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