|  | // 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 |