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