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