| // 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 > 30007 | |
| #error "Time to remove this test." | |
| #else | |
| @interface Message30007FormatTest : GPBTestCase | |
| @end | |
| // clang-format off | |
| // NOLINTBEGIN | |
| // ------------------------------------------------------------------------------------------------- | |
| // | |
| // This is extracted from generated code with the 30007 format for the following proto: | |
| // | |
| // syntax = "proto2"; | |
| // | |
| // enum Enum30007 { | |
| // FOO = 0; | |
| // BAR = 1; | |
| // } | |
| // | |
| // message Message30007 { | |
| // message SubMessage { | |
| // optional int32 x = 1; | |
| // } | |
| // enum SubEnum { | |
| // SUB_FOO = 0; | |
| // SUB_BAR = 1; | |
| // } | |
| // optional string name = 1; | |
| // optional Enum30007 value = 2; | |
| // repeated string names = 11; | |
| // repeated Enum30007 values = 12; | |
| // optional SubMessage sub_m = 20; | |
| // optional SubEnum sub_e = 21; | |
| // extensions 100 to max; | |
| // } | |
| // | |
| // extend Message30007 { | |
| // optional Message30007 other_m = 100; | |
| // optional Enum30007 other_e = 101; | |
| // repeated Message30007 other_ms = 110; | |
| // repeated Enum30007 other_es = 111; | |
| // } | |
| // | |
| // ------------------------------------------------------------------------------------------------- | |
| @class Message30007_SubMessage; | |
| NS_ASSUME_NONNULL_BEGIN | |
| typedef GPB_ENUM(Enum30007) { | |
| Enum30007_Foo = 0, | |
| Enum30007_Bar = 1, | |
| }; | |
| GPBEnumDescriptor *Enum30007_EnumDescriptor(void); | |
| BOOL Enum30007_IsValidValue(int32_t value); | |
| typedef GPB_ENUM(Message30007_SubEnum) { | |
| Message30007_SubEnum_SubFoo = 0, | |
| Message30007_SubEnum_SubBar = 1, | |
| }; | |
| GPBEnumDescriptor *Message30007_SubEnum_EnumDescriptor(void); | |
| BOOL Message30007_SubEnum_IsValidValue(int32_t value); | |
| GPB_FINAL @interface Test30007Root : GPBRootObject | |
| @end | |
| @interface Test30007Root (DynamicMethods) | |
| + (GPBExtensionDescriptor *)otherM; | |
| + (GPBExtensionDescriptor *)otherE; | |
| + (GPBExtensionDescriptor *)otherMs; | |
| + (GPBExtensionDescriptor *)otherEs; | |
| @end | |
| typedef GPB_ENUM(Message30007_FieldNumber) { | |
| Message30007_FieldNumber_Name = 1, | |
| Message30007_FieldNumber_Value = 2, | |
| Message30007_FieldNumber_NamesArray = 11, | |
| Message30007_FieldNumber_ValuesArray = 12, | |
| Message30007_FieldNumber_SubM = 20, | |
| Message30007_FieldNumber_SubE = 21, | |
| }; | |
| GPB_FINAL @interface Message30007 : GPBMessage | |
| @property(nonatomic, readwrite, copy, null_resettable) NSString *name; | |
| @property(nonatomic, readwrite) BOOL hasName; | |
| @property(nonatomic, readwrite) Enum30007 value; | |
| @property(nonatomic, readwrite) BOOL hasValue; | |
| @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *namesArray; | |
| @property(nonatomic, readonly) NSUInteger namesArray_Count; | |
| // |valuesArray| contains |Enum30007| | |
| @property(nonatomic, readwrite, strong, null_resettable) GPBEnumArray *valuesArray; | |
| @property(nonatomic, readonly) NSUInteger valuesArray_Count; | |
| @property(nonatomic, readwrite, strong, null_resettable) Message30007_SubMessage *subM; | |
| @property(nonatomic, readwrite) BOOL hasSubM; | |
| @property(nonatomic, readwrite) Message30007_SubEnum subE; | |
| @property(nonatomic, readwrite) BOOL hasSubE; | |
| @end | |
| typedef GPB_ENUM(Message30007_SubMessage_FieldNumber) { | |
| Message30007_SubMessage_FieldNumber_X = 1, | |
| }; | |
| GPB_FINAL @interface Message30007_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(Message30007); | |
| GPBObjCClassDeclaration(Message30007_SubMessage); | |
| @implementation Test30007Root | |
| + (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) { | |
| GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); | |
| registry = [[GPBExtensionRegistry alloc] init]; | |
| static GPBExtensionDescription descriptions[] = { | |
| { | |
| .defaultValue.valueMessage = nil, | |
| .singletonName = GPBStringifySymbol(Test30007Root) "_otherM", | |
| .extendedClass.clazz = GPBObjCClass(Message30007), | |
| .messageOrGroupClass.clazz = GPBObjCClass(Message30007), | |
| .enumDescriptorFunc = NULL, | |
| .fieldNumber = 100, | |
| .dataType = GPBDataTypeMessage, | |
| .options = GPBExtensionNone, | |
| }, | |
| { | |
| .defaultValue.valueEnum = Enum30007_Foo, | |
| .singletonName = GPBStringifySymbol(Test30007Root) "_otherE", | |
| .extendedClass.clazz = GPBObjCClass(Message30007), | |
| .messageOrGroupClass.clazz = Nil, | |
| .enumDescriptorFunc = Enum30007_EnumDescriptor, | |
| .fieldNumber = 101, | |
| .dataType = GPBDataTypeEnum, | |
| .options = GPBExtensionNone, | |
| }, | |
| { | |
| .defaultValue.valueMessage = nil, | |
| .singletonName = GPBStringifySymbol(Test30007Root) "_otherMs", | |
| .extendedClass.clazz = GPBObjCClass(Message30007), | |
| .messageOrGroupClass.clazz = GPBObjCClass(Message30007), | |
| .enumDescriptorFunc = NULL, | |
| .fieldNumber = 110, | |
| .dataType = GPBDataTypeMessage, | |
| .options = GPBExtensionRepeated, | |
| }, | |
| { | |
| .defaultValue.valueMessage = nil, | |
| .singletonName = GPBStringifySymbol(Test30007Root) "_otherEs", | |
| .extendedClass.clazz = GPBObjCClass(Message30007), | |
| .messageOrGroupClass.clazz = Nil, | |
| .enumDescriptorFunc = Enum30007_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] | |
| usesClassRefs:YES]; | |
| [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 GPBFileDescription Test30007Root_FileDescription = { | |
| .package = NULL, | |
| .prefix = NULL, | |
| .syntax = GPBFileSyntaxProto2 | |
| }; | |
| GPBEnumDescriptor *Enum30007_EnumDescriptor(void) { | |
| static _Atomic(GPBEnumDescriptor*) descriptor = nil; | |
| if (!descriptor) { | |
| GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); | |
| static const char *valueNames = | |
| "Foo\000Bar\000"; | |
| static const int32_t values[] = { | |
| Enum30007_Foo, | |
| Enum30007_Bar, | |
| }; | |
| GPBEnumDescriptor *worker = | |
| [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(Enum30007) | |
| valueNames:valueNames | |
| values:values | |
| count:(uint32_t)(sizeof(values) / sizeof(int32_t)) | |
| enumVerifier:Enum30007_IsValidValue | |
| flags:GPBEnumDescriptorInitializationFlag_IsClosed]; | |
| GPBEnumDescriptor *expected = nil; | |
| if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { | |
| [worker release]; | |
| } | |
| } | |
| return descriptor; | |
| } | |
| BOOL Enum30007_IsValidValue(int32_t value__) { | |
| switch (value__) { | |
| case Enum30007_Foo: | |
| case Enum30007_Bar: | |
| return YES; | |
| default: | |
| return NO; | |
| } | |
| } | |
| GPBEnumDescriptor *Message30007_SubEnum_EnumDescriptor(void) { | |
| static _Atomic(GPBEnumDescriptor*) descriptor = nil; | |
| if (!descriptor) { | |
| GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); | |
| static const char *valueNames = | |
| "SubFoo\000SubBar\000"; | |
| static const int32_t values[] = { | |
| Message30007_SubEnum_SubFoo, | |
| Message30007_SubEnum_SubBar, | |
| }; | |
| GPBEnumDescriptor *worker = | |
| [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(Message30007_SubEnum) | |
| valueNames:valueNames | |
| values:values | |
| count:(uint32_t)(sizeof(values) / sizeof(int32_t)) | |
| enumVerifier:Message30007_SubEnum_IsValidValue | |
| flags:GPBEnumDescriptorInitializationFlag_IsClosed]; | |
| GPBEnumDescriptor *expected = nil; | |
| if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { | |
| [worker release]; | |
| } | |
| } | |
| return descriptor; | |
| } | |
| BOOL Message30007_SubEnum_IsValidValue(int32_t value__) { | |
| switch (value__) { | |
| case Message30007_SubEnum_SubFoo: | |
| case Message30007_SubEnum_SubBar: | |
| return YES; | |
| default: | |
| return NO; | |
| } | |
| } | |
| @implementation Message30007 | |
| @dynamic hasName, name; | |
| @dynamic hasValue, value; | |
| @dynamic namesArray, namesArray_Count; | |
| @dynamic valuesArray, valuesArray_Count; | |
| @dynamic hasSubM, subM; | |
| @dynamic hasSubE, subE; | |
| typedef struct Message30007__storage_ { | |
| uint32_t _has_storage_[1]; | |
| Enum30007 value; | |
| Message30007_SubEnum subE; | |
| NSString *name; | |
| NSMutableArray *namesArray; | |
| GPBEnumArray *valuesArray; | |
| Message30007_SubMessage *subM; | |
| } Message30007__storage_; | |
| + (GPBDescriptor *)descriptor { | |
| static GPBDescriptor *descriptor = nil; | |
| if (!descriptor) { | |
| GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); | |
| static GPBMessageFieldDescription fields[] = { | |
| { | |
| .name = "name", | |
| .dataTypeSpecific.clazz = Nil, | |
| .number = Message30007_FieldNumber_Name, | |
| .hasIndex = 0, | |
| .offset = (uint32_t)offsetof(Message30007__storage_, name), | |
| .flags = GPBFieldOptional, | |
| .dataType = GPBDataTypeString, | |
| }, | |
| { | |
| .name = "value", | |
| .dataTypeSpecific.enumDescFunc = Enum30007_EnumDescriptor, | |
| .number = Message30007_FieldNumber_Value, | |
| .hasIndex = 1, | |
| .offset = (uint32_t)offsetof(Message30007__storage_, value), | |
| .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClosedEnum), | |
| .dataType = GPBDataTypeEnum, | |
| }, | |
| { | |
| .name = "namesArray", | |
| .dataTypeSpecific.clazz = Nil, | |
| .number = Message30007_FieldNumber_NamesArray, | |
| .hasIndex = GPBNoHasBit, | |
| .offset = (uint32_t)offsetof(Message30007__storage_, namesArray), | |
| .flags = GPBFieldRepeated, | |
| .dataType = GPBDataTypeString, | |
| }, | |
| { | |
| .name = "valuesArray", | |
| .dataTypeSpecific.enumDescFunc = Enum30007_EnumDescriptor, | |
| .number = Message30007_FieldNumber_ValuesArray, | |
| .hasIndex = GPBNoHasBit, | |
| .offset = (uint32_t)offsetof(Message30007__storage_, valuesArray), | |
| .flags = (GPBFieldFlags)(GPBFieldRepeated | GPBFieldHasEnumDescriptor | GPBFieldClosedEnum), | |
| .dataType = GPBDataTypeEnum, | |
| }, | |
| { | |
| .name = "subM", | |
| .dataTypeSpecific.clazz = GPBObjCClass(Message30007_SubMessage), | |
| .number = Message30007_FieldNumber_SubM, | |
| .hasIndex = 2, | |
| .offset = (uint32_t)offsetof(Message30007__storage_, subM), | |
| .flags = GPBFieldOptional, | |
| .dataType = GPBDataTypeMessage, | |
| }, | |
| { | |
| .name = "subE", | |
| .dataTypeSpecific.enumDescFunc = Message30007_SubEnum_EnumDescriptor, | |
| .number = Message30007_FieldNumber_SubE, | |
| .hasIndex = 3, | |
| .offset = (uint32_t)offsetof(Message30007__storage_, subE), | |
| .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClosedEnum), | |
| .dataType = GPBDataTypeEnum, | |
| }, | |
| }; | |
| GPBDescriptor *localDescriptor = | |
| [GPBDescriptor allocDescriptorForClass:GPBObjCClass(Message30007) | |
| messageName:@"Message30007" | |
| fileDescription:&Test30007Root_FileDescription | |
| fields:fields | |
| fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) | |
| storageSize:sizeof(Message30007__storage_) | |
| flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)]; | |
| 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 Message30007_SubMessage | |
| @dynamic hasX, x; | |
| typedef struct Message30007_SubMessage__storage_ { | |
| uint32_t _has_storage_[1]; | |
| int32_t x; | |
| } Message30007_SubMessage__storage_; | |
| + (GPBDescriptor *)descriptor { | |
| static GPBDescriptor *descriptor = nil; | |
| if (!descriptor) { | |
| GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); | |
| static GPBMessageFieldDescription fields[] = { | |
| { | |
| .name = "x", | |
| .dataTypeSpecific.clazz = Nil, | |
| .number = Message30007_SubMessage_FieldNumber_X, | |
| .hasIndex = 0, | |
| .offset = (uint32_t)offsetof(Message30007_SubMessage__storage_, x), | |
| .flags = GPBFieldOptional, | |
| .dataType = GPBDataTypeInt32, | |
| }, | |
| }; | |
| GPBDescriptor *localDescriptor = | |
| [GPBDescriptor allocDescriptorForClass:GPBObjCClass(Message30007_SubMessage) | |
| messageName:@"SubMessage" | |
| fileDescription:&Test30007Root_FileDescription | |
| fields:fields | |
| fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) | |
| storageSize:sizeof(Message30007_SubMessage__storage_) | |
| flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)]; | |
| [localDescriptor setupContainingMessageClass:GPBObjCClass(Message30007)]; | |
| #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 Message30007FormatTest | |
| - (void)test30007MessageFormat { | |
| // This doesn't test everything, just exists to ensure the code compiles/links and seems | |
| // to work. | |
| Message30007 *message = [Message30007 message]; | |
| message.name = @"foo"; | |
| message.subM.x = 123; | |
| } | |
| @end | |
| #endif // GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION > 30007 |