Home | History | Annotate | Download | only in objectivec
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 #import "GPBMessage_PackagePrivate.h"
     32 
     33 #import <objc/runtime.h>
     34 #import <objc/message.h>
     35 
     36 #import "GPBArray_PackagePrivate.h"
     37 #import "GPBCodedInputStream_PackagePrivate.h"
     38 #import "GPBCodedOutputStream_PackagePrivate.h"
     39 #import "GPBDescriptor_PackagePrivate.h"
     40 #import "GPBDictionary_PackagePrivate.h"
     41 #import "GPBExtensionInternals.h"
     42 #import "GPBExtensionRegistry.h"
     43 #import "GPBRootObject_PackagePrivate.h"
     44 #import "GPBUnknownFieldSet_PackagePrivate.h"
     45 #import "GPBUtilities_PackagePrivate.h"
     46 
     47 NSString *const GPBMessageErrorDomain =
     48     GPBNSStringifySymbol(GPBMessageErrorDomain);
     49 
     50 #ifdef DEBUG
     51 NSString *const GPBExceptionMessageKey =
     52     GPBNSStringifySymbol(GPBExceptionMessage);
     53 #endif  // DEBUG
     54 
     55 static NSString *const kGPBDataCoderKey = @"GPBData";
     56 
     57 //
     58 // PLEASE REMEMBER:
     59 //
     60 // This is the base class for *all* messages generated, so any selector defined,
     61 // *public* or *private* could end up colliding with a proto message field. So
     62 // avoid using selectors that could match a property, use C functions to hide
     63 // them, etc.
     64 //
     65 
     66 @interface GPBMessage () {
     67  @package
     68   GPBUnknownFieldSet *unknownFields_;
     69   NSMutableDictionary *extensionMap_;
     70   NSMutableDictionary *autocreatedExtensionMap_;
     71 
     72   // If the object was autocreated, we remember the creator so that if we get
     73   // mutated, we can inform the creator to make our field visible.
     74   GPBMessage *autocreator_;
     75   GPBFieldDescriptor *autocreatorField_;
     76   GPBExtensionDescriptor *autocreatorExtension_;
     77 }
     78 @end
     79 
     80 static id CreateArrayForField(GPBFieldDescriptor *field,
     81                               GPBMessage *autocreator)
     82     __attribute__((ns_returns_retained));
     83 static id GetOrCreateArrayIvarWithField(GPBMessage *self,
     84                                         GPBFieldDescriptor *field,
     85                                         GPBFileSyntax syntax);
     86 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
     87 static id CreateMapForField(GPBFieldDescriptor *field,
     88                             GPBMessage *autocreator)
     89     __attribute__((ns_returns_retained));
     90 static id GetOrCreateMapIvarWithField(GPBMessage *self,
     91                                       GPBFieldDescriptor *field,
     92                                       GPBFileSyntax syntax);
     93 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
     94 static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
     95                                               NSZone *zone)
     96     __attribute__((ns_returns_retained));
     97 
     98 static NSError *MessageError(NSInteger code, NSDictionary *userInfo) {
     99   return [NSError errorWithDomain:GPBMessageErrorDomain
    100                              code:code
    101                          userInfo:userInfo];
    102 }
    103 
    104 static NSError *MessageErrorWithReason(NSInteger code, NSString *reason) {
    105   NSDictionary *userInfo = nil;
    106   if ([reason length]) {
    107     userInfo = @{ @"Reason" : reason };
    108   }
    109   return MessageError(code, userInfo);
    110 }
    111 
    112 
    113 static void CheckExtension(GPBMessage *self,
    114                            GPBExtensionDescriptor *extension) {
    115   if ([self class] != extension.containingMessageClass) {
    116     [NSException
    117          raise:NSInvalidArgumentException
    118         format:@"Extension %@ used on wrong class (%@ instead of %@)",
    119                extension.singletonName,
    120                [self class], extension.containingMessageClass];
    121   }
    122 }
    123 
    124 static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
    125                                               NSZone *zone) {
    126   if (extensionMap.count == 0) {
    127     return nil;
    128   }
    129   NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone]
    130       initWithCapacity:extensionMap.count];
    131 
    132   for (GPBExtensionDescriptor *extension in extensionMap) {
    133     id value = [extensionMap objectForKey:extension];
    134     BOOL isMessageExtension = GPBExtensionIsMessage(extension);
    135 
    136     if (extension.repeated) {
    137       if (isMessageExtension) {
    138         NSMutableArray *list =
    139             [[NSMutableArray alloc] initWithCapacity:[value count]];
    140         for (GPBMessage *listValue in value) {
    141           GPBMessage *copiedValue = [listValue copyWithZone:zone];
    142           [list addObject:copiedValue];
    143           [copiedValue release];
    144         }
    145         [result setObject:list forKey:extension];
    146         [list release];
    147       } else {
    148         NSMutableArray *copiedValue = [value mutableCopyWithZone:zone];
    149         [result setObject:copiedValue forKey:extension];
    150         [copiedValue release];
    151       }
    152     } else {
    153       if (isMessageExtension) {
    154         GPBMessage *copiedValue = [value copyWithZone:zone];
    155         [result setObject:copiedValue forKey:extension];
    156         [copiedValue release];
    157       } else {
    158         [result setObject:value forKey:extension];
    159       }
    160     }
    161   }
    162 
    163   return result;
    164 }
    165 
    166 static id CreateArrayForField(GPBFieldDescriptor *field,
    167                               GPBMessage *autocreator) {
    168   id result;
    169   GPBDataType fieldDataType = GPBGetFieldDataType(field);
    170   switch (fieldDataType) {
    171     case GPBDataTypeBool:
    172       result = [[GPBBoolArray alloc] init];
    173       break;
    174     case GPBDataTypeFixed32:
    175     case GPBDataTypeUInt32:
    176       result = [[GPBUInt32Array alloc] init];
    177       break;
    178     case GPBDataTypeInt32:
    179     case GPBDataTypeSFixed32:
    180     case GPBDataTypeSInt32:
    181       result = [[GPBInt32Array alloc] init];
    182       break;
    183     case GPBDataTypeFixed64:
    184     case GPBDataTypeUInt64:
    185       result = [[GPBUInt64Array alloc] init];
    186       break;
    187     case GPBDataTypeInt64:
    188     case GPBDataTypeSFixed64:
    189     case GPBDataTypeSInt64:
    190       result = [[GPBInt64Array alloc] init];
    191       break;
    192     case GPBDataTypeFloat:
    193       result = [[GPBFloatArray alloc] init];
    194       break;
    195     case GPBDataTypeDouble:
    196       result = [[GPBDoubleArray alloc] init];
    197       break;
    198 
    199     case GPBDataTypeEnum:
    200       result = [[GPBEnumArray alloc]
    201                   initWithValidationFunction:field.enumDescriptor.enumVerifier];
    202       break;
    203 
    204     case GPBDataTypeBytes:
    205     case GPBDataTypeGroup:
    206     case GPBDataTypeMessage:
    207     case GPBDataTypeString:
    208       if (autocreator) {
    209         result = [[GPBAutocreatedArray alloc] init];
    210       } else {
    211         result = [[NSMutableArray alloc] init];
    212       }
    213       break;
    214   }
    215 
    216   if (autocreator) {
    217     if (GPBDataTypeIsObject(fieldDataType)) {
    218       GPBAutocreatedArray *autoArray = result;
    219       autoArray->_autocreator =  autocreator;
    220     } else {
    221       GPBInt32Array *gpbArray = result;
    222       gpbArray->_autocreator = autocreator;
    223     }
    224   }
    225 
    226   return result;
    227 }
    228 
    229 static id CreateMapForField(GPBFieldDescriptor *field,
    230                             GPBMessage *autocreator) {
    231   id result;
    232   GPBDataType keyDataType = field.mapKeyDataType;
    233   GPBDataType valueDataType = GPBGetFieldDataType(field);
    234   switch (keyDataType) {
    235     case GPBDataTypeBool:
    236       switch (valueDataType) {
    237         case GPBDataTypeBool:
    238           result = [[GPBBoolBoolDictionary alloc] init];
    239           break;
    240         case GPBDataTypeFixed32:
    241         case GPBDataTypeUInt32:
    242           result = [[GPBBoolUInt32Dictionary alloc] init];
    243           break;
    244         case GPBDataTypeInt32:
    245         case GPBDataTypeSFixed32:
    246         case GPBDataTypeSInt32:
    247           result = [[GPBBoolInt32Dictionary alloc] init];
    248           break;
    249         case GPBDataTypeFixed64:
    250         case GPBDataTypeUInt64:
    251           result = [[GPBBoolUInt64Dictionary alloc] init];
    252           break;
    253         case GPBDataTypeInt64:
    254         case GPBDataTypeSFixed64:
    255         case GPBDataTypeSInt64:
    256           result = [[GPBBoolInt64Dictionary alloc] init];
    257           break;
    258         case GPBDataTypeFloat:
    259           result = [[GPBBoolFloatDictionary alloc] init];
    260           break;
    261         case GPBDataTypeDouble:
    262           result = [[GPBBoolDoubleDictionary alloc] init];
    263           break;
    264         case GPBDataTypeEnum:
    265           result = [[GPBBoolEnumDictionary alloc]
    266               initWithValidationFunction:field.enumDescriptor.enumVerifier];
    267           break;
    268         case GPBDataTypeBytes:
    269         case GPBDataTypeMessage:
    270         case GPBDataTypeString:
    271           result = [[GPBBoolObjectDictionary alloc] init];
    272           break;
    273         case GPBDataTypeGroup:
    274           NSCAssert(NO, @"shouldn't happen");
    275           return nil;
    276       }
    277       break;
    278     case GPBDataTypeFixed32:
    279     case GPBDataTypeUInt32:
    280       switch (valueDataType) {
    281         case GPBDataTypeBool:
    282           result = [[GPBUInt32BoolDictionary alloc] init];
    283           break;
    284         case GPBDataTypeFixed32:
    285         case GPBDataTypeUInt32:
    286           result = [[GPBUInt32UInt32Dictionary alloc] init];
    287           break;
    288         case GPBDataTypeInt32:
    289         case GPBDataTypeSFixed32:
    290         case GPBDataTypeSInt32:
    291           result = [[GPBUInt32Int32Dictionary alloc] init];
    292           break;
    293         case GPBDataTypeFixed64:
    294         case GPBDataTypeUInt64:
    295           result = [[GPBUInt32UInt64Dictionary alloc] init];
    296           break;
    297         case GPBDataTypeInt64:
    298         case GPBDataTypeSFixed64:
    299         case GPBDataTypeSInt64:
    300           result = [[GPBUInt32Int64Dictionary alloc] init];
    301           break;
    302         case GPBDataTypeFloat:
    303           result = [[GPBUInt32FloatDictionary alloc] init];
    304           break;
    305         case GPBDataTypeDouble:
    306           result = [[GPBUInt32DoubleDictionary alloc] init];
    307           break;
    308         case GPBDataTypeEnum:
    309           result = [[GPBUInt32EnumDictionary alloc]
    310               initWithValidationFunction:field.enumDescriptor.enumVerifier];
    311           break;
    312         case GPBDataTypeBytes:
    313         case GPBDataTypeMessage:
    314         case GPBDataTypeString:
    315           result = [[GPBUInt32ObjectDictionary alloc] init];
    316           break;
    317         case GPBDataTypeGroup:
    318           NSCAssert(NO, @"shouldn't happen");
    319           return nil;
    320       }
    321       break;
    322     case GPBDataTypeInt32:
    323     case GPBDataTypeSFixed32:
    324     case GPBDataTypeSInt32:
    325       switch (valueDataType) {
    326         case GPBDataTypeBool:
    327           result = [[GPBInt32BoolDictionary alloc] init];
    328           break;
    329         case GPBDataTypeFixed32:
    330         case GPBDataTypeUInt32:
    331           result = [[GPBInt32UInt32Dictionary alloc] init];
    332           break;
    333         case GPBDataTypeInt32:
    334         case GPBDataTypeSFixed32:
    335         case GPBDataTypeSInt32:
    336           result = [[GPBInt32Int32Dictionary alloc] init];
    337           break;
    338         case GPBDataTypeFixed64:
    339         case GPBDataTypeUInt64:
    340           result = [[GPBInt32UInt64Dictionary alloc] init];
    341           break;
    342         case GPBDataTypeInt64:
    343         case GPBDataTypeSFixed64:
    344         case GPBDataTypeSInt64:
    345           result = [[GPBInt32Int64Dictionary alloc] init];
    346           break;
    347         case GPBDataTypeFloat:
    348           result = [[GPBInt32FloatDictionary alloc] init];
    349           break;
    350         case GPBDataTypeDouble:
    351           result = [[GPBInt32DoubleDictionary alloc] init];
    352           break;
    353         case GPBDataTypeEnum:
    354           result = [[GPBInt32EnumDictionary alloc]
    355               initWithValidationFunction:field.enumDescriptor.enumVerifier];
    356           break;
    357         case GPBDataTypeBytes:
    358         case GPBDataTypeMessage:
    359         case GPBDataTypeString:
    360           result = [[GPBInt32ObjectDictionary alloc] init];
    361           break;
    362         case GPBDataTypeGroup:
    363           NSCAssert(NO, @"shouldn't happen");
    364           return nil;
    365       }
    366       break;
    367     case GPBDataTypeFixed64:
    368     case GPBDataTypeUInt64:
    369       switch (valueDataType) {
    370         case GPBDataTypeBool:
    371           result = [[GPBUInt64BoolDictionary alloc] init];
    372           break;
    373         case GPBDataTypeFixed32:
    374         case GPBDataTypeUInt32:
    375           result = [[GPBUInt64UInt32Dictionary alloc] init];
    376           break;
    377         case GPBDataTypeInt32:
    378         case GPBDataTypeSFixed32:
    379         case GPBDataTypeSInt32:
    380           result = [[GPBUInt64Int32Dictionary alloc] init];
    381           break;
    382         case GPBDataTypeFixed64:
    383         case GPBDataTypeUInt64:
    384           result = [[GPBUInt64UInt64Dictionary alloc] init];
    385           break;
    386         case GPBDataTypeInt64:
    387         case GPBDataTypeSFixed64:
    388         case GPBDataTypeSInt64:
    389           result = [[GPBUInt64Int64Dictionary alloc] init];
    390           break;
    391         case GPBDataTypeFloat:
    392           result = [[GPBUInt64FloatDictionary alloc] init];
    393           break;
    394         case GPBDataTypeDouble:
    395           result = [[GPBUInt64DoubleDictionary alloc] init];
    396           break;
    397         case GPBDataTypeEnum:
    398           result = [[GPBUInt64EnumDictionary alloc]
    399               initWithValidationFunction:field.enumDescriptor.enumVerifier];
    400           break;
    401         case GPBDataTypeBytes:
    402         case GPBDataTypeMessage:
    403         case GPBDataTypeString:
    404           result = [[GPBUInt64ObjectDictionary alloc] init];
    405           break;
    406         case GPBDataTypeGroup:
    407           NSCAssert(NO, @"shouldn't happen");
    408           return nil;
    409       }
    410       break;
    411     case GPBDataTypeInt64:
    412     case GPBDataTypeSFixed64:
    413     case GPBDataTypeSInt64:
    414       switch (valueDataType) {
    415         case GPBDataTypeBool:
    416           result = [[GPBInt64BoolDictionary alloc] init];
    417           break;
    418         case GPBDataTypeFixed32:
    419         case GPBDataTypeUInt32:
    420           result = [[GPBInt64UInt32Dictionary alloc] init];
    421           break;
    422         case GPBDataTypeInt32:
    423         case GPBDataTypeSFixed32:
    424         case GPBDataTypeSInt32:
    425           result = [[GPBInt64Int32Dictionary alloc] init];
    426           break;
    427         case GPBDataTypeFixed64:
    428         case GPBDataTypeUInt64:
    429           result = [[GPBInt64UInt64Dictionary alloc] init];
    430           break;
    431         case GPBDataTypeInt64:
    432         case GPBDataTypeSFixed64:
    433         case GPBDataTypeSInt64:
    434           result = [[GPBInt64Int64Dictionary alloc] init];
    435           break;
    436         case GPBDataTypeFloat:
    437           result = [[GPBInt64FloatDictionary alloc] init];
    438           break;
    439         case GPBDataTypeDouble:
    440           result = [[GPBInt64DoubleDictionary alloc] init];
    441           break;
    442         case GPBDataTypeEnum:
    443           result = [[GPBInt64EnumDictionary alloc]
    444               initWithValidationFunction:field.enumDescriptor.enumVerifier];
    445           break;
    446         case GPBDataTypeBytes:
    447         case GPBDataTypeMessage:
    448         case GPBDataTypeString:
    449           result = [[GPBInt64ObjectDictionary alloc] init];
    450           break;
    451         case GPBDataTypeGroup:
    452           NSCAssert(NO, @"shouldn't happen");
    453           return nil;
    454       }
    455       break;
    456     case GPBDataTypeString:
    457       switch (valueDataType) {
    458         case GPBDataTypeBool:
    459           result = [[GPBStringBoolDictionary alloc] init];
    460           break;
    461         case GPBDataTypeFixed32:
    462         case GPBDataTypeUInt32:
    463           result = [[GPBStringUInt32Dictionary alloc] init];
    464           break;
    465         case GPBDataTypeInt32:
    466         case GPBDataTypeSFixed32:
    467         case GPBDataTypeSInt32:
    468           result = [[GPBStringInt32Dictionary alloc] init];
    469           break;
    470         case GPBDataTypeFixed64:
    471         case GPBDataTypeUInt64:
    472           result = [[GPBStringUInt64Dictionary alloc] init];
    473           break;
    474         case GPBDataTypeInt64:
    475         case GPBDataTypeSFixed64:
    476         case GPBDataTypeSInt64:
    477           result = [[GPBStringInt64Dictionary alloc] init];
    478           break;
    479         case GPBDataTypeFloat:
    480           result = [[GPBStringFloatDictionary alloc] init];
    481           break;
    482         case GPBDataTypeDouble:
    483           result = [[GPBStringDoubleDictionary alloc] init];
    484           break;
    485         case GPBDataTypeEnum:
    486           result = [[GPBStringEnumDictionary alloc]
    487               initWithValidationFunction:field.enumDescriptor.enumVerifier];
    488           break;
    489         case GPBDataTypeBytes:
    490         case GPBDataTypeMessage:
    491         case GPBDataTypeString:
    492           if (autocreator) {
    493             result = [[GPBAutocreatedDictionary alloc] init];
    494           } else {
    495             result = [[NSMutableDictionary alloc] init];
    496           }
    497           break;
    498         case GPBDataTypeGroup:
    499           NSCAssert(NO, @"shouldn't happen");
    500           return nil;
    501       }
    502       break;
    503 
    504     case GPBDataTypeFloat:
    505     case GPBDataTypeDouble:
    506     case GPBDataTypeEnum:
    507     case GPBDataTypeBytes:
    508     case GPBDataTypeGroup:
    509     case GPBDataTypeMessage:
    510       NSCAssert(NO, @"shouldn't happen");
    511       return nil;
    512   }
    513 
    514   if (autocreator) {
    515     if ((keyDataType == GPBDataTypeString) &&
    516         GPBDataTypeIsObject(valueDataType)) {
    517       GPBAutocreatedDictionary *autoDict = result;
    518       autoDict->_autocreator =  autocreator;
    519     } else {
    520       GPBInt32Int32Dictionary *gpbDict = result;
    521       gpbDict->_autocreator = autocreator;
    522     }
    523   }
    524 
    525   return result;
    526 }
    527 
    528 #if !defined(__clang_analyzer__)
    529 // These functions are blocked from the analyzer because the analyzer sees the
    530 // GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map,
    531 // so use of the array/map after the call returns is flagged as a use after
    532 // free.
    533 // But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain
    534 // count be holding onto the object (it is transfering it), the object is
    535 // still valid after returning from the call.  The other way to avoid this
    536 // would be to add a -retain/-autorelease, but that would force every
    537 // repeated/map field parsed into the autorelease pool which is both a memory
    538 // and performance hit.
    539 
    540 static id GetOrCreateArrayIvarWithField(GPBMessage *self,
    541                                         GPBFieldDescriptor *field,
    542                                         GPBFileSyntax syntax) {
    543   id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    544   if (!array) {
    545     // No lock needed, this is called from places expecting to mutate
    546     // so no threading protection is needed.
    547     array = CreateArrayForField(field, nil);
    548     GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax);
    549   }
    550   return array;
    551 }
    552 
    553 // This is like GPBGetObjectIvarWithField(), but for arrays, it should
    554 // only be used to wire the method into the class.
    555 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
    556   id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    557   if (!array) {
    558     // Check again after getting the lock.
    559     GPBPrepareReadOnlySemaphore(self);
    560     dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
    561     array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    562     if (!array) {
    563       array = CreateArrayForField(field, self);
    564       GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array);
    565     }
    566     dispatch_semaphore_signal(self->readOnlySemaphore_);
    567   }
    568   return array;
    569 }
    570 
    571 static id GetOrCreateMapIvarWithField(GPBMessage *self,
    572                                       GPBFieldDescriptor *field,
    573                                       GPBFileSyntax syntax) {
    574   id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    575   if (!dict) {
    576     // No lock needed, this is called from places expecting to mutate
    577     // so no threading protection is needed.
    578     dict = CreateMapForField(field, nil);
    579     GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax);
    580   }
    581   return dict;
    582 }
    583 
    584 // This is like GPBGetObjectIvarWithField(), but for maps, it should
    585 // only be used to wire the method into the class.
    586 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
    587   id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    588   if (!dict) {
    589     // Check again after getting the lock.
    590     GPBPrepareReadOnlySemaphore(self);
    591     dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
    592     dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    593     if (!dict) {
    594       dict = CreateMapForField(field, self);
    595       GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict);
    596     }
    597     dispatch_semaphore_signal(self->readOnlySemaphore_);
    598   }
    599   return dict;
    600 }
    601 
    602 #endif  // !defined(__clang_analyzer__)
    603 
    604 GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass,
    605                                             GPBMessage *autocreator,
    606                                             GPBFieldDescriptor *field) {
    607   GPBMessage *message = [[msgClass alloc] init];
    608   message->autocreator_ = autocreator;
    609   message->autocreatorField_ = [field retain];
    610   return message;
    611 }
    612 
    613 static GPBMessage *CreateMessageWithAutocreatorForExtension(
    614     Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension)
    615     __attribute__((ns_returns_retained));
    616 
    617 static GPBMessage *CreateMessageWithAutocreatorForExtension(
    618     Class msgClass, GPBMessage *autocreator,
    619     GPBExtensionDescriptor *extension) {
    620   GPBMessage *message = [[msgClass alloc] init];
    621   message->autocreator_ = autocreator;
    622   message->autocreatorExtension_ = [extension retain];
    623   return message;
    624 }
    625 
    626 BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) {
    627   return (message->autocreator_ == parent);
    628 }
    629 
    630 void GPBBecomeVisibleToAutocreator(GPBMessage *self) {
    631   // Message objects that are implicitly created by accessing a message field
    632   // are initially not visible via the hasX selector. This method makes them
    633   // visible.
    634   if (self->autocreator_) {
    635     // This will recursively make all parent messages visible until it reaches a
    636     // super-creator that's visible.
    637     if (self->autocreatorField_) {
    638       GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax;
    639       GPBSetObjectIvarWithFieldInternal(self->autocreator_,
    640                                         self->autocreatorField_, self, syntax);
    641     } else {
    642       [self->autocreator_ setExtension:self->autocreatorExtension_ value:self];
    643     }
    644   }
    645 }
    646 
    647 void GPBAutocreatedArrayModified(GPBMessage *self, id array) {
    648   // When one of our autocreated arrays adds elements, make it visible.
    649   GPBDescriptor *descriptor = [[self class] descriptor];
    650   for (GPBFieldDescriptor *field in descriptor->fields_) {
    651     if (field.fieldType == GPBFieldTypeRepeated) {
    652       id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    653       if (curArray == array) {
    654         if (GPBFieldDataTypeIsObject(field)) {
    655           GPBAutocreatedArray *autoArray = array;
    656           autoArray->_autocreator = nil;
    657         } else {
    658           GPBInt32Array *gpbArray = array;
    659           gpbArray->_autocreator = nil;
    660         }
    661         GPBBecomeVisibleToAutocreator(self);
    662         return;
    663       }
    664     }
    665   }
    666   NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self);
    667 }
    668 
    669 void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) {
    670   // When one of our autocreated dicts adds elements, make it visible.
    671   GPBDescriptor *descriptor = [[self class] descriptor];
    672   for (GPBFieldDescriptor *field in descriptor->fields_) {
    673     if (field.fieldType == GPBFieldTypeMap) {
    674       id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    675       if (curDict == dictionary) {
    676         if ((field.mapKeyDataType == GPBDataTypeString) &&
    677             GPBFieldDataTypeIsObject(field)) {
    678           GPBAutocreatedDictionary *autoDict = dictionary;
    679           autoDict->_autocreator = nil;
    680         } else {
    681           GPBInt32Int32Dictionary *gpbDict = dictionary;
    682           gpbDict->_autocreator = nil;
    683         }
    684         GPBBecomeVisibleToAutocreator(self);
    685         return;
    686       }
    687     }
    688   }
    689   NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self);
    690 }
    691 
    692 void GPBClearMessageAutocreator(GPBMessage *self) {
    693   if ((self == nil) || !self->autocreator_) {
    694     return;
    695   }
    696 
    697 #if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
    698   // Either the autocreator must have its "has" flag set to YES, or it must be
    699   // NO and not equal to ourselves.
    700   BOOL autocreatorHas =
    701       (self->autocreatorField_
    702            ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_)
    703            : [self->autocreator_ hasExtension:self->autocreatorExtension_]);
    704   GPBMessage *autocreatorFieldValue =
    705       (self->autocreatorField_
    706            ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_,
    707                                                    self->autocreatorField_)
    708            : [self->autocreator_->autocreatedExtensionMap_
    709                  objectForKey:self->autocreatorExtension_]);
    710   NSCAssert(autocreatorHas || autocreatorFieldValue != self,
    711             @"Cannot clear autocreator because it still refers to self, self: %@.",
    712             self);
    713 
    714 #endif  // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
    715 
    716   self->autocreator_ = nil;
    717   [self->autocreatorField_ release];
    718   self->autocreatorField_ = nil;
    719   [self->autocreatorExtension_ release];
    720   self->autocreatorExtension_ = nil;
    721 }
    722 
    723 static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
    724   if (!self->unknownFields_) {
    725     self->unknownFields_ = [[GPBUnknownFieldSet alloc] init];
    726     GPBBecomeVisibleToAutocreator(self);
    727   }
    728   return self->unknownFields_;
    729 }
    730 
    731 @implementation GPBMessage
    732 
    733 + (void)initialize {
    734   Class pbMessageClass = [GPBMessage class];
    735   if ([self class] == pbMessageClass) {
    736     // This is here to start up the "base" class descriptor.
    737     [self descriptor];
    738     // Message shares extension method resolving with GPBRootObject so insure
    739     // it is started up at the same time.
    740     (void)[GPBRootObject class];
    741   } else if ([self superclass] == pbMessageClass) {
    742     // This is here to start up all the "message" subclasses. Just needs to be
    743     // done for the messages, not any of the subclasses.
    744     // This must be done in initialize to enforce thread safety of start up of
    745     // the protocol buffer library.
    746     // Note: The generated code for -descriptor calls
    747     // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject
    748     // subclass for the file.  That call chain is what ensures that *Root class
    749     // is started up to support extension resolution off the message class
    750     // (+resolveClassMethod: below) in a thread safe manner.
    751     [self descriptor];
    752   }
    753 }
    754 
    755 + (instancetype)allocWithZone:(NSZone *)zone {
    756   // Override alloc to allocate our classes with the additional storage
    757   // required for the instance variables.
    758   GPBDescriptor *descriptor = [self descriptor];
    759   return NSAllocateObject(self, descriptor->storageSize_, zone);
    760 }
    761 
    762 + (instancetype)alloc {
    763   return [self allocWithZone:nil];
    764 }
    765 
    766 + (GPBDescriptor *)descriptor {
    767   // This is thread safe because it is called from +initialize.
    768   static GPBDescriptor *descriptor = NULL;
    769   static GPBFileDescriptor *fileDescriptor = NULL;
    770   if (!descriptor) {
    771     // Use a dummy file that marks it as proto2 syntax so when used generically
    772     // it supports unknowns/etc.
    773     fileDescriptor =
    774         [[GPBFileDescriptor alloc] initWithPackage:@"internal"
    775                                             syntax:GPBFileSyntaxProto2];
    776 
    777     descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class]
    778                                               rootClass:Nil
    779                                                    file:fileDescriptor
    780                                                  fields:NULL
    781                                              fieldCount:0
    782                                             storageSize:0
    783                                                   flags:0];
    784   }
    785   return descriptor;
    786 }
    787 
    788 + (instancetype)message {
    789   return [[[self alloc] init] autorelease];
    790 }
    791 
    792 - (instancetype)init {
    793   if ((self = [super init])) {
    794     messageStorage_ = (GPBMessage_StoragePtr)(
    795         ((uint8_t *)self) + class_getInstanceSize([self class]));
    796   }
    797 
    798   return self;
    799 }
    800 
    801 - (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr {
    802   return [self initWithData:data extensionRegistry:nil error:errorPtr];
    803 }
    804 
    805 - (instancetype)initWithData:(NSData *)data
    806            extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
    807                        error:(NSError **)errorPtr {
    808   if ((self = [self init])) {
    809     @try {
    810       [self mergeFromData:data extensionRegistry:extensionRegistry];
    811       if (errorPtr) {
    812         *errorPtr = nil;
    813       }
    814     }
    815     @catch (NSException *exception) {
    816       [self release];
    817       self = nil;
    818       if (errorPtr) {
    819         *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
    820                                            exception.reason);
    821       }
    822     }
    823 #ifdef DEBUG
    824     if (self && !self.initialized) {
    825       [self release];
    826       self = nil;
    827       if (errorPtr) {
    828         *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
    829       }
    830     }
    831 #endif
    832   }
    833   return self;
    834 }
    835 
    836 - (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
    837                        extensionRegistry:
    838                            (GPBExtensionRegistry *)extensionRegistry
    839                                    error:(NSError **)errorPtr {
    840   if ((self = [self init])) {
    841     @try {
    842       [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
    843       if (errorPtr) {
    844         *errorPtr = nil;
    845       }
    846     }
    847     @catch (NSException *exception) {
    848       [self release];
    849       self = nil;
    850       if (errorPtr) {
    851         *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
    852                                            exception.reason);
    853       }
    854     }
    855 #ifdef DEBUG
    856     if (self && !self.initialized) {
    857       [self release];
    858       self = nil;
    859       if (errorPtr) {
    860         *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
    861       }
    862     }
    863 #endif
    864   }
    865   return self;
    866 }
    867 
    868 - (void)dealloc {
    869   [self internalClear:NO];
    870   NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc.");
    871   if (readOnlySemaphore_) {
    872     dispatch_release(readOnlySemaphore_);
    873   }
    874   [super dealloc];
    875 }
    876 
    877 - (void)copyFieldsInto:(GPBMessage *)message
    878                   zone:(NSZone *)zone
    879             descriptor:(GPBDescriptor *)descriptor {
    880   // Copy all the storage...
    881   memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_);
    882 
    883   GPBFileSyntax syntax = descriptor.file.syntax;
    884 
    885   // Loop over the fields doing fixup...
    886   for (GPBFieldDescriptor *field in descriptor->fields_) {
    887     if (GPBFieldIsMapOrArray(field)) {
    888       id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    889       if (value) {
    890         // We need to copy the array/map, but the catch is for message fields,
    891         // we also need to ensure all the messages as those need copying also.
    892         id newValue;
    893         if (GPBFieldDataTypeIsMessage(field)) {
    894           if (field.fieldType == GPBFieldTypeRepeated) {
    895             NSArray *existingArray = (NSArray *)value;
    896             NSMutableArray *newArray =
    897                 [[NSMutableArray alloc] initWithCapacity:existingArray.count];
    898             newValue = newArray;
    899             for (GPBMessage *msg in existingArray) {
    900               GPBMessage *copiedMsg = [msg copyWithZone:zone];
    901               [newArray addObject:copiedMsg];
    902               [copiedMsg release];
    903             }
    904           } else {
    905             if (field.mapKeyDataType == GPBDataTypeString) {
    906               // Map is an NSDictionary.
    907               NSDictionary *existingDict = value;
    908               NSMutableDictionary *newDict = [[NSMutableDictionary alloc]
    909                   initWithCapacity:existingDict.count];
    910               newValue = newDict;
    911               [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key,
    912                                                                 GPBMessage *msg,
    913                                                                 BOOL *stop) {
    914 #pragma unused(stop)
    915                 GPBMessage *copiedMsg = [msg copyWithZone:zone];
    916                 [newDict setObject:copiedMsg forKey:key];
    917                 [copiedMsg release];
    918               }];
    919             } else {
    920               // Is one of the GPB*ObjectDictionary classes.  Type doesn't
    921               // matter, just need one to invoke the selector.
    922               GPBInt32ObjectDictionary *existingDict = value;
    923               newValue = [existingDict deepCopyWithZone:zone];
    924             }
    925           }
    926         } else {
    927           // Not messages (but is a map/array)...
    928           if (field.fieldType == GPBFieldTypeRepeated) {
    929             if (GPBFieldDataTypeIsObject(field)) {
    930               // NSArray
    931               newValue = [value mutableCopyWithZone:zone];
    932             } else {
    933               // GPB*Array
    934               newValue = [value copyWithZone:zone];
    935             }
    936           } else {
    937             if (field.mapKeyDataType == GPBDataTypeString) {
    938               // NSDictionary
    939               newValue = [value mutableCopyWithZone:zone];
    940             } else {
    941               // Is one of the GPB*Dictionary classes.  Type doesn't matter,
    942               // just need one to invoke the selector.
    943               GPBInt32Int32Dictionary *existingDict = value;
    944               newValue = [existingDict copyWithZone:zone];
    945             }
    946           }
    947         }
    948         // We retain here because the memcpy picked up the pointer value and
    949         // the next call to SetRetainedObject... will release the current value.
    950         [value retain];
    951         GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
    952                                                   syntax);
    953       }
    954     } else if (GPBFieldDataTypeIsMessage(field)) {
    955       // For object types, if we have a value, copy it.  If we don't,
    956       // zero it to remove the pointer to something that was autocreated
    957       // (and the ptr just got memcpyed).
    958       if (GPBGetHasIvarField(self, field)) {
    959         GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    960         GPBMessage *newValue = [value copyWithZone:zone];
    961         // We retain here because the memcpy picked up the pointer value and
    962         // the next call to SetRetainedObject... will release the current value.
    963         [value retain];
    964         GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
    965                                                   syntax);
    966       } else {
    967         uint8_t *storage = (uint8_t *)message->messageStorage_;
    968         id *typePtr = (id *)&storage[field->description_->offset];
    969         *typePtr = NULL;
    970       }
    971     } else if (GPBFieldDataTypeIsObject(field) &&
    972                GPBGetHasIvarField(self, field)) {
    973       // A set string/data value (message picked off above), copy it.
    974       id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
    975       id newValue = [value copyWithZone:zone];
    976       // We retain here because the memcpy picked up the pointer value and
    977       // the next call to SetRetainedObject... will release the current value.
    978       [value retain];
    979       GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
    980                                                 syntax);
    981     } else {
    982       // memcpy took care of the rest of the primitive fields if they were set.
    983     }
    984   }  // for (field in descriptor->fields_)
    985 }
    986 
    987 - (id)copyWithZone:(NSZone *)zone {
    988   GPBDescriptor *descriptor = [self descriptor];
    989   GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init];
    990 
    991   [self copyFieldsInto:result zone:zone descriptor:descriptor];
    992   // Make immutable copies of the extra bits.
    993   result->unknownFields_ = [unknownFields_ copyWithZone:zone];
    994   result->extensionMap_ = CloneExtensionMap(extensionMap_, zone);
    995   return result;
    996 }
    997 
    998 - (void)clear {
    999   [self internalClear:YES];
   1000 }
   1001 
   1002 - (void)internalClear:(BOOL)zeroStorage {
   1003   GPBDescriptor *descriptor = [self descriptor];
   1004   for (GPBFieldDescriptor *field in descriptor->fields_) {
   1005     if (GPBFieldIsMapOrArray(field)) {
   1006       id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1007       if (arrayOrMap) {
   1008         if (field.fieldType == GPBFieldTypeRepeated) {
   1009           if (GPBFieldDataTypeIsObject(field)) {
   1010             GPBAutocreatedArray *autoArray = arrayOrMap;
   1011             if (autoArray->_autocreator == self) {
   1012               autoArray->_autocreator = nil;
   1013             }
   1014           } else {
   1015             // Type doesn't matter, it is a GPB*Array.
   1016             GPBInt32Array *gpbArray = arrayOrMap;
   1017             if (gpbArray->_autocreator == self) {
   1018               gpbArray->_autocreator = nil;
   1019             }
   1020           }
   1021         } else {
   1022           if ((field.mapKeyDataType == GPBDataTypeString) &&
   1023               GPBFieldDataTypeIsObject(field)) {
   1024             GPBAutocreatedDictionary *autoDict = arrayOrMap;
   1025             if (autoDict->_autocreator == self) {
   1026               autoDict->_autocreator = nil;
   1027             }
   1028           } else {
   1029             // Type doesn't matter, it is a GPB*Dictionary.
   1030             GPBInt32Int32Dictionary *gpbDict = arrayOrMap;
   1031             if (gpbDict->_autocreator == self) {
   1032               gpbDict->_autocreator = nil;
   1033             }
   1034           }
   1035         }
   1036         [arrayOrMap release];
   1037       }
   1038     } else if (GPBFieldDataTypeIsMessage(field)) {
   1039       GPBClearAutocreatedMessageIvarWithField(self, field);
   1040       GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1041       [value release];
   1042     } else if (GPBFieldDataTypeIsObject(field) &&
   1043                GPBGetHasIvarField(self, field)) {
   1044       id value = GPBGetObjectIvarWithField(self, field);
   1045       [value release];
   1046     }
   1047   }
   1048 
   1049   // GPBClearMessageAutocreator() expects that its caller has already been
   1050   // removed from autocreatedExtensionMap_ so we set to nil first.
   1051   NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues];
   1052   [autocreatedExtensionMap_ release];
   1053   autocreatedExtensionMap_ = nil;
   1054 
   1055   // Since we're clearing all of our extensions, make sure that we clear the
   1056   // autocreator on any that we've created so they no longer refer to us.
   1057   for (GPBMessage *value in autocreatedValues) {
   1058     NSCAssert(GPBWasMessageAutocreatedBy(value, self),
   1059               @"Autocreated extension does not refer back to self.");
   1060     GPBClearMessageAutocreator(value);
   1061   }
   1062 
   1063   [extensionMap_ release];
   1064   extensionMap_ = nil;
   1065   [unknownFields_ release];
   1066   unknownFields_ = nil;
   1067 
   1068   // Note that clearing does not affect autocreator_. If we are being cleared
   1069   // because of a dealloc, then autocreator_ should be nil anyway. If we are
   1070   // being cleared because someone explicitly clears us, we don't want to
   1071   // sever our relationship with our autocreator.
   1072 
   1073   if (zeroStorage) {
   1074     memset(messageStorage_, 0, descriptor->storageSize_);
   1075   }
   1076 }
   1077 
   1078 - (BOOL)isInitialized {
   1079   GPBDescriptor *descriptor = [self descriptor];
   1080   for (GPBFieldDescriptor *field in descriptor->fields_) {
   1081     if (field.isRequired) {
   1082       if (!GPBGetHasIvarField(self, field)) {
   1083         return NO;
   1084       }
   1085     }
   1086     if (GPBFieldDataTypeIsMessage(field)) {
   1087       GPBFieldType fieldType = field.fieldType;
   1088       if (fieldType == GPBFieldTypeSingle) {
   1089         if (field.isRequired) {
   1090           GPBMessage *message = GPBGetMessageMessageField(self, field);
   1091           if (!message.initialized) {
   1092             return NO;
   1093           }
   1094         } else {
   1095           NSAssert(field.isOptional,
   1096                    @"%@: Single message field %@ not required or optional?",
   1097                    [self class], field.name);
   1098           if (GPBGetHasIvarField(self, field)) {
   1099             GPBMessage *message = GPBGetMessageMessageField(self, field);
   1100             if (!message.initialized) {
   1101               return NO;
   1102             }
   1103           }
   1104         }
   1105       } else if (fieldType == GPBFieldTypeRepeated) {
   1106         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1107         for (GPBMessage *message in array) {
   1108           if (!message.initialized) {
   1109             return NO;
   1110           }
   1111         }
   1112       } else {  // fieldType == GPBFieldTypeMap
   1113         if (field.mapKeyDataType == GPBDataTypeString) {
   1114           NSDictionary *map =
   1115               GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1116           if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) {
   1117             return NO;
   1118           }
   1119         } else {
   1120           // Real type is GPB*ObjectDictionary, exact type doesn't matter.
   1121           GPBInt32ObjectDictionary *map =
   1122               GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1123           if (map && ![map isInitialized]) {
   1124             return NO;
   1125           }
   1126         }
   1127       }
   1128     }
   1129   }
   1130 
   1131   __block BOOL result = YES;
   1132   [extensionMap_
   1133       enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension,
   1134                                           id obj,
   1135                                           BOOL *stop) {
   1136         if (GPBExtensionIsMessage(extension)) {
   1137           if (extension.isRepeated) {
   1138             for (GPBMessage *msg in obj) {
   1139               if (!msg.initialized) {
   1140                 result = NO;
   1141                 *stop = YES;
   1142                 break;
   1143               }
   1144             }
   1145           } else {
   1146             GPBMessage *asMsg = obj;
   1147             if (!asMsg.initialized) {
   1148               result = NO;
   1149               *stop = YES;
   1150             }
   1151           }
   1152         }
   1153       }];
   1154   return result;
   1155 }
   1156 
   1157 - (GPBDescriptor *)descriptor {
   1158   return [[self class] descriptor];
   1159 }
   1160 
   1161 - (NSData *)data {
   1162 #ifdef DEBUG
   1163   if (!self.initialized) {
   1164     return nil;
   1165   }
   1166 #endif
   1167   NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]];
   1168   GPBCodedOutputStream *stream =
   1169       [[GPBCodedOutputStream alloc] initWithData:data];
   1170   @try {
   1171     [self writeToCodedOutputStream:stream];
   1172   }
   1173   @catch (NSException *exception) {
   1174     // This really shouldn't happen. The only way writeToCodedOutputStream:
   1175     // could throw is if something in the library has a bug and the
   1176     // serializedSize was wrong.
   1177 #ifdef DEBUG
   1178     NSLog(@"%@: Internal exception while building message data: %@",
   1179           [self class], exception);
   1180 #endif
   1181     data = nil;
   1182   }
   1183   [stream release];
   1184   return data;
   1185 }
   1186 
   1187 - (NSData *)delimitedData {
   1188   size_t serializedSize = [self serializedSize];
   1189   size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize);
   1190   NSMutableData *data =
   1191       [NSMutableData dataWithLength:(serializedSize + varintSize)];
   1192   GPBCodedOutputStream *stream =
   1193       [[GPBCodedOutputStream alloc] initWithData:data];
   1194   @try {
   1195     [self writeDelimitedToCodedOutputStream:stream];
   1196   }
   1197   @catch (NSException *exception) {
   1198     // This really shouldn't happen.  The only way writeToCodedOutputStream:
   1199     // could throw is if something in the library has a bug and the
   1200     // serializedSize was wrong.
   1201 #ifdef DEBUG
   1202     NSLog(@"%@: Internal exception while building message delimitedData: %@",
   1203           [self class], exception);
   1204 #endif
   1205     // If it happens, truncate.
   1206     data.length = 0;
   1207   }
   1208   [stream release];
   1209   return data;
   1210 }
   1211 
   1212 - (void)writeToOutputStream:(NSOutputStream *)output {
   1213   GPBCodedOutputStream *stream =
   1214       [[GPBCodedOutputStream alloc] initWithOutputStream:output];
   1215   [self writeToCodedOutputStream:stream];
   1216   [stream release];
   1217 }
   1218 
   1219 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output {
   1220   GPBDescriptor *descriptor = [self descriptor];
   1221   NSArray *fieldsArray = descriptor->fields_;
   1222   NSUInteger fieldCount = fieldsArray.count;
   1223   const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
   1224   NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
   1225   for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
   1226     if (i == fieldCount) {
   1227       [self writeExtensionsToCodedOutputStream:output
   1228                                          range:extensionRanges[j++]];
   1229     } else if (j == extensionRangesCount ||
   1230                GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
   1231       [self writeField:fieldsArray[i++] toCodedOutputStream:output];
   1232     } else {
   1233       [self writeExtensionsToCodedOutputStream:output
   1234                                          range:extensionRanges[j++]];
   1235     }
   1236   }
   1237   if (descriptor.isWireFormat) {
   1238     [unknownFields_ writeAsMessageSetTo:output];
   1239   } else {
   1240     [unknownFields_ writeToCodedOutputStream:output];
   1241   }
   1242 }
   1243 
   1244 - (void)writeDelimitedToOutputStream:(NSOutputStream *)output {
   1245   GPBCodedOutputStream *codedOutput =
   1246       [[GPBCodedOutputStream alloc] initWithOutputStream:output];
   1247   [self writeDelimitedToCodedOutputStream:codedOutput];
   1248   [codedOutput release];
   1249 }
   1250 
   1251 - (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output {
   1252   [output writeRawVarintSizeTAs32:[self serializedSize]];
   1253   [self writeToCodedOutputStream:output];
   1254 }
   1255 
   1256 - (void)writeField:(GPBFieldDescriptor *)field
   1257     toCodedOutputStream:(GPBCodedOutputStream *)output {
   1258   GPBFieldType fieldType = field.fieldType;
   1259   if (fieldType == GPBFieldTypeSingle) {
   1260     BOOL has = GPBGetHasIvarField(self, field);
   1261     if (!has) {
   1262       return;
   1263     }
   1264   }
   1265   uint32_t fieldNumber = GPBFieldNumber(field);
   1266 
   1267 //%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE)
   1268 //%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE)
   1269 //%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE)
   1270 //%    case GPBDataType##TYPE:
   1271 //%      if (fieldType == GPBFieldTypeRepeated) {
   1272 //%        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1273 //%        GPB##ARRAY_TYPE##Array *array =
   1274 //%            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1275 //%        [output write##TYPE##Array:fieldNumber values:array tag:tag];
   1276 //%      } else if (fieldType == GPBFieldTypeSingle) {
   1277 //%        [output write##TYPE:fieldNumber
   1278 //%              TYPE$S  value:GPBGetMessage##REAL_TYPE##Field(self, field)];
   1279 //%      } else {  // fieldType == GPBFieldTypeMap
   1280 //%        // Exact type here doesn't matter.
   1281 //%        GPBInt32##ARRAY_TYPE##Dictionary *dict =
   1282 //%            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1283 //%        [dict writeToCodedOutputStream:output asField:field];
   1284 //%      }
   1285 //%      break;
   1286 //%
   1287 //%PDDM-DEFINE FIELD_CASE2(TYPE)
   1288 //%    case GPBDataType##TYPE:
   1289 //%      if (fieldType == GPBFieldTypeRepeated) {
   1290 //%        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1291 //%        [output write##TYPE##Array:fieldNumber values:array];
   1292 //%      } else if (fieldType == GPBFieldTypeSingle) {
   1293 //%        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
   1294 //%        // again.
   1295 //%        [output write##TYPE:fieldNumber
   1296 //%              TYPE$S  value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
   1297 //%      } else {  // fieldType == GPBFieldTypeMap
   1298 //%        // Exact type here doesn't matter.
   1299 //%        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1300 //%        GPBDataType mapKeyDataType = field.mapKeyDataType;
   1301 //%        if (mapKeyDataType == GPBDataTypeString) {
   1302 //%          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
   1303 //%        } else {
   1304 //%          [dict writeToCodedOutputStream:output asField:field];
   1305 //%        }
   1306 //%      }
   1307 //%      break;
   1308 //%
   1309 
   1310   switch (GPBGetFieldDataType(field)) {
   1311 
   1312 //%PDDM-EXPAND FIELD_CASE(Bool, Bool)
   1313 // This block of code is generated, do not edit it directly.
   1314 
   1315     case GPBDataTypeBool:
   1316       if (fieldType == GPBFieldTypeRepeated) {
   1317         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1318         GPBBoolArray *array =
   1319             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1320         [output writeBoolArray:fieldNumber values:array tag:tag];
   1321       } else if (fieldType == GPBFieldTypeSingle) {
   1322         [output writeBool:fieldNumber
   1323                     value:GPBGetMessageBoolField(self, field)];
   1324       } else {  // fieldType == GPBFieldTypeMap
   1325         // Exact type here doesn't matter.
   1326         GPBInt32BoolDictionary *dict =
   1327             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1328         [dict writeToCodedOutputStream:output asField:field];
   1329       }
   1330       break;
   1331 
   1332 //%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32)
   1333 // This block of code is generated, do not edit it directly.
   1334 
   1335     case GPBDataTypeFixed32:
   1336       if (fieldType == GPBFieldTypeRepeated) {
   1337         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1338         GPBUInt32Array *array =
   1339             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1340         [output writeFixed32Array:fieldNumber values:array tag:tag];
   1341       } else if (fieldType == GPBFieldTypeSingle) {
   1342         [output writeFixed32:fieldNumber
   1343                        value:GPBGetMessageUInt32Field(self, field)];
   1344       } else {  // fieldType == GPBFieldTypeMap
   1345         // Exact type here doesn't matter.
   1346         GPBInt32UInt32Dictionary *dict =
   1347             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1348         [dict writeToCodedOutputStream:output asField:field];
   1349       }
   1350       break;
   1351 
   1352 //%PDDM-EXPAND FIELD_CASE(SFixed32, Int32)
   1353 // This block of code is generated, do not edit it directly.
   1354 
   1355     case GPBDataTypeSFixed32:
   1356       if (fieldType == GPBFieldTypeRepeated) {
   1357         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1358         GPBInt32Array *array =
   1359             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1360         [output writeSFixed32Array:fieldNumber values:array tag:tag];
   1361       } else if (fieldType == GPBFieldTypeSingle) {
   1362         [output writeSFixed32:fieldNumber
   1363                         value:GPBGetMessageInt32Field(self, field)];
   1364       } else {  // fieldType == GPBFieldTypeMap
   1365         // Exact type here doesn't matter.
   1366         GPBInt32Int32Dictionary *dict =
   1367             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1368         [dict writeToCodedOutputStream:output asField:field];
   1369       }
   1370       break;
   1371 
   1372 //%PDDM-EXPAND FIELD_CASE(Float, Float)
   1373 // This block of code is generated, do not edit it directly.
   1374 
   1375     case GPBDataTypeFloat:
   1376       if (fieldType == GPBFieldTypeRepeated) {
   1377         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1378         GPBFloatArray *array =
   1379             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1380         [output writeFloatArray:fieldNumber values:array tag:tag];
   1381       } else if (fieldType == GPBFieldTypeSingle) {
   1382         [output writeFloat:fieldNumber
   1383                      value:GPBGetMessageFloatField(self, field)];
   1384       } else {  // fieldType == GPBFieldTypeMap
   1385         // Exact type here doesn't matter.
   1386         GPBInt32FloatDictionary *dict =
   1387             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1388         [dict writeToCodedOutputStream:output asField:field];
   1389       }
   1390       break;
   1391 
   1392 //%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64)
   1393 // This block of code is generated, do not edit it directly.
   1394 
   1395     case GPBDataTypeFixed64:
   1396       if (fieldType == GPBFieldTypeRepeated) {
   1397         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1398         GPBUInt64Array *array =
   1399             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1400         [output writeFixed64Array:fieldNumber values:array tag:tag];
   1401       } else if (fieldType == GPBFieldTypeSingle) {
   1402         [output writeFixed64:fieldNumber
   1403                        value:GPBGetMessageUInt64Field(self, field)];
   1404       } else {  // fieldType == GPBFieldTypeMap
   1405         // Exact type here doesn't matter.
   1406         GPBInt32UInt64Dictionary *dict =
   1407             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1408         [dict writeToCodedOutputStream:output asField:field];
   1409       }
   1410       break;
   1411 
   1412 //%PDDM-EXPAND FIELD_CASE(SFixed64, Int64)
   1413 // This block of code is generated, do not edit it directly.
   1414 
   1415     case GPBDataTypeSFixed64:
   1416       if (fieldType == GPBFieldTypeRepeated) {
   1417         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1418         GPBInt64Array *array =
   1419             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1420         [output writeSFixed64Array:fieldNumber values:array tag:tag];
   1421       } else if (fieldType == GPBFieldTypeSingle) {
   1422         [output writeSFixed64:fieldNumber
   1423                         value:GPBGetMessageInt64Field(self, field)];
   1424       } else {  // fieldType == GPBFieldTypeMap
   1425         // Exact type here doesn't matter.
   1426         GPBInt32Int64Dictionary *dict =
   1427             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1428         [dict writeToCodedOutputStream:output asField:field];
   1429       }
   1430       break;
   1431 
   1432 //%PDDM-EXPAND FIELD_CASE(Double, Double)
   1433 // This block of code is generated, do not edit it directly.
   1434 
   1435     case GPBDataTypeDouble:
   1436       if (fieldType == GPBFieldTypeRepeated) {
   1437         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1438         GPBDoubleArray *array =
   1439             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1440         [output writeDoubleArray:fieldNumber values:array tag:tag];
   1441       } else if (fieldType == GPBFieldTypeSingle) {
   1442         [output writeDouble:fieldNumber
   1443                       value:GPBGetMessageDoubleField(self, field)];
   1444       } else {  // fieldType == GPBFieldTypeMap
   1445         // Exact type here doesn't matter.
   1446         GPBInt32DoubleDictionary *dict =
   1447             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1448         [dict writeToCodedOutputStream:output asField:field];
   1449       }
   1450       break;
   1451 
   1452 //%PDDM-EXPAND FIELD_CASE(Int32, Int32)
   1453 // This block of code is generated, do not edit it directly.
   1454 
   1455     case GPBDataTypeInt32:
   1456       if (fieldType == GPBFieldTypeRepeated) {
   1457         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1458         GPBInt32Array *array =
   1459             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1460         [output writeInt32Array:fieldNumber values:array tag:tag];
   1461       } else if (fieldType == GPBFieldTypeSingle) {
   1462         [output writeInt32:fieldNumber
   1463                      value:GPBGetMessageInt32Field(self, field)];
   1464       } else {  // fieldType == GPBFieldTypeMap
   1465         // Exact type here doesn't matter.
   1466         GPBInt32Int32Dictionary *dict =
   1467             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1468         [dict writeToCodedOutputStream:output asField:field];
   1469       }
   1470       break;
   1471 
   1472 //%PDDM-EXPAND FIELD_CASE(Int64, Int64)
   1473 // This block of code is generated, do not edit it directly.
   1474 
   1475     case GPBDataTypeInt64:
   1476       if (fieldType == GPBFieldTypeRepeated) {
   1477         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1478         GPBInt64Array *array =
   1479             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1480         [output writeInt64Array:fieldNumber values:array tag:tag];
   1481       } else if (fieldType == GPBFieldTypeSingle) {
   1482         [output writeInt64:fieldNumber
   1483                      value:GPBGetMessageInt64Field(self, field)];
   1484       } else {  // fieldType == GPBFieldTypeMap
   1485         // Exact type here doesn't matter.
   1486         GPBInt32Int64Dictionary *dict =
   1487             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1488         [dict writeToCodedOutputStream:output asField:field];
   1489       }
   1490       break;
   1491 
   1492 //%PDDM-EXPAND FIELD_CASE(SInt32, Int32)
   1493 // This block of code is generated, do not edit it directly.
   1494 
   1495     case GPBDataTypeSInt32:
   1496       if (fieldType == GPBFieldTypeRepeated) {
   1497         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1498         GPBInt32Array *array =
   1499             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1500         [output writeSInt32Array:fieldNumber values:array tag:tag];
   1501       } else if (fieldType == GPBFieldTypeSingle) {
   1502         [output writeSInt32:fieldNumber
   1503                       value:GPBGetMessageInt32Field(self, field)];
   1504       } else {  // fieldType == GPBFieldTypeMap
   1505         // Exact type here doesn't matter.
   1506         GPBInt32Int32Dictionary *dict =
   1507             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1508         [dict writeToCodedOutputStream:output asField:field];
   1509       }
   1510       break;
   1511 
   1512 //%PDDM-EXPAND FIELD_CASE(SInt64, Int64)
   1513 // This block of code is generated, do not edit it directly.
   1514 
   1515     case GPBDataTypeSInt64:
   1516       if (fieldType == GPBFieldTypeRepeated) {
   1517         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1518         GPBInt64Array *array =
   1519             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1520         [output writeSInt64Array:fieldNumber values:array tag:tag];
   1521       } else if (fieldType == GPBFieldTypeSingle) {
   1522         [output writeSInt64:fieldNumber
   1523                       value:GPBGetMessageInt64Field(self, field)];
   1524       } else {  // fieldType == GPBFieldTypeMap
   1525         // Exact type here doesn't matter.
   1526         GPBInt32Int64Dictionary *dict =
   1527             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1528         [dict writeToCodedOutputStream:output asField:field];
   1529       }
   1530       break;
   1531 
   1532 //%PDDM-EXPAND FIELD_CASE(UInt32, UInt32)
   1533 // This block of code is generated, do not edit it directly.
   1534 
   1535     case GPBDataTypeUInt32:
   1536       if (fieldType == GPBFieldTypeRepeated) {
   1537         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1538         GPBUInt32Array *array =
   1539             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1540         [output writeUInt32Array:fieldNumber values:array tag:tag];
   1541       } else if (fieldType == GPBFieldTypeSingle) {
   1542         [output writeUInt32:fieldNumber
   1543                       value:GPBGetMessageUInt32Field(self, field)];
   1544       } else {  // fieldType == GPBFieldTypeMap
   1545         // Exact type here doesn't matter.
   1546         GPBInt32UInt32Dictionary *dict =
   1547             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1548         [dict writeToCodedOutputStream:output asField:field];
   1549       }
   1550       break;
   1551 
   1552 //%PDDM-EXPAND FIELD_CASE(UInt64, UInt64)
   1553 // This block of code is generated, do not edit it directly.
   1554 
   1555     case GPBDataTypeUInt64:
   1556       if (fieldType == GPBFieldTypeRepeated) {
   1557         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1558         GPBUInt64Array *array =
   1559             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1560         [output writeUInt64Array:fieldNumber values:array tag:tag];
   1561       } else if (fieldType == GPBFieldTypeSingle) {
   1562         [output writeUInt64:fieldNumber
   1563                       value:GPBGetMessageUInt64Field(self, field)];
   1564       } else {  // fieldType == GPBFieldTypeMap
   1565         // Exact type here doesn't matter.
   1566         GPBInt32UInt64Dictionary *dict =
   1567             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1568         [dict writeToCodedOutputStream:output asField:field];
   1569       }
   1570       break;
   1571 
   1572 //%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum)
   1573 // This block of code is generated, do not edit it directly.
   1574 
   1575     case GPBDataTypeEnum:
   1576       if (fieldType == GPBFieldTypeRepeated) {
   1577         uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
   1578         GPBEnumArray *array =
   1579             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1580         [output writeEnumArray:fieldNumber values:array tag:tag];
   1581       } else if (fieldType == GPBFieldTypeSingle) {
   1582         [output writeEnum:fieldNumber
   1583                     value:GPBGetMessageInt32Field(self, field)];
   1584       } else {  // fieldType == GPBFieldTypeMap
   1585         // Exact type here doesn't matter.
   1586         GPBInt32EnumDictionary *dict =
   1587             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1588         [dict writeToCodedOutputStream:output asField:field];
   1589       }
   1590       break;
   1591 
   1592 //%PDDM-EXPAND FIELD_CASE2(Bytes)
   1593 // This block of code is generated, do not edit it directly.
   1594 
   1595     case GPBDataTypeBytes:
   1596       if (fieldType == GPBFieldTypeRepeated) {
   1597         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1598         [output writeBytesArray:fieldNumber values:array];
   1599       } else if (fieldType == GPBFieldTypeSingle) {
   1600         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
   1601         // again.
   1602         [output writeBytes:fieldNumber
   1603                      value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
   1604       } else {  // fieldType == GPBFieldTypeMap
   1605         // Exact type here doesn't matter.
   1606         id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1607         GPBDataType mapKeyDataType = field.mapKeyDataType;
   1608         if (mapKeyDataType == GPBDataTypeString) {
   1609           GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
   1610         } else {
   1611           [dict writeToCodedOutputStream:output asField:field];
   1612         }
   1613       }
   1614       break;
   1615 
   1616 //%PDDM-EXPAND FIELD_CASE2(String)
   1617 // This block of code is generated, do not edit it directly.
   1618 
   1619     case GPBDataTypeString:
   1620       if (fieldType == GPBFieldTypeRepeated) {
   1621         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1622         [output writeStringArray:fieldNumber values:array];
   1623       } else if (fieldType == GPBFieldTypeSingle) {
   1624         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
   1625         // again.
   1626         [output writeString:fieldNumber
   1627                       value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
   1628       } else {  // fieldType == GPBFieldTypeMap
   1629         // Exact type here doesn't matter.
   1630         id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1631         GPBDataType mapKeyDataType = field.mapKeyDataType;
   1632         if (mapKeyDataType == GPBDataTypeString) {
   1633           GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
   1634         } else {
   1635           [dict writeToCodedOutputStream:output asField:field];
   1636         }
   1637       }
   1638       break;
   1639 
   1640 //%PDDM-EXPAND FIELD_CASE2(Message)
   1641 // This block of code is generated, do not edit it directly.
   1642 
   1643     case GPBDataTypeMessage:
   1644       if (fieldType == GPBFieldTypeRepeated) {
   1645         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1646         [output writeMessageArray:fieldNumber values:array];
   1647       } else if (fieldType == GPBFieldTypeSingle) {
   1648         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
   1649         // again.
   1650         [output writeMessage:fieldNumber
   1651                        value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
   1652       } else {  // fieldType == GPBFieldTypeMap
   1653         // Exact type here doesn't matter.
   1654         id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1655         GPBDataType mapKeyDataType = field.mapKeyDataType;
   1656         if (mapKeyDataType == GPBDataTypeString) {
   1657           GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
   1658         } else {
   1659           [dict writeToCodedOutputStream:output asField:field];
   1660         }
   1661       }
   1662       break;
   1663 
   1664 //%PDDM-EXPAND FIELD_CASE2(Group)
   1665 // This block of code is generated, do not edit it directly.
   1666 
   1667     case GPBDataTypeGroup:
   1668       if (fieldType == GPBFieldTypeRepeated) {
   1669         NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1670         [output writeGroupArray:fieldNumber values:array];
   1671       } else if (fieldType == GPBFieldTypeSingle) {
   1672         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
   1673         // again.
   1674         [output writeGroup:fieldNumber
   1675                      value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
   1676       } else {  // fieldType == GPBFieldTypeMap
   1677         // Exact type here doesn't matter.
   1678         id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   1679         GPBDataType mapKeyDataType = field.mapKeyDataType;
   1680         if (mapKeyDataType == GPBDataTypeString) {
   1681           GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
   1682         } else {
   1683           [dict writeToCodedOutputStream:output asField:field];
   1684         }
   1685       }
   1686       break;
   1687 
   1688 //%PDDM-EXPAND-END (18 expansions)
   1689   }
   1690 }
   1691 
   1692 #pragma mark - Extensions
   1693 
   1694 - (id)getExtension:(GPBExtensionDescriptor *)extension {
   1695   CheckExtension(self, extension);
   1696   id value = [extensionMap_ objectForKey:extension];
   1697   if (value != nil) {
   1698     return value;
   1699   }
   1700 
   1701   // No default for repeated.
   1702   if (extension.isRepeated) {
   1703     return nil;
   1704   }
   1705   // Non messages get their default.
   1706   if (!GPBExtensionIsMessage(extension)) {
   1707     return extension.defaultValue;
   1708   }
   1709 
   1710   // Check for an autocreated value.
   1711   GPBPrepareReadOnlySemaphore(self);
   1712   dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER);
   1713   value = [autocreatedExtensionMap_ objectForKey:extension];
   1714   if (!value) {
   1715     // Auto create the message extensions to match normal fields.
   1716     value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self,
   1717                                                      extension);
   1718 
   1719     if (autocreatedExtensionMap_ == nil) {
   1720       autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init];
   1721     }
   1722 
   1723     // We can't simply call setExtension here because that would clear the new
   1724     // value's autocreator.
   1725     [autocreatedExtensionMap_ setObject:value forKey:extension];
   1726     [value release];
   1727   }
   1728 
   1729   dispatch_semaphore_signal(readOnlySemaphore_);
   1730   return value;
   1731 }
   1732 
   1733 - (id)getExistingExtension:(GPBExtensionDescriptor *)extension {
   1734   // This is an internal method so we don't need to call CheckExtension().
   1735   return [extensionMap_ objectForKey:extension];
   1736 }
   1737 
   1738 - (BOOL)hasExtension:(GPBExtensionDescriptor *)extension {
   1739 #if DEBUG
   1740   CheckExtension(self, extension);
   1741 #endif  // DEBUG
   1742   return nil != [extensionMap_ objectForKey:extension];
   1743 }
   1744 
   1745 - (NSArray *)extensionsCurrentlySet {
   1746   return [extensionMap_ allKeys];
   1747 }
   1748 
   1749 - (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output
   1750                                      range:(GPBExtensionRange)range {
   1751   NSArray *sortedExtensions = [[extensionMap_ allKeys]
   1752       sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
   1753   uint32_t start = range.start;
   1754   uint32_t end = range.end;
   1755   for (GPBExtensionDescriptor *extension in sortedExtensions) {
   1756     uint32_t fieldNumber = extension.fieldNumber;
   1757     if (fieldNumber >= start && fieldNumber < end) {
   1758       id value = [extensionMap_ objectForKey:extension];
   1759       GPBWriteExtensionValueToOutputStream(extension, value, output);
   1760     }
   1761   }
   1762 }
   1763 
   1764 - (NSArray *)sortedExtensionsInUse {
   1765   return [[extensionMap_ allKeys]
   1766       sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
   1767 }
   1768 
   1769 - (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value {
   1770   if (!value) {
   1771     [self clearExtension:extension];
   1772     return;
   1773   }
   1774 
   1775   CheckExtension(self, extension);
   1776 
   1777   if (extension.repeated) {
   1778     [NSException raise:NSInvalidArgumentException
   1779                 format:@"Must call addExtension() for repeated types."];
   1780   }
   1781 
   1782   if (extensionMap_ == nil) {
   1783     extensionMap_ = [[NSMutableDictionary alloc] init];
   1784   }
   1785 
   1786   // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION.
   1787   // Without it, the compiler complains we're passing an id nullable when
   1788   // setObject:forKey: requires a id nonnull for the value. The check for
   1789   // !value at the start of the method ensures it isn't nil, but the check
   1790   // isn't smart enough to realize that.
   1791   [extensionMap_ setObject:(id)value forKey:extension];
   1792 
   1793   GPBExtensionDescriptor *descriptor = extension;
   1794 
   1795   if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) {
   1796     GPBMessage *autocreatedValue =
   1797         [[autocreatedExtensionMap_ objectForKey:extension] retain];
   1798     // Must remove from the map before calling GPBClearMessageAutocreator() so
   1799     // that GPBClearMessageAutocreator() knows its safe to clear.
   1800     [autocreatedExtensionMap_ removeObjectForKey:extension];
   1801     GPBClearMessageAutocreator(autocreatedValue);
   1802     [autocreatedValue release];
   1803   }
   1804 
   1805   GPBBecomeVisibleToAutocreator(self);
   1806 }
   1807 
   1808 - (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value {
   1809   CheckExtension(self, extension);
   1810 
   1811   if (!extension.repeated) {
   1812     [NSException raise:NSInvalidArgumentException
   1813                 format:@"Must call setExtension() for singular types."];
   1814   }
   1815 
   1816   if (extensionMap_ == nil) {
   1817     extensionMap_ = [[NSMutableDictionary alloc] init];
   1818   }
   1819   NSMutableArray *list = [extensionMap_ objectForKey:extension];
   1820   if (list == nil) {
   1821     list = [NSMutableArray array];
   1822     [extensionMap_ setObject:list forKey:extension];
   1823   }
   1824 
   1825   [list addObject:value];
   1826   GPBBecomeVisibleToAutocreator(self);
   1827 }
   1828 
   1829 - (void)setExtension:(GPBExtensionDescriptor *)extension
   1830                index:(NSUInteger)idx
   1831                value:(id)value {
   1832   CheckExtension(self, extension);
   1833 
   1834   if (!extension.repeated) {
   1835     [NSException raise:NSInvalidArgumentException
   1836                 format:@"Must call setExtension() for singular types."];
   1837   }
   1838 
   1839   if (extensionMap_ == nil) {
   1840     extensionMap_ = [[NSMutableDictionary alloc] init];
   1841   }
   1842 
   1843   NSMutableArray *list = [extensionMap_ objectForKey:extension];
   1844 
   1845   [list replaceObjectAtIndex:idx withObject:value];
   1846   GPBBecomeVisibleToAutocreator(self);
   1847 }
   1848 
   1849 - (void)clearExtension:(GPBExtensionDescriptor *)extension {
   1850   CheckExtension(self, extension);
   1851 
   1852   // Only become visible if there was actually a value to clear.
   1853   if ([extensionMap_ objectForKey:extension]) {
   1854     [extensionMap_ removeObjectForKey:extension];
   1855     GPBBecomeVisibleToAutocreator(self);
   1856   }
   1857 }
   1858 
   1859 #pragma mark - mergeFrom
   1860 
   1861 - (void)mergeFromData:(NSData *)data
   1862     extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
   1863   GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
   1864   [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
   1865   [input checkLastTagWas:0];
   1866   [input release];
   1867 }
   1868 
   1869 #pragma mark - mergeDelimitedFrom
   1870 
   1871 - (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
   1872                          extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
   1873   GPBCodedInputStreamState *state = &input->state_;
   1874   if (GPBCodedInputStreamIsAtEnd(state)) {
   1875     return;
   1876   }
   1877   NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state);
   1878   if (data == nil) {
   1879     return;
   1880   }
   1881   [self mergeFromData:data extensionRegistry:extensionRegistry];
   1882   [data release];
   1883 }
   1884 
   1885 #pragma mark - Parse From Data Support
   1886 
   1887 + (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr {
   1888   return [self parseFromData:data extensionRegistry:nil error:errorPtr];
   1889 }
   1890 
   1891 + (instancetype)parseFromData:(NSData *)data
   1892             extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
   1893                         error:(NSError **)errorPtr {
   1894   return [[[self alloc] initWithData:data
   1895                    extensionRegistry:extensionRegistry
   1896                                error:errorPtr] autorelease];
   1897 }
   1898 
   1899 + (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
   1900                         extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
   1901                                     error:(NSError **)errorPtr {
   1902   return
   1903       [[[self alloc] initWithCodedInputStream:input
   1904                             extensionRegistry:extensionRegistry
   1905                                         error:errorPtr] autorelease];
   1906 }
   1907 
   1908 #pragma mark - Parse Delimited From Data Support
   1909 
   1910 + (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
   1911                                  extensionRegistry:
   1912                                      (GPBExtensionRegistry *)extensionRegistry
   1913                                              error:(NSError **)errorPtr {
   1914   GPBMessage *message = [[[self alloc] init] autorelease];
   1915   @try {
   1916     [message mergeDelimitedFromCodedInputStream:input
   1917                               extensionRegistry:extensionRegistry];
   1918     if (errorPtr) {
   1919       *errorPtr = nil;
   1920     }
   1921   }
   1922   @catch (NSException *exception) {
   1923     message = nil;
   1924     if (errorPtr) {
   1925       *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
   1926                                          exception.reason);
   1927     }
   1928   }
   1929 #ifdef DEBUG
   1930   if (message && !message.initialized) {
   1931     message = nil;
   1932     if (errorPtr) {
   1933       *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
   1934     }
   1935   }
   1936 #endif
   1937   return message;
   1938 }
   1939 
   1940 #pragma mark - Unknown Field Support
   1941 
   1942 - (GPBUnknownFieldSet *)unknownFields {
   1943   return unknownFields_;
   1944 }
   1945 
   1946 - (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields {
   1947   if (unknownFields != unknownFields_) {
   1948     [unknownFields_ release];
   1949     unknownFields_ = [unknownFields copy];
   1950     GPBBecomeVisibleToAutocreator(self);
   1951   }
   1952 }
   1953 
   1954 - (void)parseMessageSet:(GPBCodedInputStream *)input
   1955       extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
   1956   uint32_t typeId = 0;
   1957   NSData *rawBytes = nil;
   1958   GPBExtensionDescriptor *extension = nil;
   1959   GPBCodedInputStreamState *state = &input->state_;
   1960   while (true) {
   1961     uint32_t tag = GPBCodedInputStreamReadTag(state);
   1962     if (tag == 0) {
   1963       break;
   1964     }
   1965 
   1966     if (tag == GPBWireFormatMessageSetTypeIdTag) {
   1967       typeId = GPBCodedInputStreamReadUInt32(state);
   1968       if (typeId != 0) {
   1969         extension = [extensionRegistry extensionForDescriptor:[self descriptor]
   1970                                                   fieldNumber:typeId];
   1971       }
   1972     } else if (tag == GPBWireFormatMessageSetMessageTag) {
   1973       rawBytes =
   1974           [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease];
   1975     } else {
   1976       if (![input skipField:tag]) {
   1977         break;
   1978       }
   1979     }
   1980   }
   1981 
   1982   [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag];
   1983 
   1984   if (rawBytes != nil && typeId != 0) {
   1985     if (extension != nil) {
   1986       GPBCodedInputStream *newInput =
   1987           [[GPBCodedInputStream alloc] initWithData:rawBytes];
   1988       GPBExtensionMergeFromInputStream(extension,
   1989                                        extension.packable,
   1990                                        newInput,
   1991                                        extensionRegistry,
   1992                                        self);
   1993       [newInput release];
   1994     } else {
   1995       GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
   1996       [unknownFields mergeMessageSetMessage:typeId data:rawBytes];
   1997     }
   1998   }
   1999 }
   2000 
   2001 - (BOOL)parseUnknownField:(GPBCodedInputStream *)input
   2002         extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
   2003                       tag:(uint32_t)tag {
   2004   GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
   2005   int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag);
   2006 
   2007   GPBDescriptor *descriptor = [self descriptor];
   2008   GPBExtensionDescriptor *extension =
   2009       [extensionRegistry extensionForDescriptor:descriptor
   2010                                     fieldNumber:fieldNumber];
   2011   if (extension == nil) {
   2012     if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) {
   2013       [self parseMessageSet:input extensionRegistry:extensionRegistry];
   2014       return YES;
   2015     }
   2016   } else {
   2017     if (extension.wireType == wireType) {
   2018       GPBExtensionMergeFromInputStream(extension,
   2019                                        extension.packable,
   2020                                        input,
   2021                                        extensionRegistry,
   2022                                        self);
   2023       return YES;
   2024     }
   2025     // Primitive, repeated types can be packed on unpacked on the wire, and are
   2026     // parsed either way.
   2027     if ([extension isRepeated] &&
   2028         !GPBDataTypeIsObject(extension->description_->dataType) &&
   2029         (extension.alternateWireType == wireType)) {
   2030       GPBExtensionMergeFromInputStream(extension,
   2031                                        !extension.packable,
   2032                                        input,
   2033                                        extensionRegistry,
   2034                                        self);
   2035       return YES;
   2036     }
   2037   }
   2038   if ([GPBUnknownFieldSet isFieldTag:tag]) {
   2039     GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
   2040     return [unknownFields mergeFieldFrom:tag input:input];
   2041   } else {
   2042     return NO;
   2043   }
   2044 }
   2045 
   2046 - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
   2047   GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
   2048   [unknownFields addUnknownMapEntry:fieldNum value:data];
   2049 }
   2050 
   2051 #pragma mark - MergeFromCodedInputStream Support
   2052 
   2053 static void MergeSingleFieldFromCodedInputStream(
   2054     GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
   2055     GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
   2056   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   2057   switch (fieldDataType) {
   2058 #define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                             \
   2059     case GPBDataType##NAME: {                                              \
   2060       TYPE val = GPBCodedInputStreamRead##NAME(&input->state_);            \
   2061       GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax);  \
   2062       break;                                                               \
   2063             }
   2064 #define CASE_SINGLE_OBJECT(NAME)                                           \
   2065     case GPBDataType##NAME: {                                              \
   2066       id val = GPBCodedInputStreamReadRetained##NAME(&input->state_);      \
   2067       GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \
   2068       break;                                                               \
   2069     }
   2070       CASE_SINGLE_POD(Bool, BOOL, Bool)
   2071       CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
   2072       CASE_SINGLE_POD(SFixed32, int32_t, Int32)
   2073       CASE_SINGLE_POD(Float, float, Float)
   2074       CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
   2075       CASE_SINGLE_POD(SFixed64, int64_t, Int64)
   2076       CASE_SINGLE_POD(Double, double, Double)
   2077       CASE_SINGLE_POD(Int32, int32_t, Int32)
   2078       CASE_SINGLE_POD(Int64, int64_t, Int64)
   2079       CASE_SINGLE_POD(SInt32, int32_t, Int32)
   2080       CASE_SINGLE_POD(SInt64, int64_t, Int64)
   2081       CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
   2082       CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
   2083       CASE_SINGLE_OBJECT(Bytes)
   2084       CASE_SINGLE_OBJECT(String)
   2085 #undef CASE_SINGLE_POD
   2086 #undef CASE_SINGLE_OBJECT
   2087 
   2088     case GPBDataTypeMessage: {
   2089       if (GPBGetHasIvarField(self, field)) {
   2090         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
   2091         // check again.
   2092         GPBMessage *message =
   2093             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   2094         [input readMessage:message extensionRegistry:extensionRegistry];
   2095       } else {
   2096         GPBMessage *message = [[field.msgClass alloc] init];
   2097         [input readMessage:message extensionRegistry:extensionRegistry];
   2098         GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
   2099       }
   2100       break;
   2101     }
   2102 
   2103     case GPBDataTypeGroup: {
   2104       if (GPBGetHasIvarField(self, field)) {
   2105         // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
   2106         // check again.
   2107         GPBMessage *message =
   2108             GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   2109         [input readGroup:GPBFieldNumber(field)
   2110                       message:message
   2111             extensionRegistry:extensionRegistry];
   2112       } else {
   2113         GPBMessage *message = [[field.msgClass alloc] init];
   2114         [input readGroup:GPBFieldNumber(field)
   2115                       message:message
   2116             extensionRegistry:extensionRegistry];
   2117         GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
   2118       }
   2119       break;
   2120     }
   2121 
   2122     case GPBDataTypeEnum: {
   2123       int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
   2124       if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
   2125           [field isValidEnumValue:val]) {
   2126         GPBSetInt32IvarWithFieldInternal(self, field, val, syntax);
   2127       } else {
   2128         GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
   2129         [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
   2130       }
   2131     }
   2132   }  // switch
   2133 }
   2134 
   2135 static void MergeRepeatedPackedFieldFromCodedInputStream(
   2136     GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
   2137     GPBCodedInputStream *input) {
   2138   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   2139   GPBCodedInputStreamState *state = &input->state_;
   2140   id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
   2141   int32_t length = GPBCodedInputStreamReadInt32(state);
   2142   size_t limit = GPBCodedInputStreamPushLimit(state, length);
   2143   while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
   2144     switch (fieldDataType) {
   2145 #define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE)      \
   2146      case GPBDataType##NAME: {                                \
   2147        TYPE val = GPBCodedInputStreamRead##NAME(state);       \
   2148        [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \
   2149        break;                                                 \
   2150      }
   2151         CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool)
   2152         CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32)
   2153         CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32)
   2154         CASE_REPEATED_PACKED_POD(Float, float, Float)
   2155         CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64)
   2156         CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64)
   2157         CASE_REPEATED_PACKED_POD(Double, double, Double)
   2158         CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32)
   2159         CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64)
   2160         CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32)
   2161         CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64)
   2162         CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32)
   2163         CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64)
   2164 #undef CASE_REPEATED_PACKED_POD
   2165 
   2166       case GPBDataTypeBytes:
   2167       case GPBDataTypeString:
   2168       case GPBDataTypeMessage:
   2169       case GPBDataTypeGroup:
   2170         NSCAssert(NO, @"Non primitive types can't be packed");
   2171         break;
   2172 
   2173       case GPBDataTypeEnum: {
   2174         int32_t val = GPBCodedInputStreamReadEnum(state);
   2175         if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
   2176             [field isValidEnumValue:val]) {
   2177           [(GPBEnumArray*)genericArray addRawValue:val];
   2178         } else {
   2179           GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
   2180           [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
   2181         }
   2182         break;
   2183       }
   2184     }  // switch
   2185   }  // while(BytesUntilLimit() > 0)
   2186   GPBCodedInputStreamPopLimit(state, limit);
   2187 }
   2188 
   2189 static void MergeRepeatedNotPackedFieldFromCodedInputStream(
   2190     GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
   2191     GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
   2192   GPBCodedInputStreamState *state = &input->state_;
   2193   id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
   2194   switch (GPBGetFieldDataType(field)) {
   2195 #define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \
   2196    case GPBDataType##NAME: {                                 \
   2197      TYPE val = GPBCodedInputStreamRead##NAME(state);        \
   2198      [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val];  \
   2199      break;                                                  \
   2200    }
   2201 #define CASE_REPEATED_NOT_PACKED_OBJECT(NAME)                \
   2202    case GPBDataType##NAME: {                                 \
   2203      id val = GPBCodedInputStreamReadRetained##NAME(state);  \
   2204      [(NSMutableArray*)genericArray addObject:val];          \
   2205      [val release];                                          \
   2206      break;                                                  \
   2207    }
   2208       CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool)
   2209       CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32)
   2210       CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32)
   2211       CASE_REPEATED_NOT_PACKED_POD(Float, float, Float)
   2212       CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64)
   2213       CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64)
   2214       CASE_REPEATED_NOT_PACKED_POD(Double, double, Double)
   2215       CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32)
   2216       CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64)
   2217       CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32)
   2218       CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64)
   2219       CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32)
   2220       CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64)
   2221       CASE_REPEATED_NOT_PACKED_OBJECT(Bytes)
   2222       CASE_REPEATED_NOT_PACKED_OBJECT(String)
   2223 #undef CASE_REPEATED_NOT_PACKED_POD
   2224 #undef CASE_NOT_PACKED_OBJECT
   2225     case GPBDataTypeMessage: {
   2226       GPBMessage *message = [[field.msgClass alloc] init];
   2227       [input readMessage:message extensionRegistry:extensionRegistry];
   2228       [(NSMutableArray*)genericArray addObject:message];
   2229       [message release];
   2230       break;
   2231     }
   2232     case GPBDataTypeGroup: {
   2233       GPBMessage *message = [[field.msgClass alloc] init];
   2234       [input readGroup:GPBFieldNumber(field)
   2235                     message:message
   2236           extensionRegistry:extensionRegistry];
   2237       [(NSMutableArray*)genericArray addObject:message];
   2238       [message release];
   2239       break;
   2240     }
   2241     case GPBDataTypeEnum: {
   2242       int32_t val = GPBCodedInputStreamReadEnum(state);
   2243       if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
   2244           [field isValidEnumValue:val]) {
   2245         [(GPBEnumArray*)genericArray addRawValue:val];
   2246       } else {
   2247         GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
   2248         [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
   2249       }
   2250       break;
   2251     }
   2252   }  // switch
   2253 }
   2254 
   2255 - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
   2256                 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
   2257   GPBDescriptor *descriptor = [self descriptor];
   2258   GPBFileSyntax syntax = descriptor.file.syntax;
   2259   GPBCodedInputStreamState *state = &input->state_;
   2260   uint32_t tag = 0;
   2261   NSUInteger startingIndex = 0;
   2262   NSArray *fields = descriptor->fields_;
   2263   NSUInteger numFields = fields.count;
   2264   while (YES) {
   2265     BOOL merged = NO;
   2266     tag = GPBCodedInputStreamReadTag(state);
   2267     for (NSUInteger i = 0; i < numFields; ++i) {
   2268       if (startingIndex >= numFields) startingIndex = 0;
   2269       GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
   2270       if (GPBFieldTag(fieldDescriptor) == tag) {
   2271         GPBFieldType fieldType = fieldDescriptor.fieldType;
   2272         if (fieldType == GPBFieldTypeSingle) {
   2273           MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax,
   2274                                                input, extensionRegistry);
   2275           // Well formed protos will only have a single field once, advance
   2276           // the starting index to the next field.
   2277           startingIndex += 1;
   2278         } else if (fieldType == GPBFieldTypeRepeated) {
   2279           if (fieldDescriptor.isPackable) {
   2280             MergeRepeatedPackedFieldFromCodedInputStream(
   2281                 self, fieldDescriptor, syntax, input);
   2282             // Well formed protos will only have a repeated field that is
   2283             // packed once, advance the starting index to the next field.
   2284             startingIndex += 1;
   2285           } else {
   2286             MergeRepeatedNotPackedFieldFromCodedInputStream(
   2287                 self, fieldDescriptor, syntax, input, extensionRegistry);
   2288           }
   2289         } else {  // fieldType == GPBFieldTypeMap
   2290           // GPB*Dictionary or NSDictionary, exact type doesn't matter at this
   2291           // point.
   2292           id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax);
   2293           [input readMapEntry:map
   2294             extensionRegistry:extensionRegistry
   2295                         field:fieldDescriptor
   2296                 parentMessage:self];
   2297         }
   2298         merged = YES;
   2299         break;
   2300       } else {
   2301         startingIndex += 1;
   2302       }
   2303     }  // for(i < numFields)
   2304 
   2305     if (!merged) {
   2306       // Primitive, repeated types can be packed on unpacked on the wire, and
   2307       // are parsed either way.  The above loop covered tag in the preferred
   2308       // for, so this need to check the alternate form.
   2309       for (NSUInteger i = 0; i < numFields; ++i) {
   2310         if (startingIndex >= numFields) startingIndex = 0;
   2311         GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
   2312         if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) &&
   2313             !GPBFieldDataTypeIsObject(fieldDescriptor) &&
   2314             (GPBFieldAlternateTag(fieldDescriptor) == tag)) {
   2315           BOOL alternateIsPacked = !fieldDescriptor.isPackable;
   2316           if (alternateIsPacked) {
   2317             MergeRepeatedPackedFieldFromCodedInputStream(
   2318                 self, fieldDescriptor, syntax, input);
   2319             // Well formed protos will only have a repeated field that is
   2320             // packed once, advance the starting index to the next field.
   2321             startingIndex += 1;
   2322           } else {
   2323             MergeRepeatedNotPackedFieldFromCodedInputStream(
   2324                 self, fieldDescriptor, syntax, input, extensionRegistry);
   2325           }
   2326           merged = YES;
   2327           break;
   2328         } else {
   2329           startingIndex += 1;
   2330         }
   2331       }
   2332     }
   2333 
   2334     if (!merged) {
   2335       if (tag == 0) {
   2336         // zero signals EOF / limit reached
   2337         return;
   2338       } else {
   2339         if (GPBPreserveUnknownFields(syntax)) {
   2340           if (![self parseUnknownField:input
   2341                      extensionRegistry:extensionRegistry
   2342                                    tag:tag]) {
   2343             // it's an endgroup tag
   2344             return;
   2345           }
   2346         } else {
   2347           if (![input skipField:tag]) {
   2348             return;
   2349           }
   2350         }
   2351       }
   2352     }  // if(!merged)
   2353 
   2354   }  // while(YES)
   2355 }
   2356 
   2357 #pragma mark - MergeFrom Support
   2358 
   2359 - (void)mergeFrom:(GPBMessage *)other {
   2360   Class selfClass = [self class];
   2361   Class otherClass = [other class];
   2362   if (!([selfClass isSubclassOfClass:otherClass] ||
   2363         [otherClass isSubclassOfClass:selfClass])) {
   2364     [NSException raise:NSInvalidArgumentException
   2365                 format:@"Classes must match %@ != %@", selfClass, otherClass];
   2366   }
   2367 
   2368   // We assume something will be done and become visible.
   2369   GPBBecomeVisibleToAutocreator(self);
   2370 
   2371   GPBDescriptor *descriptor = [[self class] descriptor];
   2372   GPBFileSyntax syntax = descriptor.file.syntax;
   2373 
   2374   for (GPBFieldDescriptor *field in descriptor->fields_) {
   2375     GPBFieldType fieldType = field.fieldType;
   2376     if (fieldType == GPBFieldTypeSingle) {
   2377       int32_t hasIndex = GPBFieldHasIndex(field);
   2378       uint32_t fieldNumber = GPBFieldNumber(field);
   2379       if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) {
   2380         // Other doesn't have the field set, on to the next.
   2381         continue;
   2382       }
   2383       GPBDataType fieldDataType = GPBGetFieldDataType(field);
   2384       switch (fieldDataType) {
   2385         case GPBDataTypeBool:
   2386           GPBSetBoolIvarWithFieldInternal(
   2387               self, field, GPBGetMessageBoolField(other, field), syntax);
   2388           break;
   2389         case GPBDataTypeSFixed32:
   2390         case GPBDataTypeEnum:
   2391         case GPBDataTypeInt32:
   2392         case GPBDataTypeSInt32:
   2393           GPBSetInt32IvarWithFieldInternal(
   2394               self, field, GPBGetMessageInt32Field(other, field), syntax);
   2395           break;
   2396         case GPBDataTypeFixed32:
   2397         case GPBDataTypeUInt32:
   2398           GPBSetUInt32IvarWithFieldInternal(
   2399               self, field, GPBGetMessageUInt32Field(other, field), syntax);
   2400           break;
   2401         case GPBDataTypeSFixed64:
   2402         case GPBDataTypeInt64:
   2403         case GPBDataTypeSInt64:
   2404           GPBSetInt64IvarWithFieldInternal(
   2405               self, field, GPBGetMessageInt64Field(other, field), syntax);
   2406           break;
   2407         case GPBDataTypeFixed64:
   2408         case GPBDataTypeUInt64:
   2409           GPBSetUInt64IvarWithFieldInternal(
   2410               self, field, GPBGetMessageUInt64Field(other, field), syntax);
   2411           break;
   2412         case GPBDataTypeFloat:
   2413           GPBSetFloatIvarWithFieldInternal(
   2414               self, field, GPBGetMessageFloatField(other, field), syntax);
   2415           break;
   2416         case GPBDataTypeDouble:
   2417           GPBSetDoubleIvarWithFieldInternal(
   2418               self, field, GPBGetMessageDoubleField(other, field), syntax);
   2419           break;
   2420         case GPBDataTypeBytes:
   2421         case GPBDataTypeString: {
   2422           id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
   2423           GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax);
   2424           break;
   2425         }
   2426         case GPBDataTypeMessage:
   2427         case GPBDataTypeGroup: {
   2428           id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
   2429           if (GPBGetHasIvar(self, hasIndex, fieldNumber)) {
   2430             GPBMessage *message =
   2431                 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   2432             [message mergeFrom:otherVal];
   2433           } else {
   2434             GPBMessage *message = [otherVal copy];
   2435             GPBSetRetainedObjectIvarWithFieldInternal(self, field, message,
   2436                                                       syntax);
   2437           }
   2438           break;
   2439         }
   2440       } // switch()
   2441     } else if (fieldType == GPBFieldTypeRepeated) {
   2442       // In the case of a list, they need to be appended, and there is no
   2443       // _hasIvar to worry about setting.
   2444       id otherArray =
   2445           GPBGetObjectIvarWithFieldNoAutocreate(other, field);
   2446       if (otherArray) {
   2447         GPBDataType fieldDataType = field->description_->dataType;
   2448         if (GPBDataTypeIsObject(fieldDataType)) {
   2449           NSMutableArray *resultArray =
   2450               GetOrCreateArrayIvarWithField(self, field, syntax);
   2451           [resultArray addObjectsFromArray:otherArray];
   2452         } else if (fieldDataType == GPBDataTypeEnum) {
   2453           GPBEnumArray *resultArray =
   2454               GetOrCreateArrayIvarWithField(self, field, syntax);
   2455           [resultArray addRawValuesFromArray:otherArray];
   2456         } else {
   2457           // The array type doesn't matter, that all implment
   2458           // -addValuesFromArray:.
   2459           GPBInt32Array *resultArray =
   2460               GetOrCreateArrayIvarWithField(self, field, syntax);
   2461           [resultArray addValuesFromArray:otherArray];
   2462         }
   2463       }
   2464     } else {  // fieldType = GPBFieldTypeMap
   2465       // In the case of a map, they need to be merged, and there is no
   2466       // _hasIvar to worry about setting.
   2467       id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
   2468       if (otherDict) {
   2469         GPBDataType keyDataType = field.mapKeyDataType;
   2470         GPBDataType valueDataType = field->description_->dataType;
   2471         if (GPBDataTypeIsObject(keyDataType) &&
   2472             GPBDataTypeIsObject(valueDataType)) {
   2473           NSMutableDictionary *resultDict =
   2474               GetOrCreateMapIvarWithField(self, field, syntax);
   2475           [resultDict addEntriesFromDictionary:otherDict];
   2476         } else if (valueDataType == GPBDataTypeEnum) {
   2477           // The exact type doesn't matter, just need to know it is a
   2478           // GPB*EnumDictionary.
   2479           GPBInt32EnumDictionary *resultDict =
   2480               GetOrCreateMapIvarWithField(self, field, syntax);
   2481           [resultDict addRawEntriesFromDictionary:otherDict];
   2482         } else {
   2483           // The exact type doesn't matter, they all implement
   2484           // -addEntriesFromDictionary:.
   2485           GPBInt32Int32Dictionary *resultDict =
   2486               GetOrCreateMapIvarWithField(self, field, syntax);
   2487           [resultDict addEntriesFromDictionary:otherDict];
   2488         }
   2489       }
   2490     }  // if (fieldType)..else if...else
   2491   }  // for(fields)
   2492 
   2493   // Unknown fields.
   2494   if (!unknownFields_) {
   2495     [self setUnknownFields:other.unknownFields];
   2496   } else {
   2497     [unknownFields_ mergeUnknownFields:other.unknownFields];
   2498   }
   2499 
   2500   // Extensions
   2501 
   2502   if (other->extensionMap_.count == 0) {
   2503     return;
   2504   }
   2505 
   2506   if (extensionMap_ == nil) {
   2507     extensionMap_ =
   2508         CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self));
   2509   } else {
   2510     for (GPBExtensionDescriptor *extension in other->extensionMap_) {
   2511       id otherValue = [other->extensionMap_ objectForKey:extension];
   2512       id value = [extensionMap_ objectForKey:extension];
   2513       BOOL isMessageExtension = GPBExtensionIsMessage(extension);
   2514 
   2515       if (extension.repeated) {
   2516         NSMutableArray *list = value;
   2517         if (list == nil) {
   2518           list = [[NSMutableArray alloc] init];
   2519           [extensionMap_ setObject:list forKey:extension];
   2520           [list release];
   2521         }
   2522         if (isMessageExtension) {
   2523           for (GPBMessage *otherListValue in otherValue) {
   2524             GPBMessage *copiedValue = [otherListValue copy];
   2525             [list addObject:copiedValue];
   2526             [copiedValue release];
   2527           }
   2528         } else {
   2529           [list addObjectsFromArray:otherValue];
   2530         }
   2531       } else {
   2532         if (isMessageExtension) {
   2533           if (value) {
   2534             [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue];
   2535           } else {
   2536             GPBMessage *copiedValue = [otherValue copy];
   2537             [extensionMap_ setObject:copiedValue forKey:extension];
   2538             [copiedValue release];
   2539           }
   2540         } else {
   2541           [extensionMap_ setObject:otherValue forKey:extension];
   2542         }
   2543       }
   2544 
   2545       if (isMessageExtension && !extension.isRepeated) {
   2546         GPBMessage *autocreatedValue =
   2547             [[autocreatedExtensionMap_ objectForKey:extension] retain];
   2548         // Must remove from the map before calling GPBClearMessageAutocreator()
   2549         // so that GPBClearMessageAutocreator() knows its safe to clear.
   2550         [autocreatedExtensionMap_ removeObjectForKey:extension];
   2551         GPBClearMessageAutocreator(autocreatedValue);
   2552         [autocreatedValue release];
   2553       }
   2554     }
   2555   }
   2556 }
   2557 
   2558 #pragma mark - isEqual: & hash Support
   2559 
   2560 - (BOOL)isEqual:(GPBMessage *)other {
   2561   if (other == self) {
   2562     return YES;
   2563   }
   2564   if (![other isKindOfClass:[self class]] &&
   2565       ![self isKindOfClass:[other class]]) {
   2566     return NO;
   2567   }
   2568 
   2569   GPBDescriptor *descriptor = [[self class] descriptor];
   2570   uint8_t *selfStorage = (uint8_t *)messageStorage_;
   2571   uint8_t *otherStorage = (uint8_t *)other->messageStorage_;
   2572 
   2573   for (GPBFieldDescriptor *field in descriptor->fields_) {
   2574     if (GPBFieldIsMapOrArray(field)) {
   2575       // In the case of a list or map, there is no _hasIvar to worry about.
   2576       // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but
   2577       // the type doesn't really matter as the objects all support -count and
   2578       // -isEqual:.
   2579       NSArray *resultMapOrArray =
   2580           GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   2581       NSArray *otherMapOrArray =
   2582           GPBGetObjectIvarWithFieldNoAutocreate(other, field);
   2583       // nil and empty are equal
   2584       if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) {
   2585         if (![resultMapOrArray isEqual:otherMapOrArray]) {
   2586           return NO;
   2587         }
   2588       }
   2589     } else {  // Single field
   2590       int32_t hasIndex = GPBFieldHasIndex(field);
   2591       uint32_t fieldNum = GPBFieldNumber(field);
   2592       BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum);
   2593       BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum);
   2594       if (selfHas != otherHas) {
   2595         return NO;  // Differing has values, not equal.
   2596       }
   2597       if (!selfHas) {
   2598         // Same has values, was no, nothing else to check for this field.
   2599         continue;
   2600       }
   2601       // Now compare the values.
   2602       GPBDataType fieldDataType = GPBGetFieldDataType(field);
   2603       size_t fieldOffset = field->description_->offset;
   2604       switch (fieldDataType) {
   2605         case GPBDataTypeBool: {
   2606           // Bools are stored in has_bits to avoid needing explicit space in
   2607           // the storage structure.
   2608           // (the field number passed to the HasIvar helper doesn't really
   2609           // matter since the offset is never negative)
   2610           BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0);
   2611           BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0);
   2612           if (selfValue != otherValue) {
   2613             return NO;
   2614           }
   2615           break;
   2616         }
   2617         case GPBDataTypeSFixed32:
   2618         case GPBDataTypeInt32:
   2619         case GPBDataTypeSInt32:
   2620         case GPBDataTypeEnum:
   2621         case GPBDataTypeFixed32:
   2622         case GPBDataTypeUInt32:
   2623         case GPBDataTypeFloat: {
   2624           _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
   2625           // These are all 32bit, signed/unsigned doesn't matter for equality.
   2626           uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset];
   2627           uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset];
   2628           if (*selfValPtr != *otherValPtr) {
   2629             return NO;
   2630           }
   2631           break;
   2632         }
   2633         case GPBDataTypeSFixed64:
   2634         case GPBDataTypeInt64:
   2635         case GPBDataTypeSInt64:
   2636         case GPBDataTypeFixed64:
   2637         case GPBDataTypeUInt64:
   2638         case GPBDataTypeDouble: {
   2639           _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
   2640           // These are all 64bit, signed/unsigned doesn't matter for equality.
   2641           uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset];
   2642           uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset];
   2643           if (*selfValPtr != *otherValPtr) {
   2644             return NO;
   2645           }
   2646           break;
   2647         }
   2648         case GPBDataTypeBytes:
   2649         case GPBDataTypeString:
   2650         case GPBDataTypeMessage:
   2651         case GPBDataTypeGroup: {
   2652           // Type doesn't matter here, they all implement -isEqual:.
   2653           id *selfValPtr = (id *)&selfStorage[fieldOffset];
   2654           id *otherValPtr = (id *)&otherStorage[fieldOffset];
   2655           if (![*selfValPtr isEqual:*otherValPtr]) {
   2656             return NO;
   2657           }
   2658           break;
   2659         }
   2660       } // switch()
   2661     }   // if(mapOrArray)...else
   2662   }  // for(fields)
   2663 
   2664   // nil and empty are equal
   2665   if (extensionMap_.count != 0 || other->extensionMap_.count != 0) {
   2666     if (![extensionMap_ isEqual:other->extensionMap_]) {
   2667       return NO;
   2668     }
   2669   }
   2670 
   2671   // nil and empty are equal
   2672   GPBUnknownFieldSet *otherUnknowns = other->unknownFields_;
   2673   if ([unknownFields_ countOfFields] != 0 ||
   2674       [otherUnknowns countOfFields] != 0) {
   2675     if (![unknownFields_ isEqual:otherUnknowns]) {
   2676       return NO;
   2677     }
   2678   }
   2679 
   2680   return YES;
   2681 }
   2682 
   2683 // It is very difficult to implement a generic hash for ProtoBuf messages that
   2684 // will perform well. If you need hashing on your ProtoBufs (eg you are using
   2685 // them as dictionary keys) you will probably want to implement a ProtoBuf
   2686 // message specific hash as a category on your protobuf class. Do not make it a
   2687 // category on GPBMessage as you will conflict with this hash, and will possibly
   2688 // override hash for all generated protobufs. A good implementation of hash will
   2689 // be really fast, so we would recommend only hashing protobufs that have an
   2690 // identifier field of some kind that you can easily hash. If you implement
   2691 // hash, we would strongly recommend overriding isEqual: in your category as
   2692 // well, as the default implementation of isEqual: is extremely slow, and may
   2693 // drastically affect performance in large sets.
   2694 - (NSUInteger)hash {
   2695   GPBDescriptor *descriptor = [[self class] descriptor];
   2696   const NSUInteger prime = 19;
   2697   uint8_t *storage = (uint8_t *)messageStorage_;
   2698 
   2699   // Start with the descriptor and then mix it with some instance info.
   2700   // Hopefully that will give a spread based on classes and what fields are set.
   2701   NSUInteger result = (NSUInteger)descriptor;
   2702 
   2703   for (GPBFieldDescriptor *field in descriptor->fields_) {
   2704     if (GPBFieldIsMapOrArray(field)) {
   2705       // Exact type doesn't matter, just check if there are any elements.
   2706       NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   2707       NSUInteger count = mapOrArray.count;
   2708       if (count) {
   2709         // NSArray/NSDictionary use count, use the field number and the count.
   2710         result = prime * result + GPBFieldNumber(field);
   2711         result = prime * result + count;
   2712       }
   2713     } else if (GPBGetHasIvarField(self, field)) {
   2714       // Just using the field number seemed simple/fast, but then a small
   2715       // message class where all the same fields are always set (to different
   2716       // things would end up all with the same hash, so pull in some data).
   2717       GPBDataType fieldDataType = GPBGetFieldDataType(field);
   2718       size_t fieldOffset = field->description_->offset;
   2719       switch (fieldDataType) {
   2720         case GPBDataTypeBool: {
   2721           // Bools are stored in has_bits to avoid needing explicit space in
   2722           // the storage structure.
   2723           // (the field number passed to the HasIvar helper doesn't really
   2724           // matter since the offset is never negative)
   2725           BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0);
   2726           result = prime * result + value;
   2727           break;
   2728         }
   2729         case GPBDataTypeSFixed32:
   2730         case GPBDataTypeInt32:
   2731         case GPBDataTypeSInt32:
   2732         case GPBDataTypeEnum:
   2733         case GPBDataTypeFixed32:
   2734         case GPBDataTypeUInt32:
   2735         case GPBDataTypeFloat: {
   2736           _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
   2737           // These are all 32bit, just mix it in.
   2738           uint32_t *valPtr = (uint32_t *)&storage[fieldOffset];
   2739           result = prime * result + *valPtr;
   2740           break;
   2741         }
   2742         case GPBDataTypeSFixed64:
   2743         case GPBDataTypeInt64:
   2744         case GPBDataTypeSInt64:
   2745         case GPBDataTypeFixed64:
   2746         case GPBDataTypeUInt64:
   2747         case GPBDataTypeDouble: {
   2748           _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
   2749           // These are all 64bit, just mix what fits into an NSUInteger in.
   2750           uint64_t *valPtr = (uint64_t *)&storage[fieldOffset];
   2751           result = prime * result + (NSUInteger)(*valPtr);
   2752           break;
   2753         }
   2754         case GPBDataTypeBytes:
   2755         case GPBDataTypeString: {
   2756           // Type doesn't matter here, they both implement -hash:.
   2757           id *valPtr = (id *)&storage[fieldOffset];
   2758           result = prime * result + [*valPtr hash];
   2759           break;
   2760         }
   2761 
   2762         case GPBDataTypeMessage:
   2763         case GPBDataTypeGroup: {
   2764           GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset];
   2765           // Could call -hash on the sub message, but that could recurse pretty
   2766           // deep; follow the lead of NSArray/NSDictionary and don't really
   2767           // recurse for hash, instead use the field number and the descriptor
   2768           // of the sub message.  Yes, this could suck for a bunch of messages
   2769           // where they all only differ in the sub messages, but if you are
   2770           // using a message with sub messages for something that needs -hash,
   2771           // odds are you are also copying them as keys, and that deep copy
   2772           // will also suck.
   2773           result = prime * result + GPBFieldNumber(field);
   2774           result = prime * result + (NSUInteger)[[*valPtr class] descriptor];
   2775           break;
   2776         }
   2777       } // switch()
   2778     }
   2779   }
   2780 
   2781   // Unknowns and extensions are not included.
   2782 
   2783   return result;
   2784 }
   2785 
   2786 #pragma mark - Description Support
   2787 
   2788 - (NSString *)description {
   2789   NSString *textFormat = GPBTextFormatForMessage(self, @"    ");
   2790   NSString *description = [NSString
   2791       stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat];
   2792   return description;
   2793 }
   2794 
   2795 #if DEBUG
   2796 
   2797 // Xcode 5.1 added support for custom quick look info.
   2798 // https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/CustomClassDisplay_in_QuickLook/CH01-quick_look_for_custom_objects/CH01-quick_look_for_custom_objects.html#//apple_ref/doc/uid/TP40014001-CH2-SW1
   2799 - (id)debugQuickLookObject {
   2800   return GPBTextFormatForMessage(self, nil);
   2801 }
   2802 
   2803 #endif  // DEBUG
   2804 
   2805 #pragma mark - SerializedSize
   2806 
   2807 - (size_t)serializedSize {
   2808   GPBDescriptor *descriptor = [[self class] descriptor];
   2809   size_t result = 0;
   2810 
   2811   // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate()
   2812   // avoids doing the has check again.
   2813 
   2814   // Fields.
   2815   for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
   2816     GPBFieldType fieldType = fieldDescriptor.fieldType;
   2817     GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor);
   2818 
   2819     // Single Fields
   2820     if (fieldType == GPBFieldTypeSingle) {
   2821       BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor);
   2822       if (!selfHas) {
   2823         continue;  // Nothing to do.
   2824       }
   2825 
   2826       uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor);
   2827 
   2828       switch (fieldDataType) {
   2829 #define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                                \
   2830         case GPBDataType##NAME: {                                             \
   2831           TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \
   2832           result += GPBCompute##NAME##Size(fieldNumber, fieldVal);            \
   2833           break;                                                              \
   2834         }
   2835 #define CASE_SINGLE_OBJECT(NAME)                                              \
   2836         case GPBDataType##NAME: {                                             \
   2837           id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \
   2838           result += GPBCompute##NAME##Size(fieldNumber, fieldVal);            \
   2839           break;                                                              \
   2840         }
   2841           CASE_SINGLE_POD(Bool, BOOL, Bool)
   2842           CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
   2843           CASE_SINGLE_POD(SFixed32, int32_t, Int32)
   2844           CASE_SINGLE_POD(Float, float, Float)
   2845           CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
   2846           CASE_SINGLE_POD(SFixed64, int64_t, Int64)
   2847           CASE_SINGLE_POD(Double, double, Double)
   2848           CASE_SINGLE_POD(Int32, int32_t, Int32)
   2849           CASE_SINGLE_POD(Int64, int64_t, Int64)
   2850           CASE_SINGLE_POD(SInt32, int32_t, Int32)
   2851           CASE_SINGLE_POD(SInt64, int64_t, Int64)
   2852           CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
   2853           CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
   2854           CASE_SINGLE_OBJECT(Bytes)
   2855           CASE_SINGLE_OBJECT(String)
   2856           CASE_SINGLE_OBJECT(Message)
   2857           CASE_SINGLE_OBJECT(Group)
   2858           CASE_SINGLE_POD(Enum, int32_t, Int32)
   2859 #undef CASE_SINGLE_POD
   2860 #undef CASE_SINGLE_OBJECT
   2861       }
   2862 
   2863     // Repeated Fields
   2864     } else if (fieldType == GPBFieldTypeRepeated) {
   2865       id genericArray =
   2866           GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
   2867       NSUInteger count = [genericArray count];
   2868       if (count == 0) {
   2869         continue;  // Nothing to add.
   2870       }
   2871       __block size_t dataSize = 0;
   2872 
   2873       switch (fieldDataType) {
   2874 #define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE)                             \
   2875     CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, )
   2876 #define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME)  \
   2877         case GPBDataType##NAME: {                                             \
   2878           GPB##ARRAY_TYPE##Array *array = genericArray;                       \
   2879           [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \
   2880             _Pragma("unused(idx, stop)");                                     \
   2881             dataSize += GPBCompute##NAME##SizeNoTag(value);                   \
   2882           }];                                                                 \
   2883           break;                                                              \
   2884         }
   2885 #define CASE_REPEATED_OBJECT(NAME)                                            \
   2886         case GPBDataType##NAME: {                                             \
   2887           for (id value in genericArray) {                                    \
   2888             dataSize += GPBCompute##NAME##SizeNoTag(value);                   \
   2889           }                                                                   \
   2890           break;                                                              \
   2891         }
   2892           CASE_REPEATED_POD(Bool, BOOL, Bool)
   2893           CASE_REPEATED_POD(Fixed32, uint32_t, UInt32)
   2894           CASE_REPEATED_POD(SFixed32, int32_t, Int32)
   2895           CASE_REPEATED_POD(Float, float, Float)
   2896           CASE_REPEATED_POD(Fixed64, uint64_t, UInt64)
   2897           CASE_REPEATED_POD(SFixed64, int64_t, Int64)
   2898           CASE_REPEATED_POD(Double, double, Double)
   2899           CASE_REPEATED_POD(Int32, int32_t, Int32)
   2900           CASE_REPEATED_POD(Int64, int64_t, Int64)
   2901           CASE_REPEATED_POD(SInt32, int32_t, Int32)
   2902           CASE_REPEATED_POD(SInt64, int64_t, Int64)
   2903           CASE_REPEATED_POD(UInt32, uint32_t, UInt32)
   2904           CASE_REPEATED_POD(UInt64, uint64_t, UInt64)
   2905           CASE_REPEATED_OBJECT(Bytes)
   2906           CASE_REPEATED_OBJECT(String)
   2907           CASE_REPEATED_OBJECT(Message)
   2908           CASE_REPEATED_OBJECT(Group)
   2909           CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw)
   2910 #undef CASE_REPEATED_POD
   2911 #undef CASE_REPEATED_POD_EXTRA
   2912 #undef CASE_REPEATED_OBJECT
   2913       }  // switch
   2914       result += dataSize;
   2915       size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor));
   2916       if (fieldDataType == GPBDataTypeGroup) {
   2917         // Groups have both a start and an end tag.
   2918         tagSize *= 2;
   2919       }
   2920       if (fieldDescriptor.isPackable) {
   2921         result += tagSize;
   2922         result += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
   2923       } else {
   2924         result += count * tagSize;
   2925       }
   2926 
   2927     // Map<> Fields
   2928     } else {  // fieldType == GPBFieldTypeMap
   2929       if (GPBDataTypeIsObject(fieldDataType) &&
   2930           (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) {
   2931         // If key type was string, then the map is an NSDictionary.
   2932         NSDictionary *map =
   2933             GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
   2934         if (map) {
   2935           result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor);
   2936         }
   2937       } else {
   2938         // Type will be GPB*GroupDictionary, exact type doesn't matter.
   2939         GPBInt32Int32Dictionary *map =
   2940             GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
   2941         result += [map computeSerializedSizeAsField:fieldDescriptor];
   2942       }
   2943     }
   2944   }  // for(fields)
   2945 
   2946   // Add any unknown fields.
   2947   if (descriptor.wireFormat) {
   2948     result += [unknownFields_ serializedSizeAsMessageSet];
   2949   } else {
   2950     result += [unknownFields_ serializedSize];
   2951   }
   2952 
   2953   // Add any extensions.
   2954   for (GPBExtensionDescriptor *extension in extensionMap_) {
   2955     id value = [extensionMap_ objectForKey:extension];
   2956     result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value);
   2957   }
   2958 
   2959   return result;
   2960 }
   2961 
   2962 #pragma mark - Resolve Methods Support
   2963 
   2964 typedef struct ResolveIvarAccessorMethodResult {
   2965   IMP impToAdd;
   2966   SEL encodingSelector;
   2967 } ResolveIvarAccessorMethodResult;
   2968 
   2969 static void ResolveIvarGet(GPBFieldDescriptor *field,
   2970                            ResolveIvarAccessorMethodResult *result) {
   2971   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   2972   switch (fieldDataType) {
   2973 #define CASE_GET(NAME, TYPE, TRUE_NAME)                          \
   2974     case GPBDataType##NAME: {                                    \
   2975       result->impToAdd = imp_implementationWithBlock(^(id obj) { \
   2976         return GPBGetMessage##TRUE_NAME##Field(obj, field);      \
   2977        });                                                       \
   2978       result->encodingSelector = @selector(get##NAME);           \
   2979       break;                                                     \
   2980     }
   2981 #define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME)                   \
   2982     case GPBDataType##NAME: {                                    \
   2983       result->impToAdd = imp_implementationWithBlock(^(id obj) { \
   2984         return GPBGetObjectIvarWithField(obj, field);            \
   2985        });                                                       \
   2986       result->encodingSelector = @selector(get##NAME);           \
   2987       break;                                                     \
   2988     }
   2989       CASE_GET(Bool, BOOL, Bool)
   2990       CASE_GET(Fixed32, uint32_t, UInt32)
   2991       CASE_GET(SFixed32, int32_t, Int32)
   2992       CASE_GET(Float, float, Float)
   2993       CASE_GET(Fixed64, uint64_t, UInt64)
   2994       CASE_GET(SFixed64, int64_t, Int64)
   2995       CASE_GET(Double, double, Double)
   2996       CASE_GET(Int32, int32_t, Int32)
   2997       CASE_GET(Int64, int64_t, Int64)
   2998       CASE_GET(SInt32, int32_t, Int32)
   2999       CASE_GET(SInt64, int64_t, Int64)
   3000       CASE_GET(UInt32, uint32_t, UInt32)
   3001       CASE_GET(UInt64, uint64_t, UInt64)
   3002       CASE_GET_OBJECT(Bytes, id, Object)
   3003       CASE_GET_OBJECT(String, id, Object)
   3004       CASE_GET_OBJECT(Message, id, Object)
   3005       CASE_GET_OBJECT(Group, id, Object)
   3006       CASE_GET(Enum, int32_t, Enum)
   3007 #undef CASE_GET
   3008   }
   3009 }
   3010 
   3011 static void ResolveIvarSet(GPBFieldDescriptor *field,
   3012                            GPBFileSyntax syntax,
   3013                            ResolveIvarAccessorMethodResult *result) {
   3014   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   3015   switch (fieldDataType) {
   3016 #define CASE_SET(NAME, TYPE, TRUE_NAME)                                       \
   3017     case GPBDataType##NAME: {                                                 \
   3018       result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) {  \
   3019         return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \
   3020       });                                                                     \
   3021       result->encodingSelector = @selector(set##NAME:);                       \
   3022       break;                                                                  \
   3023     }
   3024       CASE_SET(Bool, BOOL, Bool)
   3025       CASE_SET(Fixed32, uint32_t, UInt32)
   3026       CASE_SET(SFixed32, int32_t, Int32)
   3027       CASE_SET(Float, float, Float)
   3028       CASE_SET(Fixed64, uint64_t, UInt64)
   3029       CASE_SET(SFixed64, int64_t, Int64)
   3030       CASE_SET(Double, double, Double)
   3031       CASE_SET(Int32, int32_t, Int32)
   3032       CASE_SET(Int64, int64_t, Int64)
   3033       CASE_SET(SInt32, int32_t, Int32)
   3034       CASE_SET(SInt64, int64_t, Int64)
   3035       CASE_SET(UInt32, uint32_t, UInt32)
   3036       CASE_SET(UInt64, uint64_t, UInt64)
   3037       CASE_SET(Bytes, id, Object)
   3038       CASE_SET(String, id, Object)
   3039       CASE_SET(Message, id, Object)
   3040       CASE_SET(Group, id, Object)
   3041       CASE_SET(Enum, int32_t, Enum)
   3042 #undef CASE_SET
   3043   }
   3044 }
   3045 
   3046 + (BOOL)resolveInstanceMethod:(SEL)sel {
   3047   const GPBDescriptor *descriptor = [self descriptor];
   3048   if (!descriptor) {
   3049     return NO;
   3050   }
   3051 
   3052   // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given
   3053   // message should not have has support (done in GPBDescriptor.m), so there is
   3054   // no need for checks here to see if has*/setHas* are allowed.
   3055 
   3056   ResolveIvarAccessorMethodResult result = {NULL, NULL};
   3057   for (GPBFieldDescriptor *field in descriptor->fields_) {
   3058     BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
   3059     if (!isMapOrArray) {
   3060       // Single fields.
   3061       if (sel == field->getSel_) {
   3062         ResolveIvarGet(field, &result);
   3063         break;
   3064       } else if (sel == field->setSel_) {
   3065         ResolveIvarSet(field, descriptor.file.syntax, &result);
   3066         break;
   3067       } else if (sel == field->hasOrCountSel_) {
   3068         int32_t index = GPBFieldHasIndex(field);
   3069         uint32_t fieldNum = GPBFieldNumber(field);
   3070         result.impToAdd = imp_implementationWithBlock(^(id obj) {
   3071           return GPBGetHasIvar(obj, index, fieldNum);
   3072         });
   3073         result.encodingSelector = @selector(getBool);
   3074         break;
   3075       } else if (sel == field->setHasSel_) {
   3076         result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
   3077           if (value) {
   3078             [NSException raise:NSInvalidArgumentException
   3079                         format:@"%@: %@ can only be set to NO (to clear field).",
   3080                                [obj class],
   3081                                NSStringFromSelector(field->setHasSel_)];
   3082           }
   3083           GPBClearMessageField(obj, field);
   3084         });
   3085         result.encodingSelector = @selector(setBool:);
   3086         break;
   3087       } else {
   3088         GPBOneofDescriptor *oneof = field->containingOneof_;
   3089         if (oneof && (sel == oneof->caseSel_)) {
   3090           int32_t index = GPBFieldHasIndex(field);
   3091           result.impToAdd = imp_implementationWithBlock(^(id obj) {
   3092             return GPBGetHasOneof(obj, index);
   3093           });
   3094           result.encodingSelector = @selector(getEnum);
   3095           break;
   3096         }
   3097       }
   3098     } else {
   3099       // map<>/repeated fields.
   3100       if (sel == field->getSel_) {
   3101         if (field.fieldType == GPBFieldTypeRepeated) {
   3102           result.impToAdd = imp_implementationWithBlock(^(id obj) {
   3103             return GetArrayIvarWithField(obj, field);
   3104           });
   3105         } else {
   3106           result.impToAdd = imp_implementationWithBlock(^(id obj) {
   3107             return GetMapIvarWithField(obj, field);
   3108           });
   3109         }
   3110         result.encodingSelector = @selector(getArray);
   3111         break;
   3112       } else if (sel == field->setSel_) {
   3113         // Local for syntax so the block can directly capture it and not the
   3114         // full lookup.
   3115         const GPBFileSyntax syntax = descriptor.file.syntax;
   3116         result.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
   3117           return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
   3118         });
   3119         result.encodingSelector = @selector(setArray:);
   3120         break;
   3121       } else if (sel == field->hasOrCountSel_) {
   3122         result.impToAdd = imp_implementationWithBlock(^(id obj) {
   3123           // Type doesn't matter, all *Array and *Dictionary types support
   3124           // -count.
   3125           NSArray *arrayOrMap =
   3126               GPBGetObjectIvarWithFieldNoAutocreate(obj, field);
   3127           return [arrayOrMap count];
   3128         });
   3129         result.encodingSelector = @selector(getArrayCount);
   3130         break;
   3131       }
   3132     }
   3133   }
   3134   if (result.impToAdd) {
   3135     const char *encoding =
   3136         GPBMessageEncodingForSelector(result.encodingSelector, YES);
   3137     BOOL methodAdded = class_addMethod(descriptor.messageClass, sel,
   3138                                        result.impToAdd, encoding);
   3139     return methodAdded;
   3140   }
   3141   return [super resolveInstanceMethod:sel];
   3142 }
   3143 
   3144 + (BOOL)resolveClassMethod:(SEL)sel {
   3145   // Extensions scoped to a Message and looked up via class methods.
   3146   if (GPBResolveExtensionClassMethod(self, sel)) {
   3147     return YES;
   3148   }
   3149   return [super resolveClassMethod:sel];
   3150 }
   3151 
   3152 #pragma mark - NSCoding Support
   3153 
   3154 + (BOOL)supportsSecureCoding {
   3155   return YES;
   3156 }
   3157 
   3158 - (instancetype)initWithCoder:(NSCoder *)aDecoder {
   3159   self = [self init];
   3160   if (self) {
   3161     NSData *data =
   3162         [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey];
   3163     if (data.length) {
   3164       [self mergeFromData:data extensionRegistry:nil];
   3165     }
   3166   }
   3167   return self;
   3168 }
   3169 
   3170 - (void)encodeWithCoder:(NSCoder *)aCoder {
   3171   NSData *data = [self data];
   3172   if (data.length) {
   3173     [aCoder encodeObject:data forKey:kGPBDataCoderKey];
   3174   }
   3175 }
   3176 
   3177 #pragma mark - KVC Support
   3178 
   3179 + (BOOL)accessInstanceVariablesDirectly {
   3180   // Make sure KVC doesn't use instance variables.
   3181   return NO;
   3182 }
   3183 
   3184 @end
   3185