blob: a6840f219d7b1c2cbf87664eac07b7b481f1ee34 [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2025 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#import <stdatomic.h>
#import "GPBDescriptor_PackagePrivate.h"
#import "GPBExtensionRegistry.h"
#import "GPBMessage.h"
#import "GPBProtocolBuffers_RuntimeSupport.h"
#import "GPBRootObject_PackagePrivate.h"
#import "GPBTestUtilities.h"
#if GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION > 40311
#error "Time to remove this test."
#else
@interface Message40311FormatTest : GPBTestCase
@end
// clang-format off
// NOLINTBEGIN
// -------------------------------------------------------------------------------------------------
//
// This is extracted from generated code with the 40311 format for the following proto:
//
// syntax = "proto2";
//
// enum Enum40311 {
// FOO = 0;
// BAR = 1;
// }
//
// message Message40311 {
// message SubMessage {
// optional int32 x = 1;
// }
// enum SubEnum {
// SUB_FOO = 0;
// SUB_BAR = 1;
// }
// optional string name = 1;
// optional Enum40311 value = 2;
// repeated string names = 11;
// repeated Enum40311 values = 12;
// optional SubMessage sub_m = 20;
// optional SubEnum sub_e = 21;
// extensions 100 to max;
// }
//
// extend Message40311 {
// optional Message40311 other_m = 100;
// optional Enum40311 other_e = 101;
// repeated Message40311 other_ms = 110;
// repeated Enum40311 other_es = 111;
// }
//
// -------------------------------------------------------------------------------------------------
@class Message40311_SubMessage;
NS_ASSUME_NONNULL_BEGIN
typedef GPB_ENUM(Enum40311) {
Enum40311_Foo = 0,
Enum40311_Bar = 1,
};
GPBEnumDescriptor *Enum40311_EnumDescriptor(void);
BOOL Enum40311_IsValidValue(int32_t value);
#pragma mark - Enum Message40311_SubEnum
typedef GPB_ENUM(Message40311_SubEnum) {
Message40311_SubEnum_SubFoo = 0,
Message40311_SubEnum_SubBar = 1,
};
GPBEnumDescriptor *Message40311_SubEnum_EnumDescriptor(void);
BOOL Message40311_SubEnum_IsValidValue(int32_t value);
GPB_FINAL @interface Test40311Root : GPBRootObject
@end
@interface Test40311Root (DynamicMethods)
+ (GPBExtensionDescriptor *)otherM;
+ (GPBExtensionDescriptor *)otherE;
+ (GPBExtensionDescriptor *)otherMs;
+ (GPBExtensionDescriptor *)otherEs;
@end
typedef GPB_ENUM(Message40311_FieldNumber) {
Message40311_FieldNumber_Name = 1,
Message40311_FieldNumber_Value = 2,
Message40311_FieldNumber_NamesArray = 11,
Message40311_FieldNumber_ValuesArray = 12,
Message40311_FieldNumber_SubM = 20,
Message40311_FieldNumber_SubE = 21,
};
GPB_FINAL @interface Message40311 : GPBMessage
@property(nonatomic, readwrite, copy, null_resettable) NSString *name;
@property(nonatomic, readwrite) BOOL hasName;
@property(nonatomic, readwrite) Enum40311 value;
@property(nonatomic, readwrite) BOOL hasValue;
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *namesArray;
@property(nonatomic, readonly) NSUInteger namesArray_Count;
@property(nonatomic, readwrite, strong, null_resettable) GPBEnumArray *valuesArray;
@property(nonatomic, readonly) NSUInteger valuesArray_Count;
@property(nonatomic, readwrite, strong, null_resettable) Message40311_SubMessage *subM;
@property(nonatomic, readwrite) BOOL hasSubM;
@property(nonatomic, readwrite) Message40311_SubEnum subE;
@property(nonatomic, readwrite) BOOL hasSubE;
@end
typedef GPB_ENUM(Message40311_SubMessage_FieldNumber) {
Message40311_SubMessage_FieldNumber_X = 1,
};
GPB_FINAL @interface Message40311_SubMessage : GPBMessage
@property(nonatomic, readwrite) int32_t x;
@property(nonatomic, readwrite) BOOL hasX;
@end
NS_ASSUME_NONNULL_END
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
GPBObjCClassDeclaration(Message40311);
GPBObjCClassDeclaration(Message40311_SubMessage);
@implementation Test40311Root
+ (GPBExtensionRegistry*)extensionRegistry {
// This is called by +initialize so there is no need to worry
// about thread safety and initialization of registry.
static GPBExtensionRegistry* registry = nil;
if (!registry) {
registry = [[GPBExtensionRegistry alloc] init];
static GPBExtensionDescription descriptions[] = {
{
.defaultValue.valueMessage = nil,
.singletonName = GPBStringifySymbol(Test40311Root) "_otherM",
.extendedClass.clazz = GPBObjCClass(Message40311),
.messageOrGroupClass.clazz = GPBObjCClass(Message40311),
.enumDescriptorFunc = NULL,
.fieldNumber = 100,
.dataType = GPBDataTypeMessage,
.options = GPBExtensionNone,
},
{
.defaultValue.valueEnum = Enum40311_Foo,
.singletonName = GPBStringifySymbol(Test40311Root) "_otherE",
.extendedClass.clazz = GPBObjCClass(Message40311),
.messageOrGroupClass.clazz = Nil,
.enumDescriptorFunc = Enum40311_EnumDescriptor,
.fieldNumber = 101,
.dataType = GPBDataTypeEnum,
.options = GPBExtensionNone,
},
{
.defaultValue.valueMessage = nil,
.singletonName = GPBStringifySymbol(Test40311Root) "_otherMs",
.extendedClass.clazz = GPBObjCClass(Message40311),
.messageOrGroupClass.clazz = GPBObjCClass(Message40311),
.enumDescriptorFunc = NULL,
.fieldNumber = 110,
.dataType = GPBDataTypeMessage,
.options = GPBExtensionRepeated,
},
{
.defaultValue.valueMessage = nil,
.singletonName = GPBStringifySymbol(Test40311Root) "_otherEs",
.extendedClass.clazz = GPBObjCClass(Message40311),
.messageOrGroupClass.clazz = Nil,
.enumDescriptorFunc = Enum40311_EnumDescriptor,
.fieldNumber = 111,
.dataType = GPBDataTypeEnum,
.options = GPBExtensionRepeated,
},
};
for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {
GPBExtensionDescriptor *extension =
[[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]
runtimeSupport:&GOOGLE_PROTOBUF_OBJC_EXPECTED_GENCODE_VERSION_40311];
[registry addExtension:extension];
[self globallyRegisterExtension:extension];
[extension release];
}
// None of the imports (direct or indirect) defined extensions, so no need to add
// them to this registry.
}
return registry;
}
@end
static GPBFilePackageAndPrefix Test40311Root_FileDescription = {
.package = NULL,
.prefix = NULL
};
GPBEnumDescriptor *Enum40311_EnumDescriptor(void) {
static _Atomic(GPBEnumDescriptor*) descriptor = nil;
if (!descriptor) {
static const char *valueNames =
"Foo\000Bar\000";
static const int32_t values[] = {
Enum40311_Foo,
Enum40311_Bar,
};
GPBEnumDescriptor *worker =
[GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(Enum40311)
runtimeSupport:&GOOGLE_PROTOBUF_OBJC_EXPECTED_GENCODE_VERSION_40311
valueNames:valueNames
values:values
count:(uint32_t)(sizeof(values) / sizeof(int32_t))
enumVerifier:Enum40311_IsValidValue
flags:GPBEnumDescriptorInitializationFlag_IsClosed];
GPBEnumDescriptor *expected = nil;
if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {
[worker release];
}
}
return descriptor;
}
BOOL Enum40311_IsValidValue(int32_t value__) {
switch (value__) {
case Enum40311_Foo:
case Enum40311_Bar:
return YES;
default:
return NO;
}
}
GPBEnumDescriptor *Message40311_SubEnum_EnumDescriptor(void) {
static _Atomic(GPBEnumDescriptor*) descriptor = nil;
if (!descriptor) {
static const char *valueNames =
"SubFoo\000SubBar\000";
static const int32_t values[] = {
Message40311_SubEnum_SubFoo,
Message40311_SubEnum_SubBar,
};
GPBEnumDescriptor *worker =
[GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(Message40311_SubEnum)
runtimeSupport:&GOOGLE_PROTOBUF_OBJC_EXPECTED_GENCODE_VERSION_40311
valueNames:valueNames
values:values
count:(uint32_t)(sizeof(values) / sizeof(int32_t))
enumVerifier:Message40311_SubEnum_IsValidValue
flags:GPBEnumDescriptorInitializationFlag_IsClosed];
GPBEnumDescriptor *expected = nil;
if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {
[worker release];
}
}
return descriptor;
}
BOOL Message40311_SubEnum_IsValidValue(int32_t value__) {
switch (value__) {
case Message40311_SubEnum_SubFoo:
case Message40311_SubEnum_SubBar:
return YES;
default:
return NO;
}
}
@implementation Message40311
@dynamic hasName, name;
@dynamic hasValue, value;
@dynamic namesArray, namesArray_Count;
@dynamic valuesArray, valuesArray_Count;
@dynamic hasSubM, subM;
@dynamic hasSubE, subE;
typedef struct Message40311__storage_ {
uint32_t _has_storage_[1];
Enum40311 value;
Message40311_SubEnum subE;
NSString *name;
NSMutableArray *namesArray;
GPBEnumArray *valuesArray;
Message40311_SubMessage *subM;
} Message40311__storage_;
+ (GPBDescriptor *)descriptor {
static GPBDescriptor *descriptor = nil;
if (!descriptor) {
static GPBMessageFieldDescription fields[] = {
{
.name = "name",
.dataTypeSpecific.clazz = Nil,
.number = Message40311_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(Message40311__storage_, name),
.flags = GPBFieldNone,
.dataType = GPBDataTypeString,
},
{
.name = "value",
.dataTypeSpecific.enumDescFunc = Enum40311_EnumDescriptor,
.number = Message40311_FieldNumber_Value,
.hasIndex = 1,
.offset = (uint32_t)offsetof(Message40311__storage_, value),
.flags = GPBFieldNone,
.dataType = GPBDataTypeEnum,
},
{
.name = "namesArray",
.dataTypeSpecific.clazz = Nil,
.number = Message40311_FieldNumber_NamesArray,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(Message40311__storage_, namesArray),
.flags = GPBFieldRepeated,
.dataType = GPBDataTypeString,
},
{
.name = "valuesArray",
.dataTypeSpecific.enumDescFunc = Enum40311_EnumDescriptor,
.number = Message40311_FieldNumber_ValuesArray,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(Message40311__storage_, valuesArray),
.flags = GPBFieldRepeated,
.dataType = GPBDataTypeEnum,
},
{
.name = "subM",
.dataTypeSpecific.clazz = GPBObjCClass(Message40311_SubMessage),
.number = Message40311_FieldNumber_SubM,
.hasIndex = 2,
.offset = (uint32_t)offsetof(Message40311__storage_, subM),
.flags = GPBFieldNone,
.dataType = GPBDataTypeMessage,
},
{
.name = "subE",
.dataTypeSpecific.enumDescFunc = Message40311_SubEnum_EnumDescriptor,
.number = Message40311_FieldNumber_SubE,
.hasIndex = 3,
.offset = (uint32_t)offsetof(Message40311__storage_, subE),
.flags = GPBFieldNone,
.dataType = GPBDataTypeEnum,
},
};
GPBDescriptor *localDescriptor =
[GPBDescriptor allocDescriptorForClass:GPBObjCClass(Message40311)
messageName:@"Message40311"
runtimeSupport:&GOOGLE_PROTOBUF_OBJC_EXPECTED_GENCODE_VERSION_40311
fileDescription:&Test40311Root_FileDescription
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(Message40311__storage_)
flags:GPBDescriptorInitializationFlag_None];
static const GPBExtensionRange ranges[] = {
{ .start = 100, .end = 536870912 },
};
[localDescriptor setupExtensionRanges:ranges
count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
descriptor = localDescriptor;
}
return descriptor;
}
@end
@implementation Message40311_SubMessage
@dynamic hasX, x;
typedef struct Message40311_SubMessage__storage_ {
uint32_t _has_storage_[1];
int32_t x;
} Message40311_SubMessage__storage_;
// This method is threadsafe because it is initially called
// in +initialize for each subclass.
+ (GPBDescriptor *)descriptor {
static GPBDescriptor *descriptor = nil;
if (!descriptor) {
static GPBMessageFieldDescription fields[] = {
{
.name = "x",
.dataTypeSpecific.clazz = Nil,
.number = Message40311_SubMessage_FieldNumber_X,
.hasIndex = 0,
.offset = (uint32_t)offsetof(Message40311_SubMessage__storage_, x),
.flags = GPBFieldNone,
.dataType = GPBDataTypeInt32,
},
};
GPBDescriptor *localDescriptor =
[GPBDescriptor allocDescriptorForClass:GPBObjCClass(Message40311_SubMessage)
messageName:@"SubMessage"
runtimeSupport:&GOOGLE_PROTOBUF_OBJC_EXPECTED_GENCODE_VERSION_40311
fileDescription:&Test40311Root_FileDescription
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(Message40311_SubMessage__storage_)
flags:GPBDescriptorInitializationFlag_None];
[localDescriptor setupContainingMessageClass:GPBObjCClass(Message40311)];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
descriptor = localDescriptor;
}
return descriptor;
}
@end
#pragma clang diagnostic pop
// NOLINTEND
// clang-format on
// -------------------------------------------------------------------------------------------------
@implementation Message40311FormatTest
- (void)test40311MessageFormat {
// This doesn't test everything, just exists to ensure the code compiles/links and seems
// to work.
Message40311 *message = [Message40311 message];
message.name = @"foo";
message.subM.x = 123;
}
@end
#endif // GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION > 40311