| // Protocol Buffers - Google's data interchange format | 
 | // Copyright 2008 Google Inc.  All rights reserved. | 
 | // https://developers.google.com/protocol-buffers/ | 
 | // | 
 | // Redistribution and use in source and binary forms, with or without | 
 | // modification, are permitted provided that the following conditions are | 
 | // met: | 
 | // | 
 | //     * Redistributions of source code must retain the above copyright | 
 | // notice, this list of conditions and the following disclaimer. | 
 | //     * Redistributions in binary form must reproduce the above | 
 | // copyright notice, this list of conditions and the following disclaimer | 
 | // in the documentation and/or other materials provided with the | 
 | // distribution. | 
 | //     * Neither the name of Google Inc. nor the names of its | 
 | // contributors may be used to endorse or promote products derived from | 
 | // this software without specific prior written permission. | 
 | // | 
 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 |  | 
 | #import "GPBDescriptor_PackagePrivate.h" | 
 |  | 
 | #import <objc/runtime.h> | 
 |  | 
 | #import "GPBUtilities_PackagePrivate.h" | 
 | #import "GPBWireFormat.h" | 
 | #import "GPBMessage_PackagePrivate.h" | 
 |  | 
 | // Direct access is use for speed, to avoid even internally declaring things | 
 | // read/write, etc. The warning is enabled in the project to ensure code calling | 
 | // protos can turn on -Wdirect-ivar-access without issues. | 
 | #pragma clang diagnostic push | 
 | #pragma clang diagnostic ignored "-Wdirect-ivar-access" | 
 |  | 
 | // The addresses of these variables are used as keys for objc_getAssociatedObject. | 
 | static const char kTextFormatExtraValueKey = 0; | 
 | static const char kParentClassValueKey = 0; | 
 | static const char kClassNameSuffixKey = 0; | 
 |  | 
 | // Utility function to generate selectors on the fly. | 
 | static SEL SelFromStrings(const char *prefix, const char *middle, | 
 |                           const char *suffix, BOOL takesArg) { | 
 |   if (prefix == NULL && suffix == NULL && !takesArg) { | 
 |     return sel_getUid(middle); | 
 |   } | 
 |   const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0; | 
 |   const size_t middleLen = strlen(middle); | 
 |   const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0; | 
 |   size_t totalLen = | 
 |       prefixLen + middleLen + suffixLen + 1;  // include space for null on end. | 
 |   if (takesArg) { | 
 |     totalLen += 1; | 
 |   } | 
 |   char buffer[totalLen]; | 
 |   if (prefix != NULL) { | 
 |     memcpy(buffer, prefix, prefixLen); | 
 |     memcpy(buffer + prefixLen, middle, middleLen); | 
 |     buffer[prefixLen] = (char)toupper(buffer[prefixLen]); | 
 |   } else { | 
 |     memcpy(buffer, middle, middleLen); | 
 |   } | 
 |   if (suffix != NULL) { | 
 |     memcpy(buffer + prefixLen + middleLen, suffix, suffixLen); | 
 |   } | 
 |   if (takesArg) { | 
 |     buffer[totalLen - 2] = ':'; | 
 |   } | 
 |   // Always null terminate it. | 
 |   buffer[totalLen - 1] = 0; | 
 |  | 
 |   SEL result = sel_getUid(buffer); | 
 |   return result; | 
 | } | 
 |  | 
 | static NSArray *NewFieldsArrayForHasIndex(int hasIndex, | 
 |                                           NSArray *allMessageFields) | 
 |     __attribute__((ns_returns_retained)); | 
 |  | 
 | static NSArray *NewFieldsArrayForHasIndex(int hasIndex, | 
 |                                           NSArray *allMessageFields) { | 
 |   NSMutableArray *result = [[NSMutableArray alloc] init]; | 
 |   for (GPBFieldDescriptor *fieldDesc in allMessageFields) { | 
 |     if (fieldDesc->description_->hasIndex == hasIndex) { | 
 |       [result addObject:fieldDesc]; | 
 |     } | 
 |   } | 
 |   return result; | 
 | } | 
 |  | 
 | @implementation GPBDescriptor { | 
 |   Class messageClass_; | 
 |   GPBFileDescriptor *file_; | 
 |   BOOL wireFormat_; | 
 | } | 
 |  | 
 | @synthesize messageClass = messageClass_; | 
 | @synthesize fields = fields_; | 
 | @synthesize oneofs = oneofs_; | 
 | @synthesize extensionRanges = extensionRanges_; | 
 | @synthesize extensionRangesCount = extensionRangesCount_; | 
 | @synthesize file = file_; | 
 | @synthesize wireFormat = wireFormat_; | 
 |  | 
 | + (instancetype) | 
 |     allocDescriptorForClass:(Class)messageClass | 
 |                   rootClass:(Class)rootClass | 
 |                        file:(GPBFileDescriptor *)file | 
 |                      fields:(void *)fieldDescriptions | 
 |                  fieldCount:(uint32_t)fieldCount | 
 |                 storageSize:(uint32_t)storageSize | 
 |                       flags:(GPBDescriptorInitializationFlags)flags { | 
 |   // The rootClass is no longer used, but it is passed in to ensure it | 
 |   // was started up during initialization also. | 
 |   (void)rootClass; | 
 |   NSMutableArray *fields = nil; | 
 |   GPBFileSyntax syntax = file.syntax; | 
 |   BOOL fieldsIncludeDefault = | 
 |       (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; | 
 |   BOOL usesClassRefs = | 
 |       (flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0; | 
 |   BOOL proto3OptionalKnown = | 
 |       (flags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) != 0; | 
 |  | 
 |   void *desc; | 
 |   for (uint32_t i = 0; i < fieldCount; ++i) { | 
 |     if (fields == nil) { | 
 |       fields = [[NSMutableArray alloc] initWithCapacity:fieldCount]; | 
 |     } | 
 |     // Need correctly typed pointer for array indexing below to work. | 
 |     if (fieldsIncludeDefault) { | 
 |       GPBMessageFieldDescriptionWithDefault *fieldDescWithDefault = fieldDescriptions; | 
 |       desc = &(fieldDescWithDefault[i]); | 
 |     } else { | 
 |       GPBMessageFieldDescription *fieldDesc = fieldDescriptions; | 
 |       desc = &(fieldDesc[i]); | 
 |     } | 
 |     GPBFieldDescriptor *fieldDescriptor = | 
 |         [[GPBFieldDescriptor alloc] initWithFieldDescription:desc | 
 |                                              includesDefault:fieldsIncludeDefault | 
 |                                                usesClassRefs:usesClassRefs | 
 |                                          proto3OptionalKnown:proto3OptionalKnown | 
 |                                                       syntax:syntax]; | 
 |     [fields addObject:fieldDescriptor]; | 
 |     [fieldDescriptor release]; | 
 |   } | 
 |  | 
 |   BOOL wireFormat = (flags & GPBDescriptorInitializationFlag_WireFormat) != 0; | 
 |   GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass | 
 |                                                      file:file | 
 |                                                    fields:fields | 
 |                                               storageSize:storageSize | 
 |                                                wireFormat:wireFormat]; | 
 |   [fields release]; | 
 |   return descriptor; | 
 | } | 
 |  | 
 | - (instancetype)initWithClass:(Class)messageClass | 
 |                          file:(GPBFileDescriptor *)file | 
 |                        fields:(NSArray *)fields | 
 |                   storageSize:(uint32_t)storageSize | 
 |                    wireFormat:(BOOL)wireFormat { | 
 |   if ((self = [super init])) { | 
 |     messageClass_ = messageClass; | 
 |     file_ = file; | 
 |     fields_ = [fields retain]; | 
 |     storageSize_ = storageSize; | 
 |     wireFormat_ = wireFormat; | 
 |   } | 
 |   return self; | 
 | } | 
 |  | 
 | - (void)dealloc { | 
 |   [fields_ release]; | 
 |   [oneofs_ release]; | 
 |   [super dealloc]; | 
 | } | 
 |  | 
 | - (void)setupOneofs:(const char **)oneofNames | 
 |               count:(uint32_t)count | 
 |       firstHasIndex:(int32_t)firstHasIndex { | 
 |   NSCAssert(firstHasIndex < 0, @"Should always be <0"); | 
 |   NSMutableArray *oneofs = [[NSMutableArray alloc] initWithCapacity:count]; | 
 |   for (uint32_t i = 0, hasIndex = firstHasIndex; i < count; ++i, --hasIndex) { | 
 |     const char *name = oneofNames[i]; | 
 |     NSArray *fieldsForOneof = NewFieldsArrayForHasIndex(hasIndex, fields_); | 
 |     NSCAssert(fieldsForOneof.count > 0, | 
 |               @"No fields for this oneof? (%s:%d)", name, hasIndex); | 
 |     GPBOneofDescriptor *oneofDescriptor = | 
 |         [[GPBOneofDescriptor alloc] initWithName:name fields:fieldsForOneof]; | 
 |     [oneofs addObject:oneofDescriptor]; | 
 |     [oneofDescriptor release]; | 
 |     [fieldsForOneof release]; | 
 |   } | 
 |   oneofs_ = oneofs; | 
 | } | 
 |  | 
 | - (void)setupExtraTextInfo:(const char *)extraTextFormatInfo { | 
 |   // Extra info is a compile time option, so skip the work if not needed. | 
 |   if (extraTextFormatInfo) { | 
 |     NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo]; | 
 |     for (GPBFieldDescriptor *fieldDescriptor in fields_) { | 
 |       if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) { | 
 |         objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey, | 
 |                                  extraInfoValue, | 
 |                                  OBJC_ASSOCIATION_RETAIN_NONATOMIC); | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count { | 
 |   extensionRanges_ = ranges; | 
 |   extensionRangesCount_ = count; | 
 | } | 
 |  | 
 | - (void)setupContainingMessageClass:(Class)messageClass { | 
 |   objc_setAssociatedObject(self, &kParentClassValueKey, | 
 |                            messageClass, | 
 |                            OBJC_ASSOCIATION_ASSIGN); | 
 | } | 
 |  | 
 | - (void)setupContainingMessageClassName:(const char *)msgClassName { | 
 |   // Note: Only fetch the class here, can't send messages to it because | 
 |   // that could cause cycles back to this class within +initialize if | 
 |   // two messages have each other in fields (i.e. - they build a graph). | 
 |   Class clazz = objc_getClass(msgClassName); | 
 |   NSAssert(clazz, @"Class %s not defined", msgClassName); | 
 |   [self setupContainingMessageClass:clazz]; | 
 | } | 
 |  | 
 | - (void)setupMessageClassNameSuffix:(NSString *)suffix { | 
 |   if (suffix.length) { | 
 |     objc_setAssociatedObject(self, &kClassNameSuffixKey, | 
 |                              suffix, | 
 |                              OBJC_ASSOCIATION_RETAIN_NONATOMIC); | 
 |   } | 
 | } | 
 |  | 
 | - (NSString *)name { | 
 |   return NSStringFromClass(messageClass_); | 
 | } | 
 |  | 
 | - (GPBDescriptor *)containingType { | 
 |   Class parentClass = objc_getAssociatedObject(self, &kParentClassValueKey); | 
 |   return [parentClass descriptor]; | 
 | } | 
 |  | 
 | - (NSString *)fullName { | 
 |   NSString *className = NSStringFromClass(self.messageClass); | 
 |   GPBFileDescriptor *file = self.file; | 
 |   NSString *objcPrefix = file.objcPrefix; | 
 |   if (objcPrefix && ![className hasPrefix:objcPrefix]) { | 
 |     NSAssert(0, | 
 |              @"Class didn't have correct prefix? (%@ - %@)", | 
 |              className, objcPrefix); | 
 |     return nil; | 
 |   } | 
 |   GPBDescriptor *parent = self.containingType; | 
 |  | 
 |   NSString *name = nil; | 
 |   if (parent) { | 
 |     NSString *parentClassName = NSStringFromClass(parent.messageClass); | 
 |     // The generator will add _Class to avoid reserved words, drop it. | 
 |     NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey); | 
 |     if (suffix) { | 
 |       if (![parentClassName hasSuffix:suffix]) { | 
 |         NSAssert(0, | 
 |                  @"ParentMessage class didn't have correct suffix? (%@ - %@)", | 
 |                  className, suffix); | 
 |         return nil; | 
 |       } | 
 |       parentClassName = | 
 |           [parentClassName substringToIndex:(parentClassName.length - suffix.length)]; | 
 |     } | 
 |     NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"]; | 
 |     if (![className hasPrefix:parentPrefix]) { | 
 |       NSAssert(0, | 
 |                @"Class didn't have the correct parent name prefix? (%@ - %@)", | 
 |                parentPrefix, className); | 
 |       return nil; | 
 |     } | 
 |     name = [className substringFromIndex:parentPrefix.length]; | 
 |   } else { | 
 |     name = [className substringFromIndex:objcPrefix.length]; | 
 |   } | 
 |  | 
 |   // The generator will add _Class to avoid reserved words, drop it. | 
 |   NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey); | 
 |   if (suffix) { | 
 |     if (![name hasSuffix:suffix]) { | 
 |       NSAssert(0, | 
 |                @"Message class didn't have correct suffix? (%@ - %@)", | 
 |                name, suffix); | 
 |       return nil; | 
 |     } | 
 |     name = [name substringToIndex:(name.length - suffix.length)]; | 
 |   } | 
 |  | 
 |   NSString *prefix = (parent != nil ? parent.fullName : file.package); | 
 |   NSString *result; | 
 |   if (prefix.length > 0) { | 
 |     result = [NSString stringWithFormat:@"%@.%@", prefix, name]; | 
 |   } else { | 
 |     result = name; | 
 |   } | 
 |   return result; | 
 | } | 
 |  | 
 | - (id)copyWithZone:(NSZone *)zone { | 
 | #pragma unused(zone) | 
 |   return [self retain]; | 
 | } | 
 |  | 
 | - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { | 
 |   for (GPBFieldDescriptor *descriptor in fields_) { | 
 |     if (GPBFieldNumber(descriptor) == fieldNumber) { | 
 |       return descriptor; | 
 |     } | 
 |   } | 
 |   return nil; | 
 | } | 
 |  | 
 | - (GPBFieldDescriptor *)fieldWithName:(NSString *)name { | 
 |   for (GPBFieldDescriptor *descriptor in fields_) { | 
 |     if ([descriptor.name isEqual:name]) { | 
 |       return descriptor; | 
 |     } | 
 |   } | 
 |   return nil; | 
 | } | 
 |  | 
 | - (GPBOneofDescriptor *)oneofWithName:(NSString *)name { | 
 |   for (GPBOneofDescriptor *descriptor in oneofs_) { | 
 |     if ([descriptor.name isEqual:name]) { | 
 |       return descriptor; | 
 |     } | 
 |   } | 
 |   return nil; | 
 | } | 
 |  | 
 | @end | 
 |  | 
 | @implementation GPBFileDescriptor { | 
 |   NSString *package_; | 
 |   NSString *objcPrefix_; | 
 |   GPBFileSyntax syntax_; | 
 | } | 
 |  | 
 | @synthesize package = package_; | 
 | @synthesize objcPrefix = objcPrefix_; | 
 | @synthesize syntax = syntax_; | 
 |  | 
 | - (instancetype)initWithPackage:(NSString *)package | 
 |                      objcPrefix:(NSString *)objcPrefix | 
 |                          syntax:(GPBFileSyntax)syntax { | 
 |   self = [super init]; | 
 |   if (self) { | 
 |     package_ = [package copy]; | 
 |     objcPrefix_ = [objcPrefix copy]; | 
 |     syntax_ = syntax; | 
 |   } | 
 |   return self; | 
 | } | 
 |  | 
 | - (instancetype)initWithPackage:(NSString *)package | 
 |                          syntax:(GPBFileSyntax)syntax { | 
 |   self = [super init]; | 
 |   if (self) { | 
 |     package_ = [package copy]; | 
 |     syntax_ = syntax; | 
 |   } | 
 |   return self; | 
 | } | 
 |  | 
 | - (void)dealloc { | 
 |   [package_ release]; | 
 |   [objcPrefix_ release]; | 
 |   [super dealloc]; | 
 | } | 
 |  | 
 | @end | 
 |  | 
 | @implementation GPBOneofDescriptor | 
 |  | 
 | @synthesize fields = fields_; | 
 |  | 
 | - (instancetype)initWithName:(const char *)name fields:(NSArray *)fields { | 
 |   self = [super init]; | 
 |   if (self) { | 
 |     name_ = name; | 
 |     fields_ = [fields retain]; | 
 |     for (GPBFieldDescriptor *fieldDesc in fields) { | 
 |       fieldDesc->containingOneof_ = self; | 
 |     } | 
 |  | 
 |     caseSel_ = SelFromStrings(NULL, name, "OneOfCase", NO); | 
 |   } | 
 |   return self; | 
 | } | 
 |  | 
 | - (void)dealloc { | 
 |   [fields_ release]; | 
 |   [super dealloc]; | 
 | } | 
 |  | 
 | - (NSString *)name { | 
 |   return (NSString * _Nonnull)@(name_); | 
 | } | 
 |  | 
 | - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { | 
 |   for (GPBFieldDescriptor *descriptor in fields_) { | 
 |     if (GPBFieldNumber(descriptor) == fieldNumber) { | 
 |       return descriptor; | 
 |     } | 
 |   } | 
 |   return nil; | 
 | } | 
 |  | 
 | - (GPBFieldDescriptor *)fieldWithName:(NSString *)name { | 
 |   for (GPBFieldDescriptor *descriptor in fields_) { | 
 |     if ([descriptor.name isEqual:name]) { | 
 |       return descriptor; | 
 |     } | 
 |   } | 
 |   return nil; | 
 | } | 
 |  | 
 | @end | 
 |  | 
 | uint32_t GPBFieldTag(GPBFieldDescriptor *self) { | 
 |   GPBMessageFieldDescription *description = self->description_; | 
 |   GPBWireFormat format; | 
 |   if ((description->flags & GPBFieldMapKeyMask) != 0) { | 
 |     // Maps are repeated messages on the wire. | 
 |     format = GPBWireFormatForType(GPBDataTypeMessage, NO); | 
 |   } else { | 
 |     format = GPBWireFormatForType(description->dataType, | 
 |                                   ((description->flags & GPBFieldPacked) != 0)); | 
 |   } | 
 |   return GPBWireFormatMakeTag(description->number, format); | 
 | } | 
 |  | 
 | uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { | 
 |   GPBMessageFieldDescription *description = self->description_; | 
 |   NSCAssert((description->flags & GPBFieldRepeated) != 0, | 
 |             @"Only valid on repeated fields"); | 
 |   GPBWireFormat format = | 
 |       GPBWireFormatForType(description->dataType, | 
 |                            ((description->flags & GPBFieldPacked) == 0)); | 
 |   return GPBWireFormatMakeTag(description->number, format); | 
 | } | 
 |  | 
 | @implementation GPBFieldDescriptor { | 
 |   GPBGenericValue defaultValue_; | 
 |  | 
 |   // Message ivars | 
 |   Class msgClass_; | 
 |  | 
 |   // Enum ivars. | 
 |   // If protos are generated with GenerateEnumDescriptors on then it will | 
 |   // be a enumDescriptor, otherwise it will be a enumVerifier. | 
 |   union { | 
 |     GPBEnumDescriptor *enumDescriptor_; | 
 |     GPBEnumValidationFunc enumVerifier_; | 
 |   } enumHandling_; | 
 | } | 
 |  | 
 | @synthesize msgClass = msgClass_; | 
 | @synthesize containingOneof = containingOneof_; | 
 |  | 
 | - (instancetype)init { | 
 |   // Throw an exception if people attempt to not use the designated initializer. | 
 |   self = [super init]; | 
 |   if (self != nil) { | 
 |     [self doesNotRecognizeSelector:_cmd]; | 
 |     self = nil; | 
 |   } | 
 |   return self; | 
 | } | 
 |  | 
 | - (instancetype)initWithFieldDescription:(void *)description | 
 |                          includesDefault:(BOOL)includesDefault | 
 |                            usesClassRefs:(BOOL)usesClassRefs | 
 |                      proto3OptionalKnown:(BOOL)proto3OptionalKnown | 
 |                                   syntax:(GPBFileSyntax)syntax { | 
 |   if ((self = [super init])) { | 
 |     GPBMessageFieldDescription *coreDesc; | 
 |     if (includesDefault) { | 
 |       coreDesc = &(((GPBMessageFieldDescriptionWithDefault *)description)->core); | 
 |     } else { | 
 |       coreDesc = description; | 
 |     } | 
 |     description_ = coreDesc; | 
 |     getSel_ = sel_getUid(coreDesc->name); | 
 |     setSel_ = SelFromStrings("set", coreDesc->name, NULL, YES); | 
 |  | 
 |     GPBDataType dataType = coreDesc->dataType; | 
 |     BOOL isMessage = GPBDataTypeIsMessage(dataType); | 
 |     BOOL isMapOrArray = GPBFieldIsMapOrArray(self); | 
 |  | 
 |     // If proto3 optionals weren't known (i.e. generated code from an | 
 |     // older version), compute the flag for the rest of the runtime. | 
 |     if (!proto3OptionalKnown) { | 
 |       // If it was... | 
 |       //  - proto3 syntax | 
 |       //  - not repeated/map | 
 |       //  - not in a oneof (negative has index) | 
 |       //  - not a message (the flag doesn't make sense for messages) | 
 |       BOOL clearOnZero = ((syntax == GPBFileSyntaxProto3) && | 
 |                           !isMapOrArray && | 
 |                           (coreDesc->hasIndex >= 0) && | 
 |                           !isMessage); | 
 |       if (clearOnZero) { | 
 |         coreDesc->flags |= GPBFieldClearHasIvarOnZero; | 
 |       } | 
 |     } | 
 |  | 
 |     if (isMapOrArray) { | 
 |       // map<>/repeated fields get a *Count property (inplace of a has*) to | 
 |       // support checking if there are any entries without triggering | 
 |       // autocreation. | 
 |       hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO); | 
 |     } else { | 
 |       // It is a single field; it gets has/setHas selectors if... | 
 |       //  - not in a oneof (negative has index) | 
 |       //  - not clearing on zero | 
 |       if ((coreDesc->hasIndex >= 0) && | 
 |           ((coreDesc->flags & GPBFieldClearHasIvarOnZero) == 0)) { | 
 |         hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); | 
 |         setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); | 
 |       } | 
 |     } | 
 |  | 
 |     // Extra type specific data. | 
 |     if (isMessage) { | 
 |       // Note: Only fetch the class here, can't send messages to it because | 
 |       // that could cause cycles back to this class within +initialize if | 
 |       // two messages have each other in fields (i.e. - they build a graph). | 
 |       if (usesClassRefs) { | 
 |         msgClass_ = coreDesc->dataTypeSpecific.clazz; | 
 |       } else { | 
 |         // Backwards compatibility for sources generated with older protoc. | 
 |         const char *className = coreDesc->dataTypeSpecific.className; | 
 |         msgClass_ = objc_getClass(className); | 
 |         NSAssert(msgClass_, @"Class %s not defined", className); | 
 |       } | 
 |     } else if (dataType == GPBDataTypeEnum) { | 
 |       if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { | 
 |         enumHandling_.enumDescriptor_ = | 
 |             coreDesc->dataTypeSpecific.enumDescFunc(); | 
 |       } else { | 
 |         enumHandling_.enumVerifier_ = | 
 |             coreDesc->dataTypeSpecific.enumVerifier; | 
 |       } | 
 |     } | 
 |  | 
 |     // Non map<>/repeated fields can have defaults in proto2 syntax. | 
 |     if (!isMapOrArray && includesDefault) { | 
 |       defaultValue_ = ((GPBMessageFieldDescriptionWithDefault *)description)->defaultValue; | 
 |       if (dataType == GPBDataTypeBytes) { | 
 |         // Data stored as a length prefixed (network byte order) c-string in | 
 |         // descriptor structure. | 
 |         const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; | 
 |         if (bytes) { | 
 |           uint32_t length; | 
 |           memcpy(&length, bytes, sizeof(length)); | 
 |           length = ntohl(length); | 
 |           bytes += sizeof(length); | 
 |           defaultValue_.valueData = | 
 |               [[NSData alloc] initWithBytes:bytes length:length]; | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 |   return self; | 
 | } | 
 |  | 
 | - (void)dealloc { | 
 |   if (description_->dataType == GPBDataTypeBytes && | 
 |       !(description_->flags & GPBFieldRepeated)) { | 
 |     [defaultValue_.valueData release]; | 
 |   } | 
 |   [super dealloc]; | 
 | } | 
 |  | 
 | - (GPBDataType)dataType { | 
 |   return description_->dataType; | 
 | } | 
 |  | 
 | - (BOOL)hasDefaultValue { | 
 |   return (description_->flags & GPBFieldHasDefaultValue) != 0; | 
 | } | 
 |  | 
 | - (uint32_t)number { | 
 |   return description_->number; | 
 | } | 
 |  | 
 | - (NSString *)name { | 
 |   return (NSString * _Nonnull)@(description_->name); | 
 | } | 
 |  | 
 | - (BOOL)isRequired { | 
 |   return (description_->flags & GPBFieldRequired) != 0; | 
 | } | 
 |  | 
 | - (BOOL)isOptional { | 
 |   return (description_->flags & GPBFieldOptional) != 0; | 
 | } | 
 |  | 
 | - (GPBFieldType)fieldType { | 
 |   GPBFieldFlags flags = description_->flags; | 
 |   if ((flags & GPBFieldRepeated) != 0) { | 
 |     return GPBFieldTypeRepeated; | 
 |   } else if ((flags & GPBFieldMapKeyMask) != 0) { | 
 |     return GPBFieldTypeMap; | 
 |   } else { | 
 |     return GPBFieldTypeSingle; | 
 |   } | 
 | } | 
 |  | 
 | - (GPBDataType)mapKeyDataType { | 
 |   switch (description_->flags & GPBFieldMapKeyMask) { | 
 |     case GPBFieldMapKeyInt32: | 
 |       return GPBDataTypeInt32; | 
 |     case GPBFieldMapKeyInt64: | 
 |       return GPBDataTypeInt64; | 
 |     case GPBFieldMapKeyUInt32: | 
 |       return GPBDataTypeUInt32; | 
 |     case GPBFieldMapKeyUInt64: | 
 |       return GPBDataTypeUInt64; | 
 |     case GPBFieldMapKeySInt32: | 
 |       return GPBDataTypeSInt32; | 
 |     case GPBFieldMapKeySInt64: | 
 |       return GPBDataTypeSInt64; | 
 |     case GPBFieldMapKeyFixed32: | 
 |       return GPBDataTypeFixed32; | 
 |     case GPBFieldMapKeyFixed64: | 
 |       return GPBDataTypeFixed64; | 
 |     case GPBFieldMapKeySFixed32: | 
 |       return GPBDataTypeSFixed32; | 
 |     case GPBFieldMapKeySFixed64: | 
 |       return GPBDataTypeSFixed64; | 
 |     case GPBFieldMapKeyBool: | 
 |       return GPBDataTypeBool; | 
 |     case GPBFieldMapKeyString: | 
 |       return GPBDataTypeString; | 
 |  | 
 |     default: | 
 |       NSAssert(0, @"Not a map type"); | 
 |       return GPBDataTypeInt32;  // For lack of anything better. | 
 |   } | 
 | } | 
 |  | 
 | - (BOOL)isPackable { | 
 |   return (description_->flags & GPBFieldPacked) != 0; | 
 | } | 
 |  | 
 | - (BOOL)isValidEnumValue:(int32_t)value { | 
 |   NSAssert(description_->dataType == GPBDataTypeEnum, | 
 |            @"Field Must be of type GPBDataTypeEnum"); | 
 |   if (description_->flags & GPBFieldHasEnumDescriptor) { | 
 |     return enumHandling_.enumDescriptor_.enumVerifier(value); | 
 |   } else { | 
 |     return enumHandling_.enumVerifier_(value); | 
 |   } | 
 | } | 
 |  | 
 | - (GPBEnumDescriptor *)enumDescriptor { | 
 |   if (description_->flags & GPBFieldHasEnumDescriptor) { | 
 |     return enumHandling_.enumDescriptor_; | 
 |   } else { | 
 |     return nil; | 
 |   } | 
 | } | 
 |  | 
 | - (GPBGenericValue)defaultValue { | 
 |   // Depends on the fact that defaultValue_ is initialized either to "0/nil" or | 
 |   // to an actual defaultValue in our initializer. | 
 |   GPBGenericValue value = defaultValue_; | 
 |  | 
 |   if (!(description_->flags & GPBFieldRepeated)) { | 
 |     // We special handle data and strings. If they are nil, we replace them | 
 |     // with empty string/empty data. | 
 |     GPBDataType type = description_->dataType; | 
 |     if (type == GPBDataTypeBytes && value.valueData == nil) { | 
 |       value.valueData = GPBEmptyNSData(); | 
 |     } else if (type == GPBDataTypeString && value.valueString == nil) { | 
 |       value.valueString = @""; | 
 |     } | 
 |   } | 
 |   return value; | 
 | } | 
 |  | 
 | - (NSString *)textFormatName { | 
 |   if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) { | 
 |     NSValue *extraInfoValue = | 
 |         objc_getAssociatedObject(self, &kTextFormatExtraValueKey); | 
 |     // Support can be left out at generation time. | 
 |     if (!extraInfoValue) { | 
 |       return nil; | 
 |     } | 
 |     const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue]; | 
 |     return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self), | 
 |                                    self.name); | 
 |   } | 
 |  | 
 |   // The logic here has to match SetCommonFieldVariables() from | 
 |   // objectivec_field.cc in the proto compiler. | 
 |   NSString *name = self.name; | 
 |   NSUInteger len = [name length]; | 
 |  | 
 |   // Remove the "_p" added to reserved names. | 
 |   if ([name hasSuffix:@"_p"]) { | 
 |     name = [name substringToIndex:(len - 2)]; | 
 |     len = [name length]; | 
 |   } | 
 |  | 
 |   // Remove "Array" from the end for repeated fields. | 
 |   if (((description_->flags & GPBFieldRepeated) != 0) && | 
 |       [name hasSuffix:@"Array"]) { | 
 |     name = [name substringToIndex:(len - 5)]; | 
 |     len = [name length]; | 
 |   } | 
 |  | 
 |   // Groups vs. other fields. | 
 |   if (description_->dataType == GPBDataTypeGroup) { | 
 |     // Just capitalize the first letter. | 
 |     unichar firstChar = [name characterAtIndex:0]; | 
 |     if (firstChar >= 'a' && firstChar <= 'z') { | 
 |       NSString *firstCharString = | 
 |           [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')]; | 
 |       NSString *result = | 
 |           [name stringByReplacingCharactersInRange:NSMakeRange(0, 1) | 
 |                                         withString:firstCharString]; | 
 |       return result; | 
 |     } | 
 |     return name; | 
 |  | 
 |   } else { | 
 |     // Undo the CamelCase. | 
 |     NSMutableString *result = [NSMutableString stringWithCapacity:len]; | 
 |     for (uint32_t i = 0; i < len; i++) { | 
 |       unichar c = [name characterAtIndex:i]; | 
 |       if (c >= 'A' && c <= 'Z') { | 
 |         if (i > 0) { | 
 |           [result appendFormat:@"_%C", (unichar)(c - 'A' + 'a')]; | 
 |         } else { | 
 |           [result appendFormat:@"%C", c]; | 
 |         } | 
 |       } else { | 
 |         [result appendFormat:@"%C", c]; | 
 |       } | 
 |     } | 
 |     return result; | 
 |   } | 
 | } | 
 |  | 
 | @end | 
 |  | 
 | @implementation GPBEnumDescriptor { | 
 |   NSString *name_; | 
 |   // valueNames_ is a single c string with all of the value names appended | 
 |   // together, each null terminated.  -calcValueNameOffsets fills in | 
 |   // nameOffsets_ with the offsets to allow quicker access to the individual | 
 |   // names. | 
 |   const char *valueNames_; | 
 |   const int32_t *values_; | 
 |   GPBEnumValidationFunc enumVerifier_; | 
 |   const uint8_t *extraTextFormatInfo_; | 
 |   uint32_t *nameOffsets_; | 
 |   uint32_t valueCount_; | 
 | } | 
 |  | 
 | @synthesize name = name_; | 
 | @synthesize enumVerifier = enumVerifier_; | 
 |  | 
 | + (instancetype) | 
 |     allocDescriptorForName:(NSString *)name | 
 |                 valueNames:(const char *)valueNames | 
 |                     values:(const int32_t *)values | 
 |                      count:(uint32_t)valueCount | 
 |               enumVerifier:(GPBEnumValidationFunc)enumVerifier { | 
 |   GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name | 
 |                                                   valueNames:valueNames | 
 |                                                       values:values | 
 |                                                        count:valueCount | 
 |                                                 enumVerifier:enumVerifier]; | 
 |   return descriptor; | 
 | } | 
 |  | 
 | + (instancetype) | 
 |     allocDescriptorForName:(NSString *)name | 
 |                 valueNames:(const char *)valueNames | 
 |                     values:(const int32_t *)values | 
 |                      count:(uint32_t)valueCount | 
 |               enumVerifier:(GPBEnumValidationFunc)enumVerifier | 
 |        extraTextFormatInfo:(const char *)extraTextFormatInfo { | 
 |   // Call the common case. | 
 |   GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name | 
 |                                                     valueNames:valueNames | 
 |                                                         values:values | 
 |                                                          count:valueCount | 
 |                                                   enumVerifier:enumVerifier]; | 
 |   // Set the extra info. | 
 |   descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo; | 
 |   return descriptor; | 
 | } | 
 |  | 
 | - (instancetype)initWithName:(NSString *)name | 
 |                   valueNames:(const char *)valueNames | 
 |                       values:(const int32_t *)values | 
 |                        count:(uint32_t)valueCount | 
 |                 enumVerifier:(GPBEnumValidationFunc)enumVerifier { | 
 |   if ((self = [super init])) { | 
 |     name_ = [name copy]; | 
 |     valueNames_ = valueNames; | 
 |     values_ = values; | 
 |     valueCount_ = valueCount; | 
 |     enumVerifier_ = enumVerifier; | 
 |   } | 
 |   return self; | 
 | } | 
 |  | 
 | - (void)dealloc { | 
 |   [name_ release]; | 
 |   if (nameOffsets_) free(nameOffsets_); | 
 |   [super dealloc]; | 
 | } | 
 |  | 
 | - (void)calcValueNameOffsets { | 
 |   @synchronized(self) { | 
 |     if (nameOffsets_ != NULL) { | 
 |       return; | 
 |     } | 
 |     uint32_t *offsets = malloc(valueCount_ * sizeof(uint32_t)); | 
 |     if (!offsets) return; | 
 |     const char *scan = valueNames_; | 
 |     for (uint32_t i = 0; i < valueCount_; ++i) { | 
 |       offsets[i] = (uint32_t)(scan - valueNames_); | 
 |       while (*scan != '\0') ++scan; | 
 |       ++scan;  // Step over the null. | 
 |     } | 
 |     nameOffsets_ = offsets; | 
 |   } | 
 | } | 
 |  | 
 | - (NSString *)enumNameForValue:(int32_t)number { | 
 |   for (uint32_t i = 0; i < valueCount_; ++i) { | 
 |     if (values_[i] == number) { | 
 |       return [self getEnumNameForIndex:i]; | 
 |     } | 
 |   } | 
 |   return nil; | 
 | } | 
 |  | 
 | - (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name { | 
 |   // Must have the prefix. | 
 |   NSUInteger prefixLen = name_.length + 1; | 
 |   if ((name.length <= prefixLen) || ![name hasPrefix:name_] || | 
 |       ([name characterAtIndex:prefixLen - 1] != '_')) { | 
 |     return NO; | 
 |   } | 
 |  | 
 |   // Skip over the prefix. | 
 |   const char *nameAsCStr = [name UTF8String]; | 
 |   nameAsCStr += prefixLen; | 
 |  | 
 |   if (nameOffsets_ == NULL) [self calcValueNameOffsets]; | 
 |   if (nameOffsets_ == NULL) return NO; | 
 |  | 
 |   // Find it. | 
 |   for (uint32_t i = 0; i < valueCount_; ++i) { | 
 |     const char *valueName = valueNames_ + nameOffsets_[i]; | 
 |     if (strcmp(nameAsCStr, valueName) == 0) { | 
 |       if (outValue) { | 
 |         *outValue = values_[i]; | 
 |       } | 
 |       return YES; | 
 |     } | 
 |   } | 
 |   return NO; | 
 | } | 
 |  | 
 | - (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName { | 
 |     if (nameOffsets_ == NULL) [self calcValueNameOffsets]; | 
 |     if (nameOffsets_ == NULL) return NO; | 
 |  | 
 |     for (uint32_t i = 0; i < valueCount_; ++i) { | 
 |         NSString *valueTextFormatName = [self getEnumTextFormatNameForIndex:i]; | 
 |         if ([valueTextFormatName isEqual:textFormatName]) { | 
 |             if (outValue) { | 
 |                 *outValue = values_[i]; | 
 |             } | 
 |             return YES; | 
 |         } | 
 |     } | 
 |     return NO; | 
 | } | 
 |  | 
 | - (NSString *)textFormatNameForValue:(int32_t)number { | 
 |   // Find the EnumValue descriptor and its index. | 
 |   BOOL foundIt = NO; | 
 |   uint32_t valueDescriptorIndex; | 
 |   for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_; | 
 |        ++valueDescriptorIndex) { | 
 |     if (values_[valueDescriptorIndex] == number) { | 
 |       foundIt = YES; | 
 |       break; | 
 |     } | 
 |   } | 
 |  | 
 |   if (!foundIt) { | 
 |     return nil; | 
 |   } | 
 |   return [self getEnumTextFormatNameForIndex:valueDescriptorIndex]; | 
 | } | 
 |  | 
 | - (uint32_t)enumNameCount { | 
 |   return valueCount_; | 
 | } | 
 |  | 
 | - (NSString *)getEnumNameForIndex:(uint32_t)index { | 
 |   if (nameOffsets_ == NULL) [self calcValueNameOffsets]; | 
 |   if (nameOffsets_ == NULL) return nil; | 
 |  | 
 |   if (index >= valueCount_) { | 
 |     return nil; | 
 |   } | 
 |   const char *valueName = valueNames_ + nameOffsets_[index]; | 
 |   NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName]; | 
 |   return fullName; | 
 | } | 
 |  | 
 | - (NSString *)getEnumTextFormatNameForIndex:(uint32_t)index { | 
 |   if (nameOffsets_ == NULL) [self calcValueNameOffsets]; | 
 |   if (nameOffsets_ == NULL) return nil; | 
 |  | 
 |   if (index >= valueCount_) { | 
 |     return nil; | 
 |   } | 
 |   NSString *result = nil; | 
 |   // Naming adds an underscore between enum name and value name, skip that also. | 
 |   const char *valueName = valueNames_ + nameOffsets_[index]; | 
 |   NSString *shortName = @(valueName); | 
 |  | 
 |   // See if it is in the map of special format handling. | 
 |   if (extraTextFormatInfo_) { | 
 |     result = GPBDecodeTextFormatName(extraTextFormatInfo_, | 
 |                                      (int32_t)index, shortName); | 
 |   } | 
 |   // Logic here needs to match what objectivec_enum.cc does in the proto | 
 |   // compiler. | 
 |   if (result == nil) { | 
 |     NSUInteger len = [shortName length]; | 
 |     NSMutableString *worker = [NSMutableString stringWithCapacity:len]; | 
 |     for (NSUInteger i = 0; i < len; i++) { | 
 |       unichar c = [shortName characterAtIndex:i]; | 
 |       if (i > 0 && c >= 'A' && c <= 'Z') { | 
 |         [worker appendString:@"_"]; | 
 |       } | 
 |       [worker appendFormat:@"%c", toupper((char)c)]; | 
 |     } | 
 |     result = worker; | 
 |   } | 
 |   return result; | 
 | } | 
 |  | 
 | @end | 
 |  | 
 | @implementation GPBExtensionDescriptor { | 
 |   GPBGenericValue defaultValue_; | 
 | } | 
 |  | 
 | - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc | 
 |                                usesClassRefs:(BOOL)usesClassRefs { | 
 |   if ((self = [super init])) { | 
 |     description_ = desc; | 
 |     if (!usesClassRefs) { | 
 |       // Legacy without class ref support. | 
 |       const char *className = description_->messageOrGroupClass.name; | 
 |       if (className) { | 
 |         Class clazz = objc_lookUpClass(className); | 
 |         NSAssert(clazz != Nil, @"Class %s not defined", className); | 
 |         description_->messageOrGroupClass.clazz = clazz; | 
 |       } | 
 |  | 
 |       const char *extendedClassName = description_->extendedClass.name; | 
 |       if (extendedClassName) { | 
 |         Class clazz = objc_lookUpClass(extendedClassName); | 
 |         NSAssert(clazz, @"Class %s not defined", extendedClassName); | 
 |         description_->extendedClass.clazz = clazz; | 
 |       } | 
 |     } | 
 |  | 
 |     GPBDataType type = description_->dataType; | 
 |     if (type == GPBDataTypeBytes) { | 
 |       // Data stored as a length prefixed c-string in descriptor records. | 
 |       const uint8_t *bytes = | 
 |           (const uint8_t *)description_->defaultValue.valueData; | 
 |       if (bytes) { | 
 |         uint32_t length; | 
 |         memcpy(&length, bytes, sizeof(length)); | 
 |         // The length is stored in network byte order. | 
 |         length = ntohl(length); | 
 |         bytes += sizeof(length); | 
 |         defaultValue_.valueData = | 
 |             [[NSData alloc] initWithBytes:bytes length:length]; | 
 |       } | 
 |     } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) { | 
 |       // The default is looked up in -defaultValue instead since extensions | 
 |       // aren't common, we avoid the hit startup hit and it avoid initialization | 
 |       // order issues. | 
 |     } else { | 
 |       defaultValue_ = description_->defaultValue; | 
 |     } | 
 |   } | 
 |   return self; | 
 | } | 
 |  | 
 | - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc { | 
 |   return [self initWithExtensionDescription:desc usesClassRefs:NO]; | 
 | } | 
 |  | 
 | - (void)dealloc { | 
 |   if ((description_->dataType == GPBDataTypeBytes) && | 
 |       !GPBExtensionIsRepeated(description_)) { | 
 |     [defaultValue_.valueData release]; | 
 |   } | 
 |   [super dealloc]; | 
 | } | 
 |  | 
 | - (instancetype)copyWithZone:(NSZone *)zone { | 
 | #pragma unused(zone) | 
 |   // Immutable. | 
 |   return [self retain]; | 
 | } | 
 |  | 
 | - (NSString *)singletonName { | 
 |   return (NSString * _Nonnull)@(description_->singletonName); | 
 | } | 
 |  | 
 | - (const char *)singletonNameC { | 
 |   return description_->singletonName; | 
 | } | 
 |  | 
 | - (uint32_t)fieldNumber { | 
 |   return description_->fieldNumber; | 
 | } | 
 |  | 
 | - (GPBDataType)dataType { | 
 |   return description_->dataType; | 
 | } | 
 |  | 
 | - (GPBWireFormat)wireType { | 
 |   return GPBWireFormatForType(description_->dataType, | 
 |                               GPBExtensionIsPacked(description_)); | 
 | } | 
 |  | 
 | - (GPBWireFormat)alternateWireType { | 
 |   NSAssert(GPBExtensionIsRepeated(description_), | 
 |            @"Only valid on repeated extensions"); | 
 |   return GPBWireFormatForType(description_->dataType, | 
 |                               !GPBExtensionIsPacked(description_)); | 
 | } | 
 |  | 
 | - (BOOL)isRepeated { | 
 |   return GPBExtensionIsRepeated(description_); | 
 | } | 
 |  | 
 | - (BOOL)isPackable { | 
 |   return GPBExtensionIsPacked(description_); | 
 | } | 
 |  | 
 | - (Class)msgClass { | 
 |   return description_->messageOrGroupClass.clazz; | 
 | } | 
 |  | 
 | - (Class)containingMessageClass { | 
 |   return description_->extendedClass.clazz; | 
 | } | 
 |  | 
 | - (GPBEnumDescriptor *)enumDescriptor { | 
 |   if (description_->dataType == GPBDataTypeEnum) { | 
 |     GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc(); | 
 |     return enumDescriptor; | 
 |   } | 
 |   return nil; | 
 | } | 
 |  | 
 | - (id)defaultValue { | 
 |   if (GPBExtensionIsRepeated(description_)) { | 
 |     return nil; | 
 |   } | 
 |  | 
 |   switch (description_->dataType) { | 
 |     case GPBDataTypeBool: | 
 |       return @(defaultValue_.valueBool); | 
 |     case GPBDataTypeFloat: | 
 |       return @(defaultValue_.valueFloat); | 
 |     case GPBDataTypeDouble: | 
 |       return @(defaultValue_.valueDouble); | 
 |     case GPBDataTypeInt32: | 
 |     case GPBDataTypeSInt32: | 
 |     case GPBDataTypeEnum: | 
 |     case GPBDataTypeSFixed32: | 
 |       return @(defaultValue_.valueInt32); | 
 |     case GPBDataTypeInt64: | 
 |     case GPBDataTypeSInt64: | 
 |     case GPBDataTypeSFixed64: | 
 |       return @(defaultValue_.valueInt64); | 
 |     case GPBDataTypeUInt32: | 
 |     case GPBDataTypeFixed32: | 
 |       return @(defaultValue_.valueUInt32); | 
 |     case GPBDataTypeUInt64: | 
 |     case GPBDataTypeFixed64: | 
 |       return @(defaultValue_.valueUInt64); | 
 |     case GPBDataTypeBytes: | 
 |       // Like message fields, the default is zero length data. | 
 |       return (defaultValue_.valueData ? defaultValue_.valueData | 
 |                                       : GPBEmptyNSData()); | 
 |     case GPBDataTypeString: | 
 |       // Like message fields, the default is zero length string. | 
 |       return (defaultValue_.valueString ? defaultValue_.valueString : @""); | 
 |     case GPBDataTypeGroup: | 
 |     case GPBDataTypeMessage: | 
 |       return nil; | 
 |   } | 
 | } | 
 |  | 
 | - (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other { | 
 |   int32_t selfNumber = description_->fieldNumber; | 
 |   int32_t otherNumber = other->description_->fieldNumber; | 
 |   if (selfNumber < otherNumber) { | 
 |     return NSOrderedAscending; | 
 |   } else if (selfNumber == otherNumber) { | 
 |     return NSOrderedSame; | 
 |   } else { | 
 |     return NSOrderedDescending; | 
 |   } | 
 | } | 
 |  | 
 | @end | 
 |  | 
 | #pragma clang diagnostic pop |