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