• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3//
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
7
8#import "GPBMessage.h"
9#import "GPBMessage_PackagePrivate.h"
10
11#import <Foundation/Foundation.h>
12#import <objc/message.h>
13#import <objc/runtime.h>
14#import <os/lock.h>
15#import <stdatomic.h>
16
17#import "GPBArray.h"
18#import "GPBArray_PackagePrivate.h"
19#import "GPBCodedInputStream.h"
20#import "GPBCodedInputStream_PackagePrivate.h"
21#import "GPBCodedOutputStream.h"
22#import "GPBCodedOutputStream_PackagePrivate.h"
23#import "GPBDescriptor.h"
24#import "GPBDescriptor_PackagePrivate.h"
25#import "GPBDictionary.h"
26#import "GPBDictionary_PackagePrivate.h"
27#import "GPBExtensionInternals.h"
28#import "GPBExtensionRegistry.h"
29#import "GPBRootObject.h"
30#import "GPBRootObject_PackagePrivate.h"
31#import "GPBUnknownField.h"
32#import "GPBUnknownFieldSet.h"
33#import "GPBUnknownFieldSet_PackagePrivate.h"
34#import "GPBUnknownFields.h"
35#import "GPBUnknownFields_PackagePrivate.h"
36#import "GPBUtilities.h"
37#import "GPBUtilities_PackagePrivate.h"
38
39// TODO: Consider using on other functions to reduce bloat when
40// some compiler optimizations are enabled.
41#define GPB_NOINLINE __attribute__((noinline))
42
43// Returns a new instance that was automatically created by |autocreator| for
44// its field |field|.
45static GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, GPBMessage *autocreator,
46                                                   GPBFieldDescriptor *field)
47    __attribute__((ns_returns_retained));
48
49// Direct access is use for speed, to avoid even internally declaring things
50// read/write, etc. The warning is enabled in the project to ensure code calling
51// protos can turn on -Wdirect-ivar-access without issues.
52#pragma clang diagnostic push
53#pragma clang diagnostic ignored "-Wdirect-ivar-access"
54
55NSString *const GPBMessageErrorDomain = GPBNSStringifySymbol(GPBMessageErrorDomain);
56
57NSString *const GPBErrorReasonKey = @"Reason";
58
59static NSString *const kGPBDataCoderKey = @"GPBData";
60
61// Length-delimited has a max size of 2GB, and thus messages do also.
62// src/google/protobuf/message_lite also does this enforcement on the C++ side. Validation for
63// parsing is done with GPBCodedInputStream; but for messages, it is less checks to do it within
64// the message side since the input stream code calls these same bottlenecks.
65// https://protobuf.dev/programming-guides/encoding/#cheat-sheet
66static const size_t kMaximumMessageSize = 0x7fffffff;
67
68NSString *const GPBMessageExceptionMessageTooLarge =
69    GPBNSStringifySymbol(GPBMessageExceptionMessageTooLarge);
70
71//
72// PLEASE REMEMBER:
73//
74// This is the base class for *all* messages generated, so any selector defined,
75// *public* or *private* could end up colliding with a proto message field. So
76// avoid using selectors that could match a property, use C functions to hide
77// them, etc.
78//
79
80@interface GPBMessage () {
81 @package
82  // Only one of these two is ever set, GPBUnknownFieldSet is being deprecated and will
83  // eventually be removed, but because that api support mutation, once the property is
84  // fetch it must continue to be used so any mutations will be honored in future operations
85  // on the message.
86  // Read only operations that access these two/cause things to migration between them should
87  // be protected with an @synchronized(self) block (that way the code also doesn't have to
88  // worry about throws).
89  NSMutableData *unknownFieldData_;
90#pragma clang diagnostic push
91#pragma clang diagnostic ignored "-Wdeprecated-declarations"
92  GPBUnknownFieldSet *unknownFields_;
93#pragma clang diagnostic pop
94
95  NSMutableDictionary *extensionMap_;
96  // Readonly access to autocreatedExtensionMap_ is protected via readOnlyLock_.
97  NSMutableDictionary *autocreatedExtensionMap_;
98
99  // If the object was autocreated, we remember the creator so that if we get
100  // mutated, we can inform the creator to make our field visible.
101  GPBMessage *autocreator_;
102  GPBFieldDescriptor *autocreatorField_;
103  GPBExtensionDescriptor *autocreatorExtension_;
104
105  // Messages can only be mutated from one thread. But some *readonly* operations modify internal
106  // state because they autocreate things. The autocreatedExtensionMap_ is one such structure.
107  // Access during readonly operations is protected via this lock.
108  //
109  // Long ago, this was an OSSpinLock, but then it came to light that there were issues for that on
110  // iOS:
111  //   http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/
112  //   https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html
113  // It was changed to a dispatch_semaphore_t, but that has potential for priority inversion issues.
114  // The minOS versions are now high enough that os_unfair_lock can be used, and should provide
115  // all the support we need. For more information in the concurrency/locking space see:
116  //   https://gist.github.com/tclementdev/6af616354912b0347cdf6db159c37057
117  //   https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html
118  //   https://developer.apple.com/videos/play/wwdc2017/706/
119  os_unfair_lock readOnlyLock_;
120}
121@end
122
123static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator)
124    __attribute__((ns_returns_retained));
125static id GetOrCreateArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
126static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
127static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator)
128    __attribute__((ns_returns_retained));
129static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
130static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
131static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone)
132    __attribute__((ns_returns_retained));
133
134#if defined(DEBUG) && DEBUG
135static NSError *MessageError(NSInteger code, NSDictionary *userInfo) {
136  return [NSError errorWithDomain:GPBMessageErrorDomain code:code userInfo:userInfo];
137}
138#endif
139
140static NSError *ErrorFromException(NSException *exception) {
141  NSError *error = nil;
142
143  if ([exception.name isEqual:GPBCodedInputStreamException]) {
144    NSDictionary *exceptionInfo = exception.userInfo;
145    error = exceptionInfo[GPBCodedInputStreamUnderlyingErrorKey];
146  }
147
148  if (!error) {
149    NSString *reason = exception.reason;
150    NSDictionary *userInfo = nil;
151    if ([reason length]) {
152      userInfo = @{GPBErrorReasonKey : reason};
153    }
154
155    error = [NSError errorWithDomain:GPBMessageErrorDomain
156                                code:GPBMessageErrorCodeOther
157                            userInfo:userInfo];
158  }
159  return error;
160}
161
162// Helper to encode varints onto the mutable data, the max size need is 10 bytes.
163GPB_NOINLINE
164static uint8_t *EncodeVarintU64(uint64_t val, uint8_t *ptr) {
165  do {
166    uint8_t byte = val & 0x7fU;
167    val >>= 7;
168    if (val) byte |= 0x80U;
169    *(ptr++) = byte;
170  } while (val);
171  return ptr;
172}
173
174// Helper to encode varints onto the mutable data, the max size need is 5 bytes.
175GPB_NOINLINE
176static uint8_t *EncodeVarintU32(uint32_t val, uint8_t *ptr) {
177  do {
178    uint8_t byte = val & 0x7fU;
179    val >>= 7;
180    if (val) byte |= 0x80U;
181    *(ptr++) = byte;
182  } while (val);
183  return ptr;
184}
185
186// Helper to encode signed int32 values as varints onto the mutable data, the max size need is 10
187// bytes.
188GPB_NOINLINE
189static uint8_t *EncodeVarintS32(int32_t val, uint8_t *ptr) {
190  if (val >= 0) {
191    return EncodeVarintU32((uint32_t)val, ptr);
192  } else {
193    // Must sign-extend
194    int64_t extended = val;
195    return EncodeVarintU64((uint64_t)extended, ptr);
196  }
197}
198
199GPB_NOINLINE
200static void AddUnknownFieldVarint32(GPBMessage *self, uint32_t fieldNumber, int32_t value) {
201  if (self->unknownFields_) {
202    [self->unknownFields_ mergeVarintField:fieldNumber value:value];
203    return;
204  }
205  uint8_t buf[20];
206  uint8_t *ptr = buf;
207  ptr = EncodeVarintU32(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint), ptr);
208  ptr = EncodeVarintS32(value, ptr);
209
210  if (self->unknownFieldData_ == nil) {
211    self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:ptr - buf];
212    GPBBecomeVisibleToAutocreator(self);
213  }
214  [self->unknownFieldData_ appendBytes:buf length:ptr - buf];
215}
216
217GPB_NOINLINE
218static void AddUnknownFieldLengthDelimited(GPBMessage *self, uint32_t fieldNumber, NSData *value) {
219  if (self->unknownFields_) {
220    [self->unknownFields_ mergeLengthDelimited:fieldNumber value:value];
221    return;
222  }
223  uint8_t buf[20];
224  uint8_t *ptr = buf;
225  ptr = EncodeVarintU32(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatLengthDelimited), ptr);
226  ptr = EncodeVarintU64((uint64_t)value.length, ptr);
227
228  if (self->unknownFieldData_ == nil) {
229    self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:(ptr - buf) + value.length];
230    GPBBecomeVisibleToAutocreator(self);
231  }
232  [self->unknownFieldData_ appendBytes:buf length:ptr - buf];
233  [self->unknownFieldData_ appendData:value];
234}
235
236GPB_NOINLINE
237static void AddUnknownMessageSetEntry(GPBMessage *self, uint32_t typeId, NSData *value) {
238  if (self->unknownFields_) {
239    // Legacy Set does this odd storage for MessageSet.
240    [self->unknownFields_ mergeLengthDelimited:typeId value:value];
241    return;
242  }
243
244  uint8_t buf[60];
245  uint8_t *ptr = buf;
246  ptr = EncodeVarintU32(GPBWireFormatMessageSetItemTag, ptr);
247  ptr = EncodeVarintU32(GPBWireFormatMessageSetTypeIdTag, ptr);
248  ptr = EncodeVarintU32(typeId, ptr);
249  ptr = EncodeVarintU32(GPBWireFormatMessageSetMessageTag, ptr);
250  ptr = EncodeVarintU64((uint64_t)value.length, ptr);
251  uint8_t *split = ptr;
252
253  ptr = EncodeVarintU32(GPBWireFormatMessageSetItemEndTag, ptr);
254  uint8_t *end = ptr;
255
256  if (self->unknownFieldData_ == nil) {
257    self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:(end - buf) + value.length];
258    GPBBecomeVisibleToAutocreator(self);
259  }
260  [self->unknownFieldData_ appendBytes:buf length:split - buf];
261  [self->unknownFieldData_ appendData:value];
262  [self->unknownFieldData_ appendBytes:split length:end - split];
263}
264
265GPB_NOINLINE
266static void ParseUnknownField(GPBMessage *self, uint32_t tag, GPBCodedInputStream *input) {
267  if (self->unknownFields_) {
268    if (![self->unknownFields_ mergeFieldFrom:tag input:input]) {
269      GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected end-group tag");
270    }
271    return;
272  }
273
274  uint8_t buf[20];
275  uint8_t *ptr = buf;
276  ptr = EncodeVarintU32(tag, ptr);  // All will need the tag
277  NSData *bytesToAppend = nil;
278
279  GPBCodedInputStreamState *state = &input->state_;
280
281  switch (GPBWireFormatGetTagWireType(tag)) {
282    case GPBWireFormatVarint: {
283      ptr = EncodeVarintU64(GPBCodedInputStreamReadUInt64(state), ptr);
284      break;
285    }
286    case GPBWireFormatFixed64: {
287      uint64_t value = GPBCodedInputStreamReadFixed64(state);
288      *(ptr++) = (uint8_t)(value) & 0xFF;
289      *(ptr++) = (uint8_t)(value >> 8) & 0xFF;
290      *(ptr++) = (uint8_t)(value >> 16) & 0xFF;
291      *(ptr++) = (uint8_t)(value >> 24) & 0xFF;
292      *(ptr++) = (uint8_t)(value >> 32) & 0xFF;
293      *(ptr++) = (uint8_t)(value >> 40) & 0xFF;
294      *(ptr++) = (uint8_t)(value >> 48) & 0xFF;
295      *(ptr++) = (uint8_t)(value >> 56) & 0xFF;
296      break;
297    }
298    case GPBWireFormatLengthDelimited: {
299      bytesToAppend = GPBCodedInputStreamReadRetainedBytes(state);
300      ptr = EncodeVarintU64((uint64_t)bytesToAppend.length, ptr);
301      break;
302    }
303    case GPBWireFormatStartGroup: {
304      bytesToAppend = GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(
305          state, GPBWireFormatGetTagFieldNumber(tag));
306      break;
307    }
308    case GPBWireFormatEndGroup:
309      GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected end-group tag");
310      break;
311    case GPBWireFormatFixed32: {
312      uint32_t value = GPBCodedInputStreamReadFixed32(state);
313      *(ptr++) = (uint8_t)(value) & 0xFF;
314      *(ptr++) = (uint8_t)(value >> 8) & 0xFF;
315      *(ptr++) = (uint8_t)(value >> 16) & 0xFF;
316      *(ptr++) = (uint8_t)(value >> 24) & 0xFF;
317      break;
318    }
319  }
320
321  if (self->unknownFieldData_ == nil) {
322    self->unknownFieldData_ =
323        [[NSMutableData alloc] initWithCapacity:(ptr - buf) + bytesToAppend.length];
324    GPBBecomeVisibleToAutocreator(self);
325  }
326
327  [self->unknownFieldData_ appendBytes:buf length:ptr - buf];
328  if (bytesToAppend) {
329    [self->unknownFieldData_ appendData:bytesToAppend];
330    [bytesToAppend release];
331  }
332}
333
334static void CheckExtension(GPBMessage *self, GPBExtensionDescriptor *extension) {
335  if (![self isKindOfClass:extension.containingMessageClass]) {
336    [NSException raise:NSInvalidArgumentException
337                format:@"Extension %@ used on wrong class (%@ instead of %@)",
338                       extension.singletonName, [self class], extension.containingMessageClass];
339  }
340}
341
342static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone) {
343  if (extensionMap.count == 0) {
344    return nil;
345  }
346  NSMutableDictionary *result =
347      [[NSMutableDictionary allocWithZone:zone] initWithCapacity:extensionMap.count];
348
349  for (GPBExtensionDescriptor *extension in extensionMap) {
350    id value = [extensionMap objectForKey:extension];
351    BOOL isMessageExtension = GPBExtensionIsMessage(extension);
352
353    if (extension.repeated) {
354      if (isMessageExtension) {
355        NSMutableArray *list = [[NSMutableArray alloc] initWithCapacity:[value count]];
356        for (GPBMessage *listValue in value) {
357          GPBMessage *copiedValue = [listValue copyWithZone:zone];
358          [list addObject:copiedValue];
359          [copiedValue release];
360        }
361        [result setObject:list forKey:extension];
362        [list release];
363      } else {
364        NSMutableArray *copiedValue = [value mutableCopyWithZone:zone];
365        [result setObject:copiedValue forKey:extension];
366        [copiedValue release];
367      }
368    } else {
369      if (isMessageExtension) {
370        GPBMessage *copiedValue = [value copyWithZone:zone];
371        [result setObject:copiedValue forKey:extension];
372        [copiedValue release];
373      } else {
374        [result setObject:value forKey:extension];
375      }
376    }
377  }
378
379  return result;
380}
381
382static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator) {
383  id result;
384  GPBDataType fieldDataType = GPBGetFieldDataType(field);
385  switch (fieldDataType) {
386    case GPBDataTypeBool:
387      result = [[GPBBoolArray alloc] init];
388      break;
389    case GPBDataTypeFixed32:
390    case GPBDataTypeUInt32:
391      result = [[GPBUInt32Array alloc] init];
392      break;
393    case GPBDataTypeInt32:
394    case GPBDataTypeSFixed32:
395    case GPBDataTypeSInt32:
396      result = [[GPBInt32Array alloc] init];
397      break;
398    case GPBDataTypeFixed64:
399    case GPBDataTypeUInt64:
400      result = [[GPBUInt64Array alloc] init];
401      break;
402    case GPBDataTypeInt64:
403    case GPBDataTypeSFixed64:
404    case GPBDataTypeSInt64:
405      result = [[GPBInt64Array alloc] init];
406      break;
407    case GPBDataTypeFloat:
408      result = [[GPBFloatArray alloc] init];
409      break;
410    case GPBDataTypeDouble:
411      result = [[GPBDoubleArray alloc] init];
412      break;
413
414    case GPBDataTypeEnum:
415      result = [[GPBEnumArray alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier];
416      break;
417
418    case GPBDataTypeBytes:
419    case GPBDataTypeGroup:
420    case GPBDataTypeMessage:
421    case GPBDataTypeString:
422      if (autocreator) {
423        result = [[GPBAutocreatedArray alloc] init];
424      } else {
425        result = [[NSMutableArray alloc] init];
426      }
427      break;
428  }
429
430  if (autocreator) {
431    if (GPBDataTypeIsObject(fieldDataType)) {
432      GPBAutocreatedArray *autoArray = result;
433      autoArray->_autocreator = autocreator;
434    } else {
435      GPBInt32Array *gpbArray = result;
436      gpbArray->_autocreator = autocreator;
437    }
438  }
439
440  return result;
441}
442
443static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) {
444  id result;
445  GPBDataType keyDataType = field.mapKeyDataType;
446  GPBDataType valueDataType = GPBGetFieldDataType(field);
447  switch (keyDataType) {
448    case GPBDataTypeBool:
449      switch (valueDataType) {
450        case GPBDataTypeBool:
451          result = [[GPBBoolBoolDictionary alloc] init];
452          break;
453        case GPBDataTypeFixed32:
454        case GPBDataTypeUInt32:
455          result = [[GPBBoolUInt32Dictionary alloc] init];
456          break;
457        case GPBDataTypeInt32:
458        case GPBDataTypeSFixed32:
459        case GPBDataTypeSInt32:
460          result = [[GPBBoolInt32Dictionary alloc] init];
461          break;
462        case GPBDataTypeFixed64:
463        case GPBDataTypeUInt64:
464          result = [[GPBBoolUInt64Dictionary alloc] init];
465          break;
466        case GPBDataTypeInt64:
467        case GPBDataTypeSFixed64:
468        case GPBDataTypeSInt64:
469          result = [[GPBBoolInt64Dictionary alloc] init];
470          break;
471        case GPBDataTypeFloat:
472          result = [[GPBBoolFloatDictionary alloc] init];
473          break;
474        case GPBDataTypeDouble:
475          result = [[GPBBoolDoubleDictionary alloc] init];
476          break;
477        case GPBDataTypeEnum:
478          result = [[GPBBoolEnumDictionary alloc]
479              initWithValidationFunction:field.enumDescriptor.enumVerifier];
480          break;
481        case GPBDataTypeBytes:
482        case GPBDataTypeMessage:
483        case GPBDataTypeString:
484          result = [[GPBBoolObjectDictionary alloc] init];
485          break;
486        case GPBDataTypeGroup:
487          NSCAssert(NO, @"shouldn't happen");
488          return nil;
489      }
490      break;
491    case GPBDataTypeFixed32:
492    case GPBDataTypeUInt32:
493      switch (valueDataType) {
494        case GPBDataTypeBool:
495          result = [[GPBUInt32BoolDictionary alloc] init];
496          break;
497        case GPBDataTypeFixed32:
498        case GPBDataTypeUInt32:
499          result = [[GPBUInt32UInt32Dictionary alloc] init];
500          break;
501        case GPBDataTypeInt32:
502        case GPBDataTypeSFixed32:
503        case GPBDataTypeSInt32:
504          result = [[GPBUInt32Int32Dictionary alloc] init];
505          break;
506        case GPBDataTypeFixed64:
507        case GPBDataTypeUInt64:
508          result = [[GPBUInt32UInt64Dictionary alloc] init];
509          break;
510        case GPBDataTypeInt64:
511        case GPBDataTypeSFixed64:
512        case GPBDataTypeSInt64:
513          result = [[GPBUInt32Int64Dictionary alloc] init];
514          break;
515        case GPBDataTypeFloat:
516          result = [[GPBUInt32FloatDictionary alloc] init];
517          break;
518        case GPBDataTypeDouble:
519          result = [[GPBUInt32DoubleDictionary alloc] init];
520          break;
521        case GPBDataTypeEnum:
522          result = [[GPBUInt32EnumDictionary alloc]
523              initWithValidationFunction:field.enumDescriptor.enumVerifier];
524          break;
525        case GPBDataTypeBytes:
526        case GPBDataTypeMessage:
527        case GPBDataTypeString:
528          result = [[GPBUInt32ObjectDictionary alloc] init];
529          break;
530        case GPBDataTypeGroup:
531          NSCAssert(NO, @"shouldn't happen");
532          return nil;
533      }
534      break;
535    case GPBDataTypeInt32:
536    case GPBDataTypeSFixed32:
537    case GPBDataTypeSInt32:
538      switch (valueDataType) {
539        case GPBDataTypeBool:
540          result = [[GPBInt32BoolDictionary alloc] init];
541          break;
542        case GPBDataTypeFixed32:
543        case GPBDataTypeUInt32:
544          result = [[GPBInt32UInt32Dictionary alloc] init];
545          break;
546        case GPBDataTypeInt32:
547        case GPBDataTypeSFixed32:
548        case GPBDataTypeSInt32:
549          result = [[GPBInt32Int32Dictionary alloc] init];
550          break;
551        case GPBDataTypeFixed64:
552        case GPBDataTypeUInt64:
553          result = [[GPBInt32UInt64Dictionary alloc] init];
554          break;
555        case GPBDataTypeInt64:
556        case GPBDataTypeSFixed64:
557        case GPBDataTypeSInt64:
558          result = [[GPBInt32Int64Dictionary alloc] init];
559          break;
560        case GPBDataTypeFloat:
561          result = [[GPBInt32FloatDictionary alloc] init];
562          break;
563        case GPBDataTypeDouble:
564          result = [[GPBInt32DoubleDictionary alloc] init];
565          break;
566        case GPBDataTypeEnum:
567          result = [[GPBInt32EnumDictionary alloc]
568              initWithValidationFunction:field.enumDescriptor.enumVerifier];
569          break;
570        case GPBDataTypeBytes:
571        case GPBDataTypeMessage:
572        case GPBDataTypeString:
573          result = [[GPBInt32ObjectDictionary alloc] init];
574          break;
575        case GPBDataTypeGroup:
576          NSCAssert(NO, @"shouldn't happen");
577          return nil;
578      }
579      break;
580    case GPBDataTypeFixed64:
581    case GPBDataTypeUInt64:
582      switch (valueDataType) {
583        case GPBDataTypeBool:
584          result = [[GPBUInt64BoolDictionary alloc] init];
585          break;
586        case GPBDataTypeFixed32:
587        case GPBDataTypeUInt32:
588          result = [[GPBUInt64UInt32Dictionary alloc] init];
589          break;
590        case GPBDataTypeInt32:
591        case GPBDataTypeSFixed32:
592        case GPBDataTypeSInt32:
593          result = [[GPBUInt64Int32Dictionary alloc] init];
594          break;
595        case GPBDataTypeFixed64:
596        case GPBDataTypeUInt64:
597          result = [[GPBUInt64UInt64Dictionary alloc] init];
598          break;
599        case GPBDataTypeInt64:
600        case GPBDataTypeSFixed64:
601        case GPBDataTypeSInt64:
602          result = [[GPBUInt64Int64Dictionary alloc] init];
603          break;
604        case GPBDataTypeFloat:
605          result = [[GPBUInt64FloatDictionary alloc] init];
606          break;
607        case GPBDataTypeDouble:
608          result = [[GPBUInt64DoubleDictionary alloc] init];
609          break;
610        case GPBDataTypeEnum:
611          result = [[GPBUInt64EnumDictionary alloc]
612              initWithValidationFunction:field.enumDescriptor.enumVerifier];
613          break;
614        case GPBDataTypeBytes:
615        case GPBDataTypeMessage:
616        case GPBDataTypeString:
617          result = [[GPBUInt64ObjectDictionary alloc] init];
618          break;
619        case GPBDataTypeGroup:
620          NSCAssert(NO, @"shouldn't happen");
621          return nil;
622      }
623      break;
624    case GPBDataTypeInt64:
625    case GPBDataTypeSFixed64:
626    case GPBDataTypeSInt64:
627      switch (valueDataType) {
628        case GPBDataTypeBool:
629          result = [[GPBInt64BoolDictionary alloc] init];
630          break;
631        case GPBDataTypeFixed32:
632        case GPBDataTypeUInt32:
633          result = [[GPBInt64UInt32Dictionary alloc] init];
634          break;
635        case GPBDataTypeInt32:
636        case GPBDataTypeSFixed32:
637        case GPBDataTypeSInt32:
638          result = [[GPBInt64Int32Dictionary alloc] init];
639          break;
640        case GPBDataTypeFixed64:
641        case GPBDataTypeUInt64:
642          result = [[GPBInt64UInt64Dictionary alloc] init];
643          break;
644        case GPBDataTypeInt64:
645        case GPBDataTypeSFixed64:
646        case GPBDataTypeSInt64:
647          result = [[GPBInt64Int64Dictionary alloc] init];
648          break;
649        case GPBDataTypeFloat:
650          result = [[GPBInt64FloatDictionary alloc] init];
651          break;
652        case GPBDataTypeDouble:
653          result = [[GPBInt64DoubleDictionary alloc] init];
654          break;
655        case GPBDataTypeEnum:
656          result = [[GPBInt64EnumDictionary alloc]
657              initWithValidationFunction:field.enumDescriptor.enumVerifier];
658          break;
659        case GPBDataTypeBytes:
660        case GPBDataTypeMessage:
661        case GPBDataTypeString:
662          result = [[GPBInt64ObjectDictionary alloc] init];
663          break;
664        case GPBDataTypeGroup:
665          NSCAssert(NO, @"shouldn't happen");
666          return nil;
667      }
668      break;
669    case GPBDataTypeString:
670      switch (valueDataType) {
671        case GPBDataTypeBool:
672          result = [[GPBStringBoolDictionary alloc] init];
673          break;
674        case GPBDataTypeFixed32:
675        case GPBDataTypeUInt32:
676          result = [[GPBStringUInt32Dictionary alloc] init];
677          break;
678        case GPBDataTypeInt32:
679        case GPBDataTypeSFixed32:
680        case GPBDataTypeSInt32:
681          result = [[GPBStringInt32Dictionary alloc] init];
682          break;
683        case GPBDataTypeFixed64:
684        case GPBDataTypeUInt64:
685          result = [[GPBStringUInt64Dictionary alloc] init];
686          break;
687        case GPBDataTypeInt64:
688        case GPBDataTypeSFixed64:
689        case GPBDataTypeSInt64:
690          result = [[GPBStringInt64Dictionary alloc] init];
691          break;
692        case GPBDataTypeFloat:
693          result = [[GPBStringFloatDictionary alloc] init];
694          break;
695        case GPBDataTypeDouble:
696          result = [[GPBStringDoubleDictionary alloc] init];
697          break;
698        case GPBDataTypeEnum:
699          result = [[GPBStringEnumDictionary alloc]
700              initWithValidationFunction:field.enumDescriptor.enumVerifier];
701          break;
702        case GPBDataTypeBytes:
703        case GPBDataTypeMessage:
704        case GPBDataTypeString:
705          if (autocreator) {
706            result = [[GPBAutocreatedDictionary alloc] init];
707          } else {
708            result = [[NSMutableDictionary alloc] init];
709          }
710          break;
711        case GPBDataTypeGroup:
712          NSCAssert(NO, @"shouldn't happen");
713          return nil;
714      }
715      break;
716
717    case GPBDataTypeFloat:
718    case GPBDataTypeDouble:
719    case GPBDataTypeEnum:
720    case GPBDataTypeBytes:
721    case GPBDataTypeGroup:
722    case GPBDataTypeMessage:
723      NSCAssert(NO, @"shouldn't happen");
724      return nil;
725  }
726
727  if (autocreator) {
728    if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
729      GPBAutocreatedDictionary *autoDict = result;
730      autoDict->_autocreator = autocreator;
731    } else {
732      GPBInt32Int32Dictionary *gpbDict = result;
733      gpbDict->_autocreator = autocreator;
734    }
735  }
736
737  return result;
738}
739
740#if !defined(__clang_analyzer__)
741// These functions are blocked from the analyzer because the analyzer sees the
742// GPBSetRetainedObjectIvarWithFieldPrivate() call as consuming the array/map,
743// so use of the array/map after the call returns is flagged as a use after
744// free.
745// But GPBSetRetainedObjectIvarWithFieldPrivate() is "consuming" the retain
746// count be holding onto the object (it is transferring it), the object is
747// still valid after returning from the call.  The other way to avoid this
748// would be to add a -retain/-autorelease, but that would force every
749// repeated/map field parsed into the autorelease pool which is both a memory
750// and performance hit.
751
752static id GetOrCreateArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
753  id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
754  if (!array) {
755    // No lock needed, this is called from places expecting to mutate
756    // so no threading protection is needed.
757    array = CreateArrayForField(field, nil);
758    GPBSetRetainedObjectIvarWithFieldPrivate(self, field, array);
759  }
760  return array;
761}
762
763// This is like GPBGetObjectIvarWithField(), but for arrays, it should
764// only be used to wire the method into the class.
765static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
766  uint8_t *storage = (uint8_t *)self->messageStorage_;
767  _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
768  id array = atomic_load(typePtr);
769  if (array) {
770    return array;
771  }
772
773  id expected = nil;
774  id autocreated = CreateArrayForField(field, self);
775  if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
776    // Value was set, return it.
777    return autocreated;
778  }
779
780  // Some other thread set it, release the one created and return what got set.
781  if (GPBFieldDataTypeIsObject(field)) {
782    GPBAutocreatedArray *autoArray = autocreated;
783    autoArray->_autocreator = nil;
784  } else {
785    GPBInt32Array *gpbArray = autocreated;
786    gpbArray->_autocreator = nil;
787  }
788  [autocreated release];
789  return expected;
790}
791
792static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
793  id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
794  if (!dict) {
795    // No lock needed, this is called from places expecting to mutate
796    // so no threading protection is needed.
797    dict = CreateMapForField(field, nil);
798    GPBSetRetainedObjectIvarWithFieldPrivate(self, field, dict);
799  }
800  return dict;
801}
802
803// This is like GPBGetObjectIvarWithField(), but for maps, it should
804// only be used to wire the method into the class.
805static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
806  uint8_t *storage = (uint8_t *)self->messageStorage_;
807  _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
808  id dict = atomic_load(typePtr);
809  if (dict) {
810    return dict;
811  }
812
813  id expected = nil;
814  id autocreated = CreateMapForField(field, self);
815  if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
816    // Value was set, return it.
817    return autocreated;
818  }
819
820  // Some other thread set it, release the one created and return what got set.
821  if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) {
822    GPBAutocreatedDictionary *autoDict = autocreated;
823    autoDict->_autocreator = nil;
824  } else {
825    GPBInt32Int32Dictionary *gpbDict = autocreated;
826    gpbDict->_autocreator = nil;
827  }
828  [autocreated release];
829  return expected;
830}
831
832#endif  // !defined(__clang_analyzer__)
833
834static void DecodeSingleValueFromInputStream(GPBExtensionDescriptor *extension,
835                                             GPBMessage *messageToGetExtension,
836                                             GPBCodedInputStream *input,
837                                             id<GPBExtensionRegistry> extensionRegistry,
838                                             BOOL isRepeated, GPBMessage *targetMessage) {
839  GPBExtensionDescription *description = extension->description_;
840#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
841  if (GPBDataTypeIsMessage(description->dataType)) {
842    NSCAssert(targetMessage != nil, @"Internal error: must have a target message");
843  } else {
844    NSCAssert(targetMessage == nil, @"Internal error: should not have a target message");
845  }
846#endif
847  GPBCodedInputStreamState *state = &input->state_;
848  id nsValue;
849  switch (description->dataType) {
850    case GPBDataTypeBool: {
851      BOOL value = GPBCodedInputStreamReadBool(state);
852      nsValue = [[NSNumber alloc] initWithBool:value];
853      break;
854    }
855    case GPBDataTypeFixed32: {
856      uint32_t value = GPBCodedInputStreamReadFixed32(state);
857      nsValue = [[NSNumber alloc] initWithUnsignedInt:value];
858      break;
859    }
860    case GPBDataTypeSFixed32: {
861      int32_t value = GPBCodedInputStreamReadSFixed32(state);
862      nsValue = [[NSNumber alloc] initWithInt:value];
863      break;
864    }
865    case GPBDataTypeFloat: {
866      float value = GPBCodedInputStreamReadFloat(state);
867      nsValue = [[NSNumber alloc] initWithFloat:value];
868      break;
869    }
870    case GPBDataTypeFixed64: {
871      uint64_t value = GPBCodedInputStreamReadFixed64(state);
872      nsValue = [[NSNumber alloc] initWithUnsignedLongLong:value];
873      break;
874    }
875    case GPBDataTypeSFixed64: {
876      int64_t value = GPBCodedInputStreamReadSFixed64(state);
877      nsValue = [[NSNumber alloc] initWithLongLong:value];
878      break;
879    }
880    case GPBDataTypeDouble: {
881      double value = GPBCodedInputStreamReadDouble(state);
882      nsValue = [[NSNumber alloc] initWithDouble:value];
883      break;
884    }
885    case GPBDataTypeInt32: {
886      int32_t value = GPBCodedInputStreamReadInt32(state);
887      nsValue = [[NSNumber alloc] initWithInt:value];
888      break;
889    }
890    case GPBDataTypeInt64: {
891      int64_t value = GPBCodedInputStreamReadInt64(state);
892      nsValue = [[NSNumber alloc] initWithLongLong:value];
893      break;
894    }
895    case GPBDataTypeSInt32: {
896      int32_t value = GPBCodedInputStreamReadSInt32(state);
897      nsValue = [[NSNumber alloc] initWithInt:value];
898      break;
899    }
900    case GPBDataTypeSInt64: {
901      int64_t value = GPBCodedInputStreamReadSInt64(state);
902      nsValue = [[NSNumber alloc] initWithLongLong:value];
903      break;
904    }
905    case GPBDataTypeUInt32: {
906      uint32_t value = GPBCodedInputStreamReadUInt32(state);
907      nsValue = [[NSNumber alloc] initWithUnsignedInt:value];
908      break;
909    }
910    case GPBDataTypeUInt64: {
911      uint64_t value = GPBCodedInputStreamReadUInt64(state);
912      nsValue = [[NSNumber alloc] initWithUnsignedLongLong:value];
913      break;
914    }
915    case GPBDataTypeBytes:
916      nsValue = GPBCodedInputStreamReadRetainedBytes(state);
917      break;
918    case GPBDataTypeString:
919      nsValue = GPBCodedInputStreamReadRetainedString(state);
920      break;
921    case GPBDataTypeEnum: {
922      int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
923      GPBEnumDescriptor *enumDescriptor = extension.enumDescriptor;
924      // If run with source generated before the closed enum support, all enums
925      // will be considers not closed, so casing to the enum type for a switch
926      // could cause things to fall off the end of a switch.
927      if (!enumDescriptor.isClosed || enumDescriptor.enumVerifier(val)) {
928        nsValue = [[NSNumber alloc] initWithInt:val];
929      } else {
930        AddUnknownFieldVarint32(messageToGetExtension, extension->description_->fieldNumber, val);
931        nsValue = nil;
932      }
933      break;
934    }
935    case GPBDataTypeGroup:
936    case GPBDataTypeMessage: {
937      if (description->dataType == GPBDataTypeGroup) {
938        [input readGroup:description->fieldNumber
939                      message:targetMessage
940            extensionRegistry:extensionRegistry];
941      } else {
942// description->dataType == GPBDataTypeMessage
943#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
944        NSCAssert(!GPBExtensionIsWireFormat(description),
945                  @"Internal error: got a MessageSet extension when not expected.");
946#endif
947        [input readMessage:targetMessage extensionRegistry:extensionRegistry];
948      }
949      // Nothing to add below since the caller provided the message (and added it).
950      nsValue = nil;
951      break;
952    }
953  }  // switch
954
955  if (nsValue) {
956    if (isRepeated) {
957      [messageToGetExtension addExtension:extension value:nsValue];
958    } else {
959      [messageToGetExtension setExtension:extension value:nsValue];
960    }
961    [nsValue release];
962  }
963}
964
965static void ExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, BOOL isPackedOnStream,
966                                          GPBCodedInputStream *input,
967                                          id<GPBExtensionRegistry> extensionRegistry,
968                                          GPBMessage *message) {
969  GPBExtensionDescription *description = extension->description_;
970  GPBCodedInputStreamState *state = &input->state_;
971  if (isPackedOnStream) {
972#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
973    NSCAssert(GPBExtensionIsRepeated(description), @"How was it packed if it isn't repeated?");
974#endif
975    int32_t length = GPBCodedInputStreamReadInt32(state);
976    size_t limit = GPBCodedInputStreamPushLimit(state, length);
977    while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
978      DecodeSingleValueFromInputStream(extension, message, input, extensionRegistry,
979                                       /*isRepeated=*/YES, nil);
980    }
981    GPBCodedInputStreamPopLimit(state, limit);
982  } else {
983    BOOL isRepeated = GPBExtensionIsRepeated(description);
984    GPBMessage *targetMessage = nil;
985    if (GPBDataTypeIsMessage(description->dataType)) {
986      // For messages/groups create the targetMessage out here and add it to the objects graph in
987      // advance, that way if DecodeSingleValueFromInputStream() throw for a parsing issue, the
988      // object won't be leaked.
989      if (isRepeated) {
990        GPBDescriptor *descriptor = [extension.msgClass descriptor];
991        targetMessage = [[descriptor.messageClass alloc] init];
992        [message addExtension:extension value:targetMessage];
993        [targetMessage release];
994      } else {
995        targetMessage = [message getExistingExtension:extension];
996        if (!targetMessage) {
997          GPBDescriptor *descriptor = [extension.msgClass descriptor];
998          targetMessage = [[descriptor.messageClass alloc] init];
999          [message setExtension:extension value:targetMessage];
1000          [targetMessage release];
1001        }
1002      }
1003    }
1004    DecodeSingleValueFromInputStream(extension, message, input, extensionRegistry, isRepeated,
1005                                     targetMessage);
1006  }
1007}
1008
1009static GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, GPBMessage *autocreator,
1010                                                   GPBFieldDescriptor *field) {
1011  GPBMessage *message = [[msgClass alloc] init];
1012  message->autocreator_ = autocreator;
1013  message->autocreatorField_ = [field retain];
1014  return message;
1015}
1016
1017static GPBMessage *CreateMessageWithAutocreatorForExtension(Class msgClass, GPBMessage *autocreator,
1018                                                            GPBExtensionDescriptor *extension)
1019    __attribute__((ns_returns_retained));
1020
1021static GPBMessage *CreateMessageWithAutocreatorForExtension(Class msgClass, GPBMessage *autocreator,
1022                                                            GPBExtensionDescriptor *extension) {
1023  GPBMessage *message = [[msgClass alloc] init];
1024  message->autocreator_ = autocreator;
1025  message->autocreatorExtension_ = [extension retain];
1026  return message;
1027}
1028
1029BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) {
1030  return (message->autocreator_ == parent);
1031}
1032
1033void GPBBecomeVisibleToAutocreator(GPBMessage *self) {
1034  // Message objects that are implicitly created by accessing a message field
1035  // are initially not visible via the hasX selector. This method makes them
1036  // visible.
1037  if (self->autocreator_) {
1038    // This will recursively make all parent messages visible until it reaches a
1039    // super-creator that's visible.
1040    if (self->autocreatorField_) {
1041      GPBSetObjectIvarWithFieldPrivate(self->autocreator_, self->autocreatorField_, self);
1042    } else {
1043      [self->autocreator_ setExtension:self->autocreatorExtension_ value:self];
1044    }
1045  }
1046}
1047
1048void GPBAutocreatedArrayModified(GPBMessage *self, id array) {
1049  // When one of our autocreated arrays adds elements, make it visible.
1050  GPBDescriptor *descriptor = [[self class] descriptor];
1051  for (GPBFieldDescriptor *field in descriptor->fields_) {
1052    if (field.fieldType == GPBFieldTypeRepeated) {
1053      id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1054      if (curArray == array) {
1055        if (GPBFieldDataTypeIsObject(field)) {
1056          GPBAutocreatedArray *autoArray = array;
1057          autoArray->_autocreator = nil;
1058        } else {
1059          GPBInt32Array *gpbArray = array;
1060          gpbArray->_autocreator = nil;
1061        }
1062        GPBBecomeVisibleToAutocreator(self);
1063        return;
1064      }
1065    }
1066  }
1067  NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self);
1068}
1069
1070void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) {
1071  // When one of our autocreated dicts adds elements, make it visible.
1072  GPBDescriptor *descriptor = [[self class] descriptor];
1073  for (GPBFieldDescriptor *field in descriptor->fields_) {
1074    if (field.fieldType == GPBFieldTypeMap) {
1075      id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1076      if (curDict == dictionary) {
1077        if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) {
1078          GPBAutocreatedDictionary *autoDict = dictionary;
1079          autoDict->_autocreator = nil;
1080        } else {
1081          GPBInt32Int32Dictionary *gpbDict = dictionary;
1082          gpbDict->_autocreator = nil;
1083        }
1084        GPBBecomeVisibleToAutocreator(self);
1085        return;
1086      }
1087    }
1088  }
1089  NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self);
1090}
1091
1092void GPBClearMessageAutocreator(GPBMessage *self) {
1093  if ((self == nil) || !self->autocreator_) {
1094    return;
1095  }
1096
1097#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
1098  // Either the autocreator must have its "has" flag set to YES, or it must be
1099  // NO and not equal to ourselves.
1100  BOOL autocreatorHas =
1101      (self->autocreatorField_ ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_)
1102                               : [self->autocreator_ hasExtension:self->autocreatorExtension_]);
1103  GPBMessage *autocreatorFieldValue =
1104      (self->autocreatorField_
1105           ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_, self->autocreatorField_)
1106           : [self->autocreator_->autocreatedExtensionMap_
1107                 objectForKey:self->autocreatorExtension_]);
1108  NSCAssert(autocreatorHas || autocreatorFieldValue != self,
1109            @"Cannot clear autocreator because it still refers to self, self: %@.", self);
1110
1111#endif  // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
1112
1113  self->autocreator_ = nil;
1114  [self->autocreatorField_ release];
1115  self->autocreatorField_ = nil;
1116  [self->autocreatorExtension_ release];
1117  self->autocreatorExtension_ = nil;
1118}
1119
1120#pragma clang diagnostic push
1121#pragma clang diagnostic ignored "-Wdeprecated-declarations"
1122GPB_NOINLINE
1123static void MergeUnknownFieldDataIntoFieldSet(GPBMessage *self, NSData *data,
1124                                              GPBUnknownFieldSet *targetSet) {
1125  GPBUnknownFieldSet *unknownFields = targetSet ? targetSet : self->unknownFields_;
1126
1127#if defined(DEBUG) && DEBUG
1128  NSCAssert(unknownFields != nil, @"Internal error: unknown fields not initialized.");
1129#endif
1130
1131  BOOL isMessageSet = self.descriptor.isWireFormat;
1132  GPBUnknownFieldSet *decodeInto = isMessageSet ? [[GPBUnknownFieldSet alloc] init] : unknownFields;
1133
1134  GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
1135  @try {
1136    [decodeInto mergeFromCodedInputStream:input];
1137  } @catch (NSException *exception) {
1138#if defined(DEBUG) && DEBUG
1139    NSLog(@"%@: Internal exception while parsing the unknown fields into a Set: %@", [self class],
1140          exception);
1141#endif
1142  }
1143  [input release];
1144
1145  if (isMessageSet) {
1146    // Need to transform the groups back into how Message feeds the data into a MessageSet when
1147    // doing a full MessageSet based decode.
1148    GPBUnknownField *groupField = [decodeInto getField:GPBWireFormatMessageSetItem];
1149    for (GPBUnknownFieldSet *group in groupField.groupList) {
1150      GPBUnknownField *typeIdField = [group getField:GPBWireFormatMessageSetTypeId];
1151      GPBUnknownField *messageField = [group getField:GPBWireFormatMessageSetMessage];
1152      if (typeIdField.varintList.count != 1 || messageField.lengthDelimitedList.count != 1) {
1153#if defined(DEBUG) && DEBUG
1154        NSCAssert(NO, @"Internal error: MessageSet group missing typeId or message.");
1155#endif
1156        continue;
1157      }
1158      int32_t fieldNumber = (int32_t)[typeIdField.varintList valueAtIndex:0];
1159      GPBUnknownField *messageSetField = [[GPBUnknownField alloc] initWithNumber:fieldNumber];
1160      [messageSetField addLengthDelimited:messageField.lengthDelimitedList[0]];
1161      [unknownFields addField:messageSetField];
1162      [messageSetField release];
1163    }
1164    [decodeInto release];
1165  }
1166}
1167#pragma clang diagnostic pop
1168
1169@implementation GPBMessage
1170
1171+ (void)initialize {
1172  Class pbMessageClass = [GPBMessage class];
1173  if ([self class] == pbMessageClass) {
1174    // This is here to start up the "base" class descriptor.
1175    [self descriptor];
1176    // Message shares extension method resolving with GPBRootObject so insure
1177    // it is started up at the same time.
1178    (void)[GPBRootObject class];
1179  } else if ([self superclass] == pbMessageClass) {
1180    // This is here to start up all the "message" subclasses. Just needs to be
1181    // done for the messages, not any of the subclasses.
1182    // This must be done in initialize to enforce thread safety of start up of
1183    // the protocol buffer library.
1184    // Note: The generated code for -descriptor calls
1185    // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject
1186    // subclass for the file.  That call chain is what ensures that *Root class
1187    // is started up to support extension resolution off the message class
1188    // (+resolveClassMethod: below) in a thread safe manner.
1189    [self descriptor];
1190  }
1191}
1192
1193+ (instancetype)allocWithZone:(NSZone *)zone {
1194  // Override alloc to allocate our classes with the additional storage
1195  // required for the instance variables.
1196  GPBDescriptor *descriptor = [self descriptor];
1197  return NSAllocateObject(self, descriptor->storageSize_, zone);
1198}
1199
1200+ (instancetype)alloc {
1201  return [self allocWithZone:nil];
1202}
1203
1204+ (GPBDescriptor *)descriptor {
1205  // This is thread safe because it is called from +initialize.
1206  static GPBDescriptor *descriptor = NULL;
1207  static GPBFileDescription fileDescription = {
1208      .package = "internal", .prefix = "", .syntax = GPBFileSyntaxProto2};
1209  if (!descriptor) {
1210    descriptor = [GPBDescriptor
1211        allocDescriptorForClass:[GPBMessage class]
1212                    messageName:@"GPBMessage"
1213                fileDescription:&fileDescription
1214                         fields:NULL
1215                     fieldCount:0
1216                    storageSize:0
1217                          flags:(GPBDescriptorInitializationFlag_UsesClassRefs |
1218                                 GPBDescriptorInitializationFlag_Proto3OptionalKnown |
1219                                 GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
1220  }
1221  return descriptor;
1222}
1223
1224+ (instancetype)message {
1225  return [[[self alloc] init] autorelease];
1226}
1227
1228- (instancetype)init {
1229  if ((self = [super init])) {
1230    messageStorage_ =
1231        (GPBMessage_StoragePtr)(((uint8_t *)self) + class_getInstanceSize([self class]));
1232    readOnlyLock_ = OS_UNFAIR_LOCK_INIT;
1233  }
1234
1235  return self;
1236}
1237
1238- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr {
1239  return [self initWithData:data extensionRegistry:nil error:errorPtr];
1240}
1241
1242- (instancetype)initWithData:(NSData *)data
1243           extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
1244                       error:(NSError **)errorPtr {
1245  if ((self = [self init])) {
1246    if (![self mergeFromData:data extensionRegistry:extensionRegistry error:errorPtr]) {
1247      [self release];
1248      self = nil;
1249#if defined(DEBUG) && DEBUG
1250    } else if (!self.initialized) {
1251      [self release];
1252      self = nil;
1253      if (errorPtr) {
1254        *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
1255      }
1256#endif
1257    }
1258  }
1259  return self;
1260}
1261
1262- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
1263                       extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
1264                                   error:(NSError **)errorPtr {
1265  if ((self = [self init])) {
1266    @try {
1267      [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
1268      if (errorPtr) {
1269        *errorPtr = nil;
1270      }
1271    } @catch (NSException *exception) {
1272      [self release];
1273      self = nil;
1274      if (errorPtr) {
1275        *errorPtr = ErrorFromException(exception);
1276      }
1277    }
1278#if defined(DEBUG) && DEBUG
1279    if (self && !self.initialized) {
1280      [self release];
1281      self = nil;
1282      if (errorPtr) {
1283        *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
1284      }
1285    }
1286#endif
1287  }
1288  return self;
1289}
1290
1291- (void)dealloc {
1292  [self internalClear:NO];
1293  NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc.");
1294  [super dealloc];
1295}
1296
1297- (void)copyFieldsInto:(GPBMessage *)message
1298                  zone:(NSZone *)zone
1299            descriptor:(GPBDescriptor *)descriptor {
1300  // Copy all the storage...
1301  memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_);
1302
1303  // Loop over the fields doing fixup...
1304  for (GPBFieldDescriptor *field in descriptor->fields_) {
1305    if (GPBFieldIsMapOrArray(field)) {
1306      id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1307      if (value) {
1308        // We need to copy the array/map, but the catch is for message fields,
1309        // we also need to ensure all the messages as those need copying also.
1310        id newValue;
1311        if (GPBFieldDataTypeIsMessage(field)) {
1312          if (field.fieldType == GPBFieldTypeRepeated) {
1313            NSArray *existingArray = (NSArray *)value;
1314            NSMutableArray *newArray =
1315                [[NSMutableArray alloc] initWithCapacity:existingArray.count];
1316            newValue = newArray;
1317            for (GPBMessage *msg in existingArray) {
1318              GPBMessage *copiedMsg = [msg copyWithZone:zone];
1319              [newArray addObject:copiedMsg];
1320              [copiedMsg release];
1321            }
1322          } else {
1323            if (field.mapKeyDataType == GPBDataTypeString) {
1324              // Map is an NSDictionary.
1325              NSDictionary *existingDict = value;
1326              NSMutableDictionary *newDict =
1327                  [[NSMutableDictionary alloc] initWithCapacity:existingDict.count];
1328              newValue = newDict;
1329              [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, GPBMessage *msg,
1330                                                                __unused BOOL *stop) {
1331                GPBMessage *copiedMsg = [msg copyWithZone:zone];
1332                [newDict setObject:copiedMsg forKey:key];
1333                [copiedMsg release];
1334              }];
1335            } else {
1336              // Is one of the GPB*ObjectDictionary classes.  Type doesn't
1337              // matter, just need one to invoke the selector.
1338              GPBInt32ObjectDictionary *existingDict = value;
1339              newValue = [existingDict deepCopyWithZone:zone];
1340            }
1341          }
1342        } else {
1343          // Not messages (but is a map/array)...
1344          if (field.fieldType == GPBFieldTypeRepeated) {
1345            if (GPBFieldDataTypeIsObject(field)) {
1346              // NSArray
1347              newValue = [value mutableCopyWithZone:zone];
1348            } else {
1349              // GPB*Array
1350              newValue = [value copyWithZone:zone];
1351            }
1352          } else {
1353            if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) {
1354              // NSDictionary
1355              newValue = [value mutableCopyWithZone:zone];
1356            } else {
1357              // Is one of the GPB*Dictionary classes.  Type doesn't matter,
1358              // just need one to invoke the selector.
1359              GPBInt32Int32Dictionary *existingDict = value;
1360              newValue = [existingDict copyWithZone:zone];
1361            }
1362          }
1363        }
1364        // We retain here because the memcpy picked up the pointer value and
1365        // the next call to SetRetainedObject... will release the current value.
1366        [value retain];
1367        GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
1368      }
1369    } else if (GPBFieldDataTypeIsMessage(field)) {
1370      // For object types, if we have a value, copy it.  If we don't,
1371      // zero it to remove the pointer to something that was autocreated
1372      // (and the ptr just got memcpyed).
1373      if (GPBGetHasIvarField(self, field)) {
1374        GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1375        GPBMessage *newValue = [value copyWithZone:zone];
1376        // We retain here because the memcpy picked up the pointer value and
1377        // the next call to SetRetainedObject... will release the current value.
1378        [value retain];
1379        GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
1380      } else {
1381        uint8_t *storage = (uint8_t *)message->messageStorage_;
1382        id *typePtr = (id *)&storage[field->description_->offset];
1383        *typePtr = NULL;
1384      }
1385    } else if (GPBFieldDataTypeIsObject(field) && GPBGetHasIvarField(self, field)) {
1386      // A set string/data value (message picked off above), copy it.
1387      id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1388      id newValue = [value copyWithZone:zone];
1389      // We retain here because the memcpy picked up the pointer value and
1390      // the next call to SetRetainedObject... will release the current value.
1391      [value retain];
1392      GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue);
1393    } else {
1394      // memcpy took care of the rest of the primitive fields if they were set.
1395    }
1396  }  // for (field in descriptor->fields_)
1397}
1398
1399- (id)copyWithZone:(NSZone *)zone {
1400  GPBDescriptor *descriptor = [self descriptor];
1401  GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init];
1402
1403  [self copyFieldsInto:result zone:zone descriptor:descriptor];
1404
1405  @synchronized(self) {
1406    result->unknownFields_ = [unknownFields_ copyWithZone:zone];
1407    result->unknownFieldData_ = [unknownFieldData_ mutableCopyWithZone:zone];
1408  }
1409
1410  result->extensionMap_ = CloneExtensionMap(extensionMap_, zone);
1411  return result;
1412}
1413
1414- (void)clear {
1415  [self internalClear:YES];
1416}
1417
1418- (void)internalClear:(BOOL)zeroStorage {
1419  GPBDescriptor *descriptor = [self descriptor];
1420  for (GPBFieldDescriptor *field in descriptor->fields_) {
1421    if (GPBFieldIsMapOrArray(field)) {
1422      id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1423      if (arrayOrMap) {
1424        if (field.fieldType == GPBFieldTypeRepeated) {
1425          if (GPBFieldDataTypeIsObject(field)) {
1426            if ([arrayOrMap isKindOfClass:[GPBAutocreatedArray class]]) {
1427              GPBAutocreatedArray *autoArray = arrayOrMap;
1428              if (autoArray->_autocreator == self) {
1429                autoArray->_autocreator = nil;
1430              }
1431            }
1432          } else {
1433            // Type doesn't matter, it is a GPB*Array.
1434            GPBInt32Array *gpbArray = arrayOrMap;
1435            if (gpbArray->_autocreator == self) {
1436              gpbArray->_autocreator = nil;
1437            }
1438          }
1439        } else {
1440          if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) {
1441            if ([arrayOrMap isKindOfClass:[GPBAutocreatedDictionary class]]) {
1442              GPBAutocreatedDictionary *autoDict = arrayOrMap;
1443              if (autoDict->_autocreator == self) {
1444                autoDict->_autocreator = nil;
1445              }
1446            }
1447          } else {
1448            // Type doesn't matter, it is a GPB*Dictionary.
1449            GPBInt32Int32Dictionary *gpbDict = arrayOrMap;
1450            if (gpbDict->_autocreator == self) {
1451              gpbDict->_autocreator = nil;
1452            }
1453          }
1454        }
1455        [arrayOrMap release];
1456      }
1457    } else if (GPBFieldDataTypeIsMessage(field)) {
1458      GPBClearAutocreatedMessageIvarWithField(self, field);
1459      GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1460      [value release];
1461    } else if (GPBFieldDataTypeIsObject(field) && GPBGetHasIvarField(self, field)) {
1462      id value = GPBGetObjectIvarWithField(self, field);
1463      [value release];
1464    }
1465  }
1466
1467  // GPBClearMessageAutocreator() expects that its caller has already been
1468  // removed from autocreatedExtensionMap_ so we set to nil first.
1469  NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues];
1470  [autocreatedExtensionMap_ release];
1471  autocreatedExtensionMap_ = nil;
1472
1473  // Since we're clearing all of our extensions, make sure that we clear the
1474  // autocreator on any that we've created so they no longer refer to us.
1475  for (GPBMessage *value in autocreatedValues) {
1476    NSCAssert(GPBWasMessageAutocreatedBy(value, self),
1477              @"Autocreated extension does not refer back to self.");
1478    GPBClearMessageAutocreator(value);
1479  }
1480
1481  [extensionMap_ release];
1482  extensionMap_ = nil;
1483  [unknownFieldData_ release];
1484  unknownFieldData_ = nil;
1485  [unknownFields_ release];
1486  unknownFields_ = nil;
1487
1488  // Note that clearing does not affect autocreator_. If we are being cleared
1489  // because of a dealloc, then autocreator_ should be nil anyway. If we are
1490  // being cleared because someone explicitly clears us, we don't want to
1491  // sever our relationship with our autocreator.
1492
1493  if (zeroStorage) {
1494    memset(messageStorage_, 0, descriptor->storageSize_);
1495  }
1496}
1497
1498- (void)clearUnknownFields {
1499  [unknownFieldData_ release];
1500  unknownFieldData_ = nil;
1501#pragma clang diagnostic push
1502#pragma clang diagnostic ignored "-Wdeprecated-declarations"
1503  [unknownFields_ release];
1504  unknownFields_ = nil;
1505#pragma clang diagnostic pop
1506  GPBBecomeVisibleToAutocreator(self);
1507}
1508
1509- (BOOL)mergeUnknownFields:(GPBUnknownFields *)unknownFields
1510         extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
1511                     error:(NSError **)errorPtr {
1512  return [self mergeFromData:[unknownFields serializeAsData]
1513           extensionRegistry:extensionRegistry
1514                       error:errorPtr];
1515}
1516
1517- (BOOL)isInitialized {
1518  GPBDescriptor *descriptor = [self descriptor];
1519  for (GPBFieldDescriptor *field in descriptor->fields_) {
1520    if (field.isRequired) {
1521      if (!GPBGetHasIvarField(self, field)) {
1522        return NO;
1523      }
1524    }
1525    if (GPBFieldDataTypeIsMessage(field)) {
1526      GPBFieldType fieldType = field.fieldType;
1527      if (fieldType == GPBFieldTypeSingle) {
1528        if (field.isRequired) {
1529          GPBMessage *message = GPBGetMessageMessageField(self, field);
1530          if (!message.initialized) {
1531            return NO;
1532          }
1533        } else {
1534          NSAssert(field.isOptional, @"%@: Single message field %@ not required or optional?",
1535                   [self class], field.name);
1536          if (GPBGetHasIvarField(self, field)) {
1537            GPBMessage *message = GPBGetMessageMessageField(self, field);
1538            if (!message.initialized) {
1539              return NO;
1540            }
1541          }
1542        }
1543      } else if (fieldType == GPBFieldTypeRepeated) {
1544        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1545        for (GPBMessage *message in array) {
1546          if (!message.initialized) {
1547            return NO;
1548          }
1549        }
1550      } else {  // fieldType == GPBFieldTypeMap
1551        if (field.mapKeyDataType == GPBDataTypeString) {
1552          NSDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1553          if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) {
1554            return NO;
1555          }
1556        } else {
1557          // Real type is GPB*ObjectDictionary, exact type doesn't matter.
1558          GPBInt32ObjectDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1559          if (map && ![map isInitialized]) {
1560            return NO;
1561          }
1562        }
1563      }
1564    }
1565  }
1566
1567  __block BOOL result = YES;
1568  [extensionMap_
1569      enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, id obj, BOOL *stop) {
1570        if (GPBExtensionIsMessage(extension)) {
1571          if (extension.isRepeated) {
1572            for (GPBMessage *msg in obj) {
1573              if (!msg.initialized) {
1574                result = NO;
1575                *stop = YES;
1576                break;
1577              }
1578            }
1579          } else {
1580            GPBMessage *asMsg = obj;
1581            if (!asMsg.initialized) {
1582              result = NO;
1583              *stop = YES;
1584            }
1585          }
1586        }
1587      }];
1588  return result;
1589}
1590
1591- (GPBDescriptor *)descriptor {
1592  return [[self class] descriptor];
1593}
1594
1595- (NSData *)data {
1596#if defined(DEBUG) && DEBUG
1597  if (!self.initialized) {
1598    return nil;
1599  }
1600#endif
1601  size_t expectedSize = [self serializedSize];
1602  if (expectedSize > kMaximumMessageSize) {
1603    return nil;
1604  }
1605  NSMutableData *data = [NSMutableData dataWithLength:expectedSize];
1606  GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data];
1607  @try {
1608    [self writeToCodedOutputStream:stream];
1609    [stream flush];
1610  } @catch (NSException *exception) {
1611    // This really shouldn't happen. Normally, this could mean there was a bug in the library and it
1612    // failed to match between computing the size and writing out the bytes. However, the more
1613    // common cause is while one thread was writing out the data, some other thread had a reference
1614    // to this message or a message used as a nested field, and that other thread mutated that
1615    // message, causing the pre computed serializedSize to no longer match the final size after
1616    // serialization. It is not safe to mutate a message while accessing it from another thread.
1617#if defined(DEBUG) && DEBUG
1618    NSLog(@"%@: Internal exception while building message data: %@", [self class], exception);
1619#endif
1620    data = nil;
1621  }
1622#if defined(DEBUG) && DEBUG
1623  NSAssert(!data || [stream bytesWritten] == expectedSize, @"Internal error within the library");
1624#endif
1625  [stream release];
1626  return data;
1627}
1628
1629- (NSData *)delimitedData {
1630  size_t serializedSize = [self serializedSize];
1631  size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize);
1632  NSMutableData *data = [NSMutableData dataWithLength:(serializedSize + varintSize)];
1633  GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data];
1634  @try {
1635    [self writeDelimitedToCodedOutputStream:stream];
1636    [stream flush];
1637  } @catch (NSException *exception) {
1638    // This really shouldn't happen. Normally, this could mean there was a bug in the library and it
1639    // failed to match between computing the size and writing out the bytes. However, the more
1640    // common cause is while one thread was writing out the data, some other thread had a reference
1641    // to this message or a message used as a nested field, and that other thread mutated that
1642    // message, causing the pre computed serializedSize to no longer match the final size after
1643    // serialization. It is not safe to mutate a message while accessing it from another thread.
1644#if defined(DEBUG) && DEBUG
1645    NSLog(@"%@: Internal exception while building message delimitedData: %@", [self class],
1646          exception);
1647#endif
1648    // If it happens, return an empty data.
1649    [stream release];
1650    return [NSData data];
1651  }
1652  [stream release];
1653  return data;
1654}
1655
1656- (void)writeToOutputStream:(NSOutputStream *)output {
1657  GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithOutputStream:output];
1658  @try {
1659    [self writeToCodedOutputStream:stream];
1660    [stream flush];
1661    size_t bytesWritten = [stream bytesWritten];
1662    if (bytesWritten > kMaximumMessageSize) {
1663      [NSException raise:GPBMessageExceptionMessageTooLarge
1664                  format:@"Message would have been %zu bytes", bytesWritten];
1665    }
1666  } @finally {
1667    [stream release];
1668  }
1669}
1670
1671- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output {
1672  GPBDescriptor *descriptor = [self descriptor];
1673  NSArray *fieldsArray = descriptor->fields_;
1674  NSUInteger fieldCount = fieldsArray.count;
1675  const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
1676  NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
1677  NSArray *sortedExtensions =
1678      [[extensionMap_ allKeys] sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
1679  for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
1680    if (i == fieldCount) {
1681      [self writeExtensionsToCodedOutputStream:output
1682                                         range:extensionRanges[j++]
1683                              sortedExtensions:sortedExtensions];
1684    } else if (j == extensionRangesCount ||
1685               GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
1686      [self writeField:fieldsArray[i++] toCodedOutputStream:output];
1687    } else {
1688      [self writeExtensionsToCodedOutputStream:output
1689                                         range:extensionRanges[j++]
1690                              sortedExtensions:sortedExtensions];
1691    }
1692  }
1693  @synchronized(self) {
1694    if (unknownFieldData_) {
1695#if defined(DEBUG) && DEBUG
1696      NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set");
1697#endif
1698      [output writeRawData:unknownFieldData_];
1699    } else {
1700      if (descriptor.isWireFormat) {
1701        [unknownFields_ writeAsMessageSetTo:output];
1702      } else {
1703        [unknownFields_ writeToCodedOutputStream:output];
1704      }
1705    }
1706  }  // @synchronized(self)
1707}
1708
1709- (void)writeDelimitedToOutputStream:(NSOutputStream *)output {
1710  GPBCodedOutputStream *codedOutput = [[GPBCodedOutputStream alloc] initWithOutputStream:output];
1711  @try {
1712    [self writeDelimitedToCodedOutputStream:codedOutput];
1713    [codedOutput flush];
1714  } @finally {
1715    [codedOutput release];
1716  }
1717}
1718
1719- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output {
1720  size_t expectedSize = [self serializedSize];
1721  if (expectedSize > kMaximumMessageSize) {
1722    [NSException raise:GPBMessageExceptionMessageTooLarge
1723                format:@"Message would have been %zu bytes", expectedSize];
1724  }
1725  [output writeRawVarintSizeTAs32:expectedSize];
1726#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
1727  size_t initialSize = [output bytesWritten];
1728#endif
1729  [self writeToCodedOutputStream:output];
1730#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
1731  NSAssert(([output bytesWritten] - initialSize) == expectedSize,
1732           @"Internal error within the library");
1733#endif
1734}
1735
1736- (void)writeField:(GPBFieldDescriptor *)field toCodedOutputStream:(GPBCodedOutputStream *)output {
1737  GPBFieldType fieldType = field.fieldType;
1738  if (fieldType == GPBFieldTypeSingle) {
1739    BOOL has = GPBGetHasIvarField(self, field);
1740    if (!has) {
1741      return;
1742    }
1743  }
1744  uint32_t fieldNumber = GPBFieldNumber(field);
1745
1746  switch (GPBGetFieldDataType(field)) {
1747      // clang-format off
1748
1749//%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE)
1750//%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE)
1751//%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE)
1752//%    case GPBDataType##TYPE:
1753//%      if (fieldType == GPBFieldTypeRepeated) {
1754//%        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1755//%        GPB##ARRAY_TYPE##Array *array =
1756//%            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1757//%        [output write##TYPE##Array:fieldNumber values:array tag:tag];
1758//%      } else if (fieldType == GPBFieldTypeSingle) {
1759//%        [output write##TYPE:fieldNumber
1760//%              TYPE$S  value:GPBGetMessage##REAL_TYPE##Field(self, field)];
1761//%      } else {  // fieldType == GPBFieldTypeMap
1762//%        // Exact type here doesn't matter.
1763//%        GPBInt32##ARRAY_TYPE##Dictionary *dict =
1764//%            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1765//%        [dict writeToCodedOutputStream:output asField:field];
1766//%      }
1767//%      break;
1768//%
1769//%PDDM-DEFINE FIELD_CASE2(TYPE)
1770//%    case GPBDataType##TYPE:
1771//%      if (fieldType == GPBFieldTypeRepeated) {
1772//%        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1773//%        [output write##TYPE##Array:fieldNumber values:array];
1774//%      } else if (fieldType == GPBFieldTypeSingle) {
1775//%        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
1776//%        // again.
1777//%        [output write##TYPE:fieldNumber
1778//%              TYPE$S  value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
1779//%      } else {  // fieldType == GPBFieldTypeMap
1780//%        // Exact type here doesn't matter.
1781//%        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1782//%        GPBDataType mapKeyDataType = field.mapKeyDataType;
1783//%        if (mapKeyDataType == GPBDataTypeString) {
1784//%          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
1785//%        } else {
1786//%          [dict writeToCodedOutputStream:output asField:field];
1787//%        }
1788//%      }
1789//%      break;
1790//%
1791//%PDDM-EXPAND FIELD_CASE(Bool, Bool)
1792// This block of code is generated, do not edit it directly.
1793
1794    case GPBDataTypeBool:
1795      if (fieldType == GPBFieldTypeRepeated) {
1796        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1797        GPBBoolArray *array =
1798            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1799        [output writeBoolArray:fieldNumber values:array tag:tag];
1800      } else if (fieldType == GPBFieldTypeSingle) {
1801        [output writeBool:fieldNumber
1802                    value:GPBGetMessageBoolField(self, field)];
1803      } else {  // fieldType == GPBFieldTypeMap
1804        // Exact type here doesn't matter.
1805        GPBInt32BoolDictionary *dict =
1806            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1807        [dict writeToCodedOutputStream:output asField:field];
1808      }
1809      break;
1810
1811//%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32)
1812// This block of code is generated, do not edit it directly.
1813
1814    case GPBDataTypeFixed32:
1815      if (fieldType == GPBFieldTypeRepeated) {
1816        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1817        GPBUInt32Array *array =
1818            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1819        [output writeFixed32Array:fieldNumber values:array tag:tag];
1820      } else if (fieldType == GPBFieldTypeSingle) {
1821        [output writeFixed32:fieldNumber
1822                       value:GPBGetMessageUInt32Field(self, field)];
1823      } else {  // fieldType == GPBFieldTypeMap
1824        // Exact type here doesn't matter.
1825        GPBInt32UInt32Dictionary *dict =
1826            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1827        [dict writeToCodedOutputStream:output asField:field];
1828      }
1829      break;
1830
1831//%PDDM-EXPAND FIELD_CASE(SFixed32, Int32)
1832// This block of code is generated, do not edit it directly.
1833
1834    case GPBDataTypeSFixed32:
1835      if (fieldType == GPBFieldTypeRepeated) {
1836        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1837        GPBInt32Array *array =
1838            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1839        [output writeSFixed32Array:fieldNumber values:array tag:tag];
1840      } else if (fieldType == GPBFieldTypeSingle) {
1841        [output writeSFixed32:fieldNumber
1842                        value:GPBGetMessageInt32Field(self, field)];
1843      } else {  // fieldType == GPBFieldTypeMap
1844        // Exact type here doesn't matter.
1845        GPBInt32Int32Dictionary *dict =
1846            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1847        [dict writeToCodedOutputStream:output asField:field];
1848      }
1849      break;
1850
1851//%PDDM-EXPAND FIELD_CASE(Float, Float)
1852// This block of code is generated, do not edit it directly.
1853
1854    case GPBDataTypeFloat:
1855      if (fieldType == GPBFieldTypeRepeated) {
1856        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1857        GPBFloatArray *array =
1858            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1859        [output writeFloatArray:fieldNumber values:array tag:tag];
1860      } else if (fieldType == GPBFieldTypeSingle) {
1861        [output writeFloat:fieldNumber
1862                     value:GPBGetMessageFloatField(self, field)];
1863      } else {  // fieldType == GPBFieldTypeMap
1864        // Exact type here doesn't matter.
1865        GPBInt32FloatDictionary *dict =
1866            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1867        [dict writeToCodedOutputStream:output asField:field];
1868      }
1869      break;
1870
1871//%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64)
1872// This block of code is generated, do not edit it directly.
1873
1874    case GPBDataTypeFixed64:
1875      if (fieldType == GPBFieldTypeRepeated) {
1876        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1877        GPBUInt64Array *array =
1878            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1879        [output writeFixed64Array:fieldNumber values:array tag:tag];
1880      } else if (fieldType == GPBFieldTypeSingle) {
1881        [output writeFixed64:fieldNumber
1882                       value:GPBGetMessageUInt64Field(self, field)];
1883      } else {  // fieldType == GPBFieldTypeMap
1884        // Exact type here doesn't matter.
1885        GPBInt32UInt64Dictionary *dict =
1886            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1887        [dict writeToCodedOutputStream:output asField:field];
1888      }
1889      break;
1890
1891//%PDDM-EXPAND FIELD_CASE(SFixed64, Int64)
1892// This block of code is generated, do not edit it directly.
1893
1894    case GPBDataTypeSFixed64:
1895      if (fieldType == GPBFieldTypeRepeated) {
1896        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1897        GPBInt64Array *array =
1898            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1899        [output writeSFixed64Array:fieldNumber values:array tag:tag];
1900      } else if (fieldType == GPBFieldTypeSingle) {
1901        [output writeSFixed64:fieldNumber
1902                        value:GPBGetMessageInt64Field(self, field)];
1903      } else {  // fieldType == GPBFieldTypeMap
1904        // Exact type here doesn't matter.
1905        GPBInt32Int64Dictionary *dict =
1906            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1907        [dict writeToCodedOutputStream:output asField:field];
1908      }
1909      break;
1910
1911//%PDDM-EXPAND FIELD_CASE(Double, Double)
1912// This block of code is generated, do not edit it directly.
1913
1914    case GPBDataTypeDouble:
1915      if (fieldType == GPBFieldTypeRepeated) {
1916        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1917        GPBDoubleArray *array =
1918            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1919        [output writeDoubleArray:fieldNumber values:array tag:tag];
1920      } else if (fieldType == GPBFieldTypeSingle) {
1921        [output writeDouble:fieldNumber
1922                      value:GPBGetMessageDoubleField(self, field)];
1923      } else {  // fieldType == GPBFieldTypeMap
1924        // Exact type here doesn't matter.
1925        GPBInt32DoubleDictionary *dict =
1926            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1927        [dict writeToCodedOutputStream:output asField:field];
1928      }
1929      break;
1930
1931//%PDDM-EXPAND FIELD_CASE(Int32, Int32)
1932// This block of code is generated, do not edit it directly.
1933
1934    case GPBDataTypeInt32:
1935      if (fieldType == GPBFieldTypeRepeated) {
1936        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1937        GPBInt32Array *array =
1938            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1939        [output writeInt32Array:fieldNumber values:array tag:tag];
1940      } else if (fieldType == GPBFieldTypeSingle) {
1941        [output writeInt32:fieldNumber
1942                     value:GPBGetMessageInt32Field(self, field)];
1943      } else {  // fieldType == GPBFieldTypeMap
1944        // Exact type here doesn't matter.
1945        GPBInt32Int32Dictionary *dict =
1946            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1947        [dict writeToCodedOutputStream:output asField:field];
1948      }
1949      break;
1950
1951//%PDDM-EXPAND FIELD_CASE(Int64, Int64)
1952// This block of code is generated, do not edit it directly.
1953
1954    case GPBDataTypeInt64:
1955      if (fieldType == GPBFieldTypeRepeated) {
1956        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1957        GPBInt64Array *array =
1958            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1959        [output writeInt64Array:fieldNumber values:array tag:tag];
1960      } else if (fieldType == GPBFieldTypeSingle) {
1961        [output writeInt64:fieldNumber
1962                     value:GPBGetMessageInt64Field(self, field)];
1963      } else {  // fieldType == GPBFieldTypeMap
1964        // Exact type here doesn't matter.
1965        GPBInt32Int64Dictionary *dict =
1966            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1967        [dict writeToCodedOutputStream:output asField:field];
1968      }
1969      break;
1970
1971//%PDDM-EXPAND FIELD_CASE(SInt32, Int32)
1972// This block of code is generated, do not edit it directly.
1973
1974    case GPBDataTypeSInt32:
1975      if (fieldType == GPBFieldTypeRepeated) {
1976        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1977        GPBInt32Array *array =
1978            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1979        [output writeSInt32Array:fieldNumber values:array tag:tag];
1980      } else if (fieldType == GPBFieldTypeSingle) {
1981        [output writeSInt32:fieldNumber
1982                      value:GPBGetMessageInt32Field(self, field)];
1983      } else {  // fieldType == GPBFieldTypeMap
1984        // Exact type here doesn't matter.
1985        GPBInt32Int32Dictionary *dict =
1986            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1987        [dict writeToCodedOutputStream:output asField:field];
1988      }
1989      break;
1990
1991//%PDDM-EXPAND FIELD_CASE(SInt64, Int64)
1992// This block of code is generated, do not edit it directly.
1993
1994    case GPBDataTypeSInt64:
1995      if (fieldType == GPBFieldTypeRepeated) {
1996        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1997        GPBInt64Array *array =
1998            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1999        [output writeSInt64Array:fieldNumber values:array tag:tag];
2000      } else if (fieldType == GPBFieldTypeSingle) {
2001        [output writeSInt64:fieldNumber
2002                      value:GPBGetMessageInt64Field(self, field)];
2003      } else {  // fieldType == GPBFieldTypeMap
2004        // Exact type here doesn't matter.
2005        GPBInt32Int64Dictionary *dict =
2006            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2007        [dict writeToCodedOutputStream:output asField:field];
2008      }
2009      break;
2010
2011//%PDDM-EXPAND FIELD_CASE(UInt32, UInt32)
2012// This block of code is generated, do not edit it directly.
2013
2014    case GPBDataTypeUInt32:
2015      if (fieldType == GPBFieldTypeRepeated) {
2016        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
2017        GPBUInt32Array *array =
2018            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2019        [output writeUInt32Array:fieldNumber values:array tag:tag];
2020      } else if (fieldType == GPBFieldTypeSingle) {
2021        [output writeUInt32:fieldNumber
2022                      value:GPBGetMessageUInt32Field(self, field)];
2023      } else {  // fieldType == GPBFieldTypeMap
2024        // Exact type here doesn't matter.
2025        GPBInt32UInt32Dictionary *dict =
2026            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2027        [dict writeToCodedOutputStream:output asField:field];
2028      }
2029      break;
2030
2031//%PDDM-EXPAND FIELD_CASE(UInt64, UInt64)
2032// This block of code is generated, do not edit it directly.
2033
2034    case GPBDataTypeUInt64:
2035      if (fieldType == GPBFieldTypeRepeated) {
2036        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
2037        GPBUInt64Array *array =
2038            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2039        [output writeUInt64Array:fieldNumber values:array tag:tag];
2040      } else if (fieldType == GPBFieldTypeSingle) {
2041        [output writeUInt64:fieldNumber
2042                      value:GPBGetMessageUInt64Field(self, field)];
2043      } else {  // fieldType == GPBFieldTypeMap
2044        // Exact type here doesn't matter.
2045        GPBInt32UInt64Dictionary *dict =
2046            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2047        [dict writeToCodedOutputStream:output asField:field];
2048      }
2049      break;
2050
2051//%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum)
2052// This block of code is generated, do not edit it directly.
2053
2054    case GPBDataTypeEnum:
2055      if (fieldType == GPBFieldTypeRepeated) {
2056        uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
2057        GPBEnumArray *array =
2058            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2059        [output writeEnumArray:fieldNumber values:array tag:tag];
2060      } else if (fieldType == GPBFieldTypeSingle) {
2061        [output writeEnum:fieldNumber
2062                    value:GPBGetMessageInt32Field(self, field)];
2063      } else {  // fieldType == GPBFieldTypeMap
2064        // Exact type here doesn't matter.
2065        GPBInt32EnumDictionary *dict =
2066            GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2067        [dict writeToCodedOutputStream:output asField:field];
2068      }
2069      break;
2070
2071//%PDDM-EXPAND FIELD_CASE2(Bytes)
2072// This block of code is generated, do not edit it directly.
2073
2074    case GPBDataTypeBytes:
2075      if (fieldType == GPBFieldTypeRepeated) {
2076        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2077        [output writeBytesArray:fieldNumber values:array];
2078      } else if (fieldType == GPBFieldTypeSingle) {
2079        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
2080        // again.
2081        [output writeBytes:fieldNumber
2082                     value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
2083      } else {  // fieldType == GPBFieldTypeMap
2084        // Exact type here doesn't matter.
2085        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2086        GPBDataType mapKeyDataType = field.mapKeyDataType;
2087        if (mapKeyDataType == GPBDataTypeString) {
2088          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
2089        } else {
2090          [dict writeToCodedOutputStream:output asField:field];
2091        }
2092      }
2093      break;
2094
2095//%PDDM-EXPAND FIELD_CASE2(String)
2096// This block of code is generated, do not edit it directly.
2097
2098    case GPBDataTypeString:
2099      if (fieldType == GPBFieldTypeRepeated) {
2100        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2101        [output writeStringArray:fieldNumber values:array];
2102      } else if (fieldType == GPBFieldTypeSingle) {
2103        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
2104        // again.
2105        [output writeString:fieldNumber
2106                      value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
2107      } else {  // fieldType == GPBFieldTypeMap
2108        // Exact type here doesn't matter.
2109        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2110        GPBDataType mapKeyDataType = field.mapKeyDataType;
2111        if (mapKeyDataType == GPBDataTypeString) {
2112          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
2113        } else {
2114          [dict writeToCodedOutputStream:output asField:field];
2115        }
2116      }
2117      break;
2118
2119//%PDDM-EXPAND FIELD_CASE2(Message)
2120// This block of code is generated, do not edit it directly.
2121
2122    case GPBDataTypeMessage:
2123      if (fieldType == GPBFieldTypeRepeated) {
2124        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2125        [output writeMessageArray:fieldNumber values:array];
2126      } else if (fieldType == GPBFieldTypeSingle) {
2127        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
2128        // again.
2129        [output writeMessage:fieldNumber
2130                       value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
2131      } else {  // fieldType == GPBFieldTypeMap
2132        // Exact type here doesn't matter.
2133        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2134        GPBDataType mapKeyDataType = field.mapKeyDataType;
2135        if (mapKeyDataType == GPBDataTypeString) {
2136          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
2137        } else {
2138          [dict writeToCodedOutputStream:output asField:field];
2139        }
2140      }
2141      break;
2142
2143//%PDDM-EXPAND FIELD_CASE2(Group)
2144// This block of code is generated, do not edit it directly.
2145
2146    case GPBDataTypeGroup:
2147      if (fieldType == GPBFieldTypeRepeated) {
2148        NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2149        [output writeGroupArray:fieldNumber values:array];
2150      } else if (fieldType == GPBFieldTypeSingle) {
2151        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
2152        // again.
2153        [output writeGroup:fieldNumber
2154                     value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
2155      } else {  // fieldType == GPBFieldTypeMap
2156        // Exact type here doesn't matter.
2157        id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2158        GPBDataType mapKeyDataType = field.mapKeyDataType;
2159        if (mapKeyDataType == GPBDataTypeString) {
2160          GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
2161        } else {
2162          [dict writeToCodedOutputStream:output asField:field];
2163        }
2164      }
2165      break;
2166
2167//%PDDM-EXPAND-END (18 expansions)
2168
2169      // clang-format on
2170  }
2171}
2172
2173#pragma mark - Extensions
2174
2175- (id)getExtension:(GPBExtensionDescriptor *)extension {
2176  CheckExtension(self, extension);
2177  id value = [extensionMap_ objectForKey:extension];
2178  if (value != nil) {
2179    return value;
2180  }
2181
2182  // No default for repeated.
2183  if (extension.isRepeated) {
2184    return nil;
2185  }
2186  // Non messages get their default.
2187  if (!GPBExtensionIsMessage(extension)) {
2188    return extension.defaultValue;
2189  }
2190
2191  // Check for an autocreated value.
2192  os_unfair_lock_lock(&readOnlyLock_);
2193  value = [autocreatedExtensionMap_ objectForKey:extension];
2194  if (!value) {
2195    // Auto create the message extensions to match normal fields.
2196    value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, extension);
2197
2198    if (autocreatedExtensionMap_ == nil) {
2199      autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init];
2200    }
2201
2202    // We can't simply call setExtension here because that would clear the new
2203    // value's autocreator.
2204    [autocreatedExtensionMap_ setObject:value forKey:extension];
2205    [value release];
2206  }
2207
2208  os_unfair_lock_unlock(&readOnlyLock_);
2209  return value;
2210}
2211
2212- (id)getExistingExtension:(GPBExtensionDescriptor *)extension {
2213  // This is an internal method so we don't need to call CheckExtension().
2214  return [extensionMap_ objectForKey:extension];
2215}
2216
2217- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension {
2218#if defined(DEBUG) && DEBUG
2219  CheckExtension(self, extension);
2220#endif  // DEBUG
2221  return nil != [extensionMap_ objectForKey:extension];
2222}
2223
2224- (NSArray *)extensionsCurrentlySet {
2225  return [extensionMap_ allKeys];
2226}
2227
2228- (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output
2229                                     range:(GPBExtensionRange)range
2230                          sortedExtensions:(NSArray *)sortedExtensions {
2231  uint32_t start = range.start;
2232  uint32_t end = range.end;
2233  for (GPBExtensionDescriptor *extension in sortedExtensions) {
2234    uint32_t fieldNumber = extension.fieldNumber;
2235    if (fieldNumber < start) {
2236      continue;
2237    }
2238    if (fieldNumber >= end) {
2239      break;
2240    }
2241    id value = [extensionMap_ objectForKey:extension];
2242    GPBWriteExtensionValueToOutputStream(extension, value, output);
2243  }
2244}
2245
2246- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value {
2247  if (!value) {
2248    [self clearExtension:extension];
2249    return;
2250  }
2251
2252  CheckExtension(self, extension);
2253
2254  if (extension.repeated) {
2255    [NSException raise:NSInvalidArgumentException
2256                format:@"Must call addExtension() for repeated types."];
2257  }
2258
2259  if (extensionMap_ == nil) {
2260    extensionMap_ = [[NSMutableDictionary alloc] init];
2261  }
2262
2263  // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION.
2264  // Without it, the compiler complains we're passing an id nullable when
2265  // setObject:forKey: requires a id nonnull for the value. The check for
2266  // !value at the start of the method ensures it isn't nil, but the check
2267  // isn't smart enough to realize that.
2268  [extensionMap_ setObject:(id)value forKey:extension];
2269
2270  GPBExtensionDescriptor *descriptor = extension;
2271
2272  if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) {
2273    GPBMessage *autocreatedValue = [[autocreatedExtensionMap_ objectForKey:extension] retain];
2274    // Must remove from the map before calling GPBClearMessageAutocreator() so
2275    // that GPBClearMessageAutocreator() knows its safe to clear.
2276    [autocreatedExtensionMap_ removeObjectForKey:extension];
2277    GPBClearMessageAutocreator(autocreatedValue);
2278    [autocreatedValue release];
2279  }
2280
2281  GPBBecomeVisibleToAutocreator(self);
2282}
2283
2284- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value {
2285  CheckExtension(self, extension);
2286
2287  if (!extension.repeated) {
2288    [NSException raise:NSInvalidArgumentException
2289                format:@"Must call setExtension() for singular types."];
2290  }
2291
2292  if (extensionMap_ == nil) {
2293    extensionMap_ = [[NSMutableDictionary alloc] init];
2294  }
2295  NSMutableArray *list = [extensionMap_ objectForKey:extension];
2296  if (list == nil) {
2297    list = [NSMutableArray array];
2298    [extensionMap_ setObject:list forKey:extension];
2299  }
2300
2301  [list addObject:value];
2302  GPBBecomeVisibleToAutocreator(self);
2303}
2304
2305- (void)setExtension:(GPBExtensionDescriptor *)extension index:(NSUInteger)idx value:(id)value {
2306  CheckExtension(self, extension);
2307
2308  if (!extension.repeated) {
2309    [NSException raise:NSInvalidArgumentException
2310                format:@"Must call setExtension() for singular types."];
2311  }
2312
2313  if (extensionMap_ == nil) {
2314    extensionMap_ = [[NSMutableDictionary alloc] init];
2315  }
2316
2317  NSMutableArray *list = [extensionMap_ objectForKey:extension];
2318
2319  [list replaceObjectAtIndex:idx withObject:value];
2320  GPBBecomeVisibleToAutocreator(self);
2321}
2322
2323- (void)clearExtension:(GPBExtensionDescriptor *)extension {
2324  CheckExtension(self, extension);
2325
2326  // Only become visible if there was actually a value to clear.
2327  if ([extensionMap_ objectForKey:extension]) {
2328    [extensionMap_ removeObjectForKey:extension];
2329    GPBBecomeVisibleToAutocreator(self);
2330  }
2331}
2332
2333#pragma mark - mergeFrom
2334
2335- (void)mergeFromData:(NSData *)data extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
2336  GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
2337  @try {
2338    [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
2339  } @finally {
2340    [input release];
2341  }
2342}
2343
2344- (BOOL)mergeFromData:(NSData *)data
2345    extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
2346                error:(NSError **)errorPtr {
2347  GPBBecomeVisibleToAutocreator(self);
2348  GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
2349  @try {
2350    [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
2351    [input checkLastTagWas:0];
2352    if (errorPtr) {
2353      *errorPtr = nil;
2354    }
2355  } @catch (NSException *exception) {
2356    [input release];
2357    if (errorPtr) {
2358      *errorPtr = ErrorFromException(exception);
2359    }
2360    return NO;
2361  }
2362  [input release];
2363  return YES;
2364}
2365
2366#pragma mark - Parse From Data Support
2367
2368+ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr {
2369  return [self parseFromData:data extensionRegistry:nil error:errorPtr];
2370}
2371
2372+ (instancetype)parseFromData:(NSData *)data
2373            extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
2374                        error:(NSError **)errorPtr {
2375  return [[[self alloc] initWithData:data extensionRegistry:extensionRegistry
2376                               error:errorPtr] autorelease];
2377}
2378
2379+ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
2380                        extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
2381                                    error:(NSError **)errorPtr {
2382  return [[[self alloc] initWithCodedInputStream:input
2383                               extensionRegistry:extensionRegistry
2384                                           error:errorPtr] autorelease];
2385}
2386
2387#pragma mark - Parse Delimited From Data Support
2388
2389+ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
2390                                 extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
2391                                             error:(NSError **)errorPtr {
2392  GPBCodedInputStreamState *state = &input->state_;
2393  // This doesn't completely match the C++, but if the stream has nothing, just make an empty
2394  // message.
2395  if (GPBCodedInputStreamIsAtEnd(state)) {
2396    return [[[self alloc] init] autorelease];
2397  }
2398
2399  // Manually extract the data and parse it. If we read a varint and push a limit, that consumes
2400  // some of the recursion buffer which isn't correct, it also can result in a change in error
2401  // codes for attempts to parse partial data; and there are projects sensitive to that, so this
2402  // maintains existing error flows.
2403
2404  // Extract the data, but in a "no copy" mode since we will immediately parse it so this NSData
2405  // is transient.
2406  NSData *data = nil;
2407  @try {
2408    data = GPBCodedInputStreamReadRetainedBytesNoCopy(state);
2409  } @catch (NSException *exception) {
2410    if (errorPtr) {
2411      *errorPtr = ErrorFromException(exception);
2412    }
2413    return nil;
2414  }
2415
2416  GPBMessage *result = [self parseFromData:data extensionRegistry:extensionRegistry error:errorPtr];
2417  [data release];
2418  if (result && errorPtr) {
2419    *errorPtr = nil;
2420  }
2421  return result;
2422}
2423
2424#pragma mark - Unknown Field Support
2425
2426- (GPBUnknownFieldSet *)unknownFields {
2427  @synchronized(self) {
2428    if (unknownFieldData_) {
2429#if defined(DEBUG) && DEBUG
2430      NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set");
2431#endif
2432      unknownFields_ = [[GPBUnknownFieldSet alloc] init];
2433      MergeUnknownFieldDataIntoFieldSet(self, unknownFieldData_, nil);
2434      [unknownFieldData_ release];
2435      unknownFieldData_ = nil;
2436    }
2437    return unknownFields_;
2438  }  // @synchronized(self)
2439}
2440
2441- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields {
2442  if (unknownFields != unknownFields_ || unknownFieldData_ != nil) {
2443    // Changing sets or clearing.
2444    [unknownFieldData_ release];
2445    unknownFieldData_ = nil;
2446    [unknownFields_ release];
2447    unknownFields_ = [unknownFields copy];
2448    GPBBecomeVisibleToAutocreator(self);
2449  }
2450}
2451
2452- (void)parseMessageSet:(GPBCodedInputStream *)input
2453      extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
2454  uint32_t typeId = 0;
2455  NSData *rawBytes = nil;
2456  GPBCodedInputStreamState *state = &input->state_;
2457  BOOL gotType = NO;
2458  BOOL gotBytes = NO;
2459  while (true) {
2460    uint32_t tag = GPBCodedInputStreamReadTag(state);
2461    if (tag == GPBWireFormatMessageSetItemEndTag || tag == 0) {
2462      break;
2463    }
2464
2465    if (tag == GPBWireFormatMessageSetTypeIdTag) {
2466      uint32_t tmp = GPBCodedInputStreamReadUInt32(state);
2467      // Spec says only use the first value.
2468      if (!gotType) {
2469        gotType = YES;
2470        typeId = tmp;
2471      }
2472    } else if (tag == GPBWireFormatMessageSetMessageTag) {
2473      if (gotBytes) {
2474        // Skip over the payload instead of collecting it.
2475        [input skipField:tag];
2476      } else {
2477        rawBytes = [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease];
2478        gotBytes = YES;
2479      }
2480    } else {
2481      // Don't capture unknowns within the message set impl group.
2482      if (![input skipField:tag]) {
2483        break;
2484      }
2485    }
2486  }
2487
2488  // If we get here because of end of input (tag zero) or the wrong end tag (within the skipField:),
2489  // this will error.
2490  GPBCodedInputStreamCheckLastTagWas(state, GPBWireFormatMessageSetItemEndTag);
2491
2492  if (!gotType || !gotBytes) {
2493    // upb_Decoder_DecodeMessageSetItem does't keep this partial as an unknown field, it just drops
2494    // it, so do the same thing.
2495    return;
2496  }
2497
2498  GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor:[self descriptor]
2499                                                                    fieldNumber:typeId];
2500  if (extension) {
2501#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
2502    NSAssert(extension.dataType == GPBDataTypeMessage,
2503             @"Internal Error: MessageSet extension must be a message field.");
2504    NSAssert(GPBExtensionIsWireFormat(extension->description_),
2505             @"Internal Error: MessageSet extension must have message_set_wire_format set.");
2506    NSAssert(!GPBExtensionIsRepeated(extension->description_),
2507             @"Internal Error: MessageSet extension can't be repeated.");
2508#endif
2509    // Look up the existing one to merge to or create a new one.
2510    GPBMessage *targetMessage = [self getExistingExtension:extension];
2511    if (!targetMessage) {
2512      GPBDescriptor *descriptor = [extension.msgClass descriptor];
2513      targetMessage = [[descriptor.messageClass alloc] init];
2514      [self setExtension:extension value:targetMessage];
2515      [targetMessage release];
2516    }
2517    GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc] initWithData:rawBytes];
2518    @try {
2519      [targetMessage mergeFromCodedInputStream:newInput
2520                             extensionRegistry:extensionRegistry
2521                                     endingTag:0];
2522    } @finally {
2523      [newInput release];
2524    }
2525  } else {
2526    // The extension isn't in the registry, but it was well formed, so the whole group structure
2527    // get preserved as an unknown field.
2528
2529    // rawBytes was created via a NoCopy, so it can be reusing a
2530    // subrange of another NSData that might go out of scope as things
2531    // unwind, so a copy is needed to ensure what is saved in the
2532    // unknown fields stays valid.
2533    NSData *cloned = [NSData dataWithData:rawBytes];
2534    AddUnknownMessageSetEntry(self, typeId, cloned);
2535  }
2536}
2537
2538- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
2539  AddUnknownFieldLengthDelimited(self, fieldNum, data);
2540}
2541
2542#pragma mark - MergeFromCodedInputStream Support
2543
2544static void MergeSingleFieldFromCodedInputStream(GPBMessage *self, GPBFieldDescriptor *field,
2545                                                 GPBCodedInputStream *input,
2546                                                 id<GPBExtensionRegistry> extensionRegistry) {
2547  GPBDataType fieldDataType = GPBGetFieldDataType(field);
2548  switch (fieldDataType) {
2549#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                 \
2550  case GPBDataType##NAME: {                                    \
2551    TYPE val = GPBCodedInputStreamRead##NAME(&input->state_);  \
2552    GPBSet##FUNC_TYPE##IvarWithFieldPrivate(self, field, val); \
2553    break;                                                     \
2554  }
2555#define CASE_SINGLE_OBJECT(NAME)                                    \
2556  case GPBDataType##NAME: {                                         \
2557    id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \
2558    GPBSetRetainedObjectIvarWithFieldPrivate(self, field, val);     \
2559    break;                                                          \
2560  }
2561    CASE_SINGLE_POD(Bool, BOOL, Bool)
2562    CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
2563    CASE_SINGLE_POD(SFixed32, int32_t, Int32)
2564    CASE_SINGLE_POD(Float, float, Float)
2565    CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
2566    CASE_SINGLE_POD(SFixed64, int64_t, Int64)
2567    CASE_SINGLE_POD(Double, double, Double)
2568    CASE_SINGLE_POD(Int32, int32_t, Int32)
2569    CASE_SINGLE_POD(Int64, int64_t, Int64)
2570    CASE_SINGLE_POD(SInt32, int32_t, Int32)
2571    CASE_SINGLE_POD(SInt64, int64_t, Int64)
2572    CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
2573    CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
2574    CASE_SINGLE_OBJECT(Bytes)
2575    CASE_SINGLE_OBJECT(String)
2576#undef CASE_SINGLE_POD
2577#undef CASE_SINGLE_OBJECT
2578
2579    case GPBDataTypeMessage: {
2580      if (GPBGetHasIvarField(self, field)) {
2581        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
2582        // check again.
2583        GPBMessage *message = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2584        [input readMessage:message extensionRegistry:extensionRegistry];
2585      } else {
2586        GPBMessage *message = [[field.msgClass alloc] init];
2587        GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
2588        [input readMessage:message extensionRegistry:extensionRegistry];
2589      }
2590      break;
2591    }
2592
2593    case GPBDataTypeGroup: {
2594      if (GPBGetHasIvarField(self, field)) {
2595        // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
2596        // check again.
2597        GPBMessage *message = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2598        [input readGroup:GPBFieldNumber(field) message:message extensionRegistry:extensionRegistry];
2599      } else {
2600        GPBMessage *message = [[field.msgClass alloc] init];
2601        GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
2602        [input readGroup:GPBFieldNumber(field) message:message extensionRegistry:extensionRegistry];
2603      }
2604      break;
2605    }
2606
2607    case GPBDataTypeEnum: {
2608      int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
2609      if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
2610        GPBSetInt32IvarWithFieldPrivate(self, field, val);
2611      } else {
2612        AddUnknownFieldVarint32(self, GPBFieldNumber(field), val);
2613      }
2614    }
2615  }  // switch
2616}
2617
2618static void MergeRepeatedPackedFieldFromCodedInputStream(GPBMessage *self,
2619                                                         GPBFieldDescriptor *field,
2620                                                         GPBCodedInputStream *input) {
2621  GPBDataType fieldDataType = GPBGetFieldDataType(field);
2622  GPBCodedInputStreamState *state = &input->state_;
2623  id genericArray = GetOrCreateArrayIvarWithField(self, field);
2624  int32_t length = GPBCodedInputStreamReadInt32(state);
2625  size_t limit = GPBCodedInputStreamPushLimit(state, length);
2626  while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
2627    switch (fieldDataType) {
2628#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE)   \
2629  case GPBDataType##NAME: {                                \
2630    TYPE val = GPBCodedInputStreamRead##NAME(state);       \
2631    [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \
2632    break;                                                 \
2633  }
2634      CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool)
2635      CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32)
2636      CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32)
2637      CASE_REPEATED_PACKED_POD(Float, float, Float)
2638      CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64)
2639      CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64)
2640      CASE_REPEATED_PACKED_POD(Double, double, Double)
2641      CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32)
2642      CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64)
2643      CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32)
2644      CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64)
2645      CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32)
2646      CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64)
2647#undef CASE_REPEATED_PACKED_POD
2648
2649      case GPBDataTypeBytes:
2650      case GPBDataTypeString:
2651      case GPBDataTypeMessage:
2652      case GPBDataTypeGroup:
2653        NSCAssert(NO, @"Non primitive types can't be packed");
2654        break;
2655
2656      case GPBDataTypeEnum: {
2657        int32_t val = GPBCodedInputStreamReadEnum(state);
2658        if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
2659          [(GPBEnumArray *)genericArray addRawValue:val];
2660        } else {
2661          AddUnknownFieldVarint32(self, GPBFieldNumber(field), val);
2662        }
2663        break;
2664      }
2665    }  // switch
2666  }  // while(BytesUntilLimit() > 0)
2667  GPBCodedInputStreamPopLimit(state, limit);
2668}
2669
2670static void MergeRepeatedNotPackedFieldFromCodedInputStream(
2671    GPBMessage *self, GPBFieldDescriptor *field, GPBCodedInputStream *input,
2672    id<GPBExtensionRegistry> extensionRegistry) {
2673  GPBCodedInputStreamState *state = &input->state_;
2674  id genericArray = GetOrCreateArrayIvarWithField(self, field);
2675  switch (GPBGetFieldDataType(field)) {
2676#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \
2677  case GPBDataType##NAME: {                                  \
2678    TYPE val = GPBCodedInputStreamRead##NAME(state);         \
2679    [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val];   \
2680    break;                                                   \
2681  }
2682#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME)              \
2683  case GPBDataType##NAME: {                                \
2684    id val = GPBCodedInputStreamReadRetained##NAME(state); \
2685    [(NSMutableArray *)genericArray addObject:val];        \
2686    [val release];                                         \
2687    break;                                                 \
2688  }
2689    CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool)
2690    CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32)
2691    CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32)
2692    CASE_REPEATED_NOT_PACKED_POD(Float, float, Float)
2693    CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64)
2694    CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64)
2695    CASE_REPEATED_NOT_PACKED_POD(Double, double, Double)
2696    CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32)
2697    CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64)
2698    CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32)
2699    CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64)
2700    CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32)
2701    CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64)
2702    CASE_REPEATED_NOT_PACKED_OBJECT(Bytes)
2703    CASE_REPEATED_NOT_PACKED_OBJECT(String)
2704#undef CASE_REPEATED_NOT_PACKED_POD
2705#undef CASE_NOT_PACKED_OBJECT
2706    case GPBDataTypeMessage: {
2707      GPBMessage *message = [[field.msgClass alloc] init];
2708      [(NSMutableArray *)genericArray addObject:message];
2709      // The array will now retain message, so go ahead and release it in case
2710      // -readMessage:extensionRegistry: throws so it won't be leaked.
2711      [message release];
2712      [input readMessage:message extensionRegistry:extensionRegistry];
2713      break;
2714    }
2715    case GPBDataTypeGroup: {
2716      GPBMessage *message = [[field.msgClass alloc] init];
2717      [(NSMutableArray *)genericArray addObject:message];
2718      // The array will now retain message, so go ahead and release it in case
2719      // -readGroup:extensionRegistry: throws so it won't be leaked.
2720      [message release];
2721      [input readGroup:GPBFieldNumber(field) message:message extensionRegistry:extensionRegistry];
2722      break;
2723    }
2724    case GPBDataTypeEnum: {
2725      int32_t val = GPBCodedInputStreamReadEnum(state);
2726      if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
2727        [(GPBEnumArray *)genericArray addRawValue:val];
2728      } else {
2729        AddUnknownFieldVarint32(self, GPBFieldNumber(field), val);
2730      }
2731      break;
2732    }
2733  }  // switch
2734}
2735
2736- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
2737                extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
2738                        endingTag:(uint32_t)endingTag {
2739#if defined(DEBUG) && DEBUG
2740  NSAssert(endingTag == 0 || GPBWireFormatGetTagWireType(endingTag) == GPBWireFormatEndGroup,
2741           @"endingTag should have been an endGroup tag");
2742#endif  // DEBUG
2743  GPBDescriptor *descriptor = [self descriptor];
2744  GPBCodedInputStreamState *state = &input->state_;
2745  uint32_t tag = 0;
2746  NSUInteger startingIndex = 0;
2747  NSArray *fields = descriptor->fields_;
2748  BOOL isMessageSetWireFormat = descriptor.isWireFormat;
2749  NSUInteger numFields = fields.count;
2750  while (YES) {
2751    BOOL merged = NO;
2752    tag = GPBCodedInputStreamReadTag(state);
2753    if (tag == endingTag || tag == 0) {
2754      // If we got to the end (tag zero), when we were expecting the end group, this will
2755      // raise the error.
2756      GPBCodedInputStreamCheckLastTagWas(state, endingTag);
2757      return;
2758    }
2759    for (NSUInteger i = 0; i < numFields; ++i) {
2760      if (startingIndex >= numFields) startingIndex = 0;
2761      GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
2762      if (GPBFieldTag(fieldDescriptor) == tag) {
2763        GPBFieldType fieldType = fieldDescriptor.fieldType;
2764        if (fieldType == GPBFieldTypeSingle) {
2765          MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, input, extensionRegistry);
2766          // Well formed protos will only have a single field once, advance
2767          // the starting index to the next field.
2768          startingIndex += 1;
2769        } else if (fieldType == GPBFieldTypeRepeated) {
2770          if (fieldDescriptor.isPackable) {
2771            MergeRepeatedPackedFieldFromCodedInputStream(self, fieldDescriptor, input);
2772            // Well formed protos will only have a repeated field that is
2773            // packed once, advance the starting index to the next field.
2774            startingIndex += 1;
2775          } else {
2776            MergeRepeatedNotPackedFieldFromCodedInputStream(self, fieldDescriptor, input,
2777                                                            extensionRegistry);
2778          }
2779        } else {  // fieldType == GPBFieldTypeMap
2780          // GPB*Dictionary or NSDictionary, exact type doesn't matter at this
2781          // point.
2782          id map = GetOrCreateMapIvarWithField(self, fieldDescriptor);
2783          [input readMapEntry:map
2784              extensionRegistry:extensionRegistry
2785                          field:fieldDescriptor
2786                  parentMessage:self];
2787        }
2788        merged = YES;
2789        break;
2790      } else {
2791        startingIndex += 1;
2792      }
2793    }  // for(i < numFields)
2794
2795    if (merged) continue;  // On to the next tag
2796
2797    // Primitive, repeated types can be packed or unpacked on the wire, and
2798    // are parsed either way.  The above loop covered tag in the preferred
2799    // for, so this need to check the alternate form.
2800    for (NSUInteger i = 0; i < numFields; ++i) {
2801      if (startingIndex >= numFields) startingIndex = 0;
2802      GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
2803      if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) &&
2804          !GPBFieldDataTypeIsObject(fieldDescriptor) &&
2805          (GPBFieldAlternateTag(fieldDescriptor) == tag)) {
2806        BOOL alternateIsPacked = !fieldDescriptor.isPackable;
2807        if (alternateIsPacked) {
2808          MergeRepeatedPackedFieldFromCodedInputStream(self, fieldDescriptor, input);
2809          // Well formed protos will only have a repeated field that is
2810          // packed once, advance the starting index to the next field.
2811          startingIndex += 1;
2812        } else {
2813          MergeRepeatedNotPackedFieldFromCodedInputStream(self, fieldDescriptor, input,
2814                                                          extensionRegistry);
2815        }
2816        merged = YES;
2817        break;
2818      } else {
2819        startingIndex += 1;
2820      }
2821    }
2822
2823    if (merged) continue;  // On to the next tag
2824
2825    if (isMessageSetWireFormat) {
2826      if (GPBWireFormatMessageSetItemTag == tag) {
2827        [self parseMessageSet:input extensionRegistry:extensionRegistry];
2828        continue;  // On to the next tag
2829      }
2830    } else {
2831      // ObjC Runtime currently doesn't track if a message supported extensions, so the check is
2832      // always done.
2833      GPBExtensionDescriptor *extension =
2834          [extensionRegistry extensionForDescriptor:descriptor
2835                                        fieldNumber:GPBWireFormatGetTagFieldNumber(tag)];
2836      if (extension) {
2837        GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
2838        if (extension.wireType == wireType) {
2839          ExtensionMergeFromInputStream(extension, extension.packable, input, extensionRegistry,
2840                                        self);
2841          continue;  // On to the next tag
2842        }
2843        // Primitive, repeated types can be packed on unpacked on the wire, and are
2844        // parsed either way.
2845        if ([extension isRepeated] && !GPBDataTypeIsObject(extension->description_->dataType) &&
2846            (extension.alternateWireType == wireType)) {
2847          ExtensionMergeFromInputStream(extension, !extension.packable, input, extensionRegistry,
2848                                        self);
2849          continue;  // On to the next tag
2850        }
2851      }
2852    }
2853
2854    ParseUnknownField(self, tag, input);
2855  }  // while(YES)
2856}
2857
2858#pragma mark - MergeFrom Support
2859
2860- (void)mergeFrom:(GPBMessage *)other {
2861  Class selfClass = [self class];
2862  Class otherClass = [other class];
2863  if (!([selfClass isSubclassOfClass:otherClass] || [otherClass isSubclassOfClass:selfClass])) {
2864    [NSException raise:NSInvalidArgumentException
2865                format:@"Classes must match %@ != %@", selfClass, otherClass];
2866  }
2867
2868  // We assume something will be done and become visible.
2869  GPBBecomeVisibleToAutocreator(self);
2870
2871  GPBDescriptor *descriptor = [[self class] descriptor];
2872
2873  for (GPBFieldDescriptor *field in descriptor->fields_) {
2874    GPBFieldType fieldType = field.fieldType;
2875    if (fieldType == GPBFieldTypeSingle) {
2876      int32_t hasIndex = GPBFieldHasIndex(field);
2877      uint32_t fieldNumber = GPBFieldNumber(field);
2878      if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) {
2879        // Other doesn't have the field set, on to the next.
2880        continue;
2881      }
2882      GPBDataType fieldDataType = GPBGetFieldDataType(field);
2883      switch (fieldDataType) {
2884        case GPBDataTypeBool:
2885          GPBSetBoolIvarWithFieldPrivate(self, field, GPBGetMessageBoolField(other, field));
2886          break;
2887        case GPBDataTypeSFixed32:
2888        case GPBDataTypeEnum:
2889        case GPBDataTypeInt32:
2890        case GPBDataTypeSInt32:
2891          GPBSetInt32IvarWithFieldPrivate(self, field, GPBGetMessageInt32Field(other, field));
2892          break;
2893        case GPBDataTypeFixed32:
2894        case GPBDataTypeUInt32:
2895          GPBSetUInt32IvarWithFieldPrivate(self, field, GPBGetMessageUInt32Field(other, field));
2896          break;
2897        case GPBDataTypeSFixed64:
2898        case GPBDataTypeInt64:
2899        case GPBDataTypeSInt64:
2900          GPBSetInt64IvarWithFieldPrivate(self, field, GPBGetMessageInt64Field(other, field));
2901          break;
2902        case GPBDataTypeFixed64:
2903        case GPBDataTypeUInt64:
2904          GPBSetUInt64IvarWithFieldPrivate(self, field, GPBGetMessageUInt64Field(other, field));
2905          break;
2906        case GPBDataTypeFloat:
2907          GPBSetFloatIvarWithFieldPrivate(self, field, GPBGetMessageFloatField(other, field));
2908          break;
2909        case GPBDataTypeDouble:
2910          GPBSetDoubleIvarWithFieldPrivate(self, field, GPBGetMessageDoubleField(other, field));
2911          break;
2912        case GPBDataTypeBytes:
2913        case GPBDataTypeString: {
2914          id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2915          GPBSetObjectIvarWithFieldPrivate(self, field, otherVal);
2916          break;
2917        }
2918        case GPBDataTypeMessage:
2919        case GPBDataTypeGroup: {
2920          id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2921          if (GPBGetHasIvar(self, hasIndex, fieldNumber)) {
2922            GPBMessage *message = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2923            [message mergeFrom:otherVal];
2924          } else {
2925            GPBMessage *message = [otherVal copy];
2926            GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message);
2927          }
2928          break;
2929        }
2930      }  // switch()
2931    } else if (fieldType == GPBFieldTypeRepeated) {
2932      // In the case of a list, they need to be appended, and there is no
2933      // _hasIvar to worry about setting.
2934      id otherArray = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2935      if (otherArray) {
2936        GPBDataType fieldDataType = field->description_->dataType;
2937        if (GPBDataTypeIsObject(fieldDataType)) {
2938          NSMutableArray *resultArray = GetOrCreateArrayIvarWithField(self, field);
2939          [resultArray addObjectsFromArray:otherArray];
2940        } else if (fieldDataType == GPBDataTypeEnum) {
2941          GPBEnumArray *resultArray = GetOrCreateArrayIvarWithField(self, field);
2942          [resultArray addRawValuesFromArray:otherArray];
2943        } else {
2944          // The array type doesn't matter, that all implement
2945          // -addValuesFromArray:.
2946          GPBInt32Array *resultArray = GetOrCreateArrayIvarWithField(self, field);
2947          [resultArray addValuesFromArray:otherArray];
2948        }
2949      }
2950    } else {  // fieldType = GPBFieldTypeMap
2951      // In the case of a map, they need to be merged, and there is no
2952      // _hasIvar to worry about setting.
2953      id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2954      if (otherDict) {
2955        GPBDataType keyDataType = field.mapKeyDataType;
2956        GPBDataType valueDataType = field->description_->dataType;
2957        if (GPBDataTypeIsObject(keyDataType) && GPBDataTypeIsObject(valueDataType)) {
2958          NSMutableDictionary *resultDict = GetOrCreateMapIvarWithField(self, field);
2959          [resultDict addEntriesFromDictionary:otherDict];
2960        } else if (valueDataType == GPBDataTypeEnum) {
2961          // The exact type doesn't matter, just need to know it is a
2962          // GPB*EnumDictionary.
2963          GPBInt32EnumDictionary *resultDict = GetOrCreateMapIvarWithField(self, field);
2964          [resultDict addRawEntriesFromDictionary:otherDict];
2965        } else {
2966          // The exact type doesn't matter, they all implement
2967          // -addEntriesFromDictionary:.
2968          GPBInt32Int32Dictionary *resultDict = GetOrCreateMapIvarWithField(self, field);
2969          [resultDict addEntriesFromDictionary:otherDict];
2970        }
2971      }
2972    }  // if (fieldType)..else if...else
2973  }  // for(fields)
2974
2975  // Unknown fields.
2976  if (unknownFields_) {
2977#if defined(DEBUG) && DEBUG
2978    NSAssert(unknownFieldData_ == nil, @"Internal error both unknown states were set");
2979#endif
2980    @synchronized(other) {
2981      if (other->unknownFields_) {
2982#if defined(DEBUG) && DEBUG
2983        NSAssert(other->unknownFieldData_ == nil, @"Internal error both unknown states were set");
2984#endif
2985        [unknownFields_ mergeUnknownFields:other->unknownFields_];
2986      } else if (other->unknownFieldData_) {
2987        MergeUnknownFieldDataIntoFieldSet(self, other->unknownFieldData_, nil);
2988      }
2989    }  // @synchronized(other)
2990  } else {
2991    NSData *otherData = GPBMessageUnknownFieldsData(other);
2992    if (otherData) {
2993      if (unknownFieldData_) {
2994        [unknownFieldData_ appendData:otherData];
2995      } else {
2996        unknownFieldData_ = [otherData mutableCopy];
2997      }
2998    }
2999  }
3000
3001  // Extensions
3002
3003  if (other->extensionMap_.count == 0) {
3004    return;
3005  }
3006
3007  if (extensionMap_ == nil) {
3008    extensionMap_ = CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self));
3009  } else {
3010    for (GPBExtensionDescriptor *extension in other->extensionMap_) {
3011      id otherValue = [other->extensionMap_ objectForKey:extension];
3012      id value = [extensionMap_ objectForKey:extension];
3013      BOOL isMessageExtension = GPBExtensionIsMessage(extension);
3014
3015      if (extension.repeated) {
3016        NSMutableArray *list = value;
3017        if (list == nil) {
3018          list = [[NSMutableArray alloc] init];
3019          [extensionMap_ setObject:list forKey:extension];
3020          [list release];
3021        }
3022        if (isMessageExtension) {
3023          for (GPBMessage *otherListValue in otherValue) {
3024            GPBMessage *copiedValue = [otherListValue copy];
3025            [list addObject:copiedValue];
3026            [copiedValue release];
3027          }
3028        } else {
3029          [list addObjectsFromArray:otherValue];
3030        }
3031      } else {
3032        if (isMessageExtension) {
3033          if (value) {
3034            [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue];
3035          } else {
3036            GPBMessage *copiedValue = [otherValue copy];
3037            [extensionMap_ setObject:copiedValue forKey:extension];
3038            [copiedValue release];
3039          }
3040        } else {
3041          [extensionMap_ setObject:otherValue forKey:extension];
3042        }
3043      }
3044
3045      if (isMessageExtension && !extension.isRepeated) {
3046        GPBMessage *autocreatedValue = [[autocreatedExtensionMap_ objectForKey:extension] retain];
3047        // Must remove from the map before calling GPBClearMessageAutocreator()
3048        // so that GPBClearMessageAutocreator() knows its safe to clear.
3049        [autocreatedExtensionMap_ removeObjectForKey:extension];
3050        GPBClearMessageAutocreator(autocreatedValue);
3051        [autocreatedValue release];
3052      }
3053    }
3054  }
3055}
3056
3057#pragma mark - isEqual: & hash Support
3058
3059- (BOOL)isEqual:(id)other {
3060  if (other == self) {
3061    return YES;
3062  }
3063  if (![other isKindOfClass:[GPBMessage class]]) {
3064    return NO;
3065  }
3066  GPBMessage *otherMsg = other;
3067  GPBDescriptor *descriptor = [[self class] descriptor];
3068  if ([[otherMsg class] descriptor] != descriptor) {
3069    return NO;
3070  }
3071  uint8_t *selfStorage = (uint8_t *)messageStorage_;
3072  uint8_t *otherStorage = (uint8_t *)otherMsg->messageStorage_;
3073
3074  for (GPBFieldDescriptor *field in descriptor->fields_) {
3075    if (GPBFieldIsMapOrArray(field)) {
3076      // In the case of a list or map, there is no _hasIvar to worry about.
3077      // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but
3078      // the type doesn't really matter as the objects all support -count and
3079      // -isEqual:.
3080      NSArray *resultMapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
3081      NSArray *otherMapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
3082      // nil and empty are equal
3083      if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) {
3084        if (![resultMapOrArray isEqual:otherMapOrArray]) {
3085          return NO;
3086        }
3087      }
3088    } else {  // Single field
3089      int32_t hasIndex = GPBFieldHasIndex(field);
3090      uint32_t fieldNum = GPBFieldNumber(field);
3091      BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum);
3092      BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum);
3093      if (selfHas != otherHas) {
3094        return NO;  // Differing has values, not equal.
3095      }
3096      if (!selfHas) {
3097        // Same has values, was no, nothing else to check for this field.
3098        continue;
3099      }
3100      // Now compare the values.
3101      GPBDataType fieldDataType = GPBGetFieldDataType(field);
3102      size_t fieldOffset = field->description_->offset;
3103      switch (fieldDataType) {
3104        case GPBDataTypeBool: {
3105          // Bools are stored in has_bits to avoid needing explicit space in
3106          // the storage structure.
3107          // (the field number passed to the HasIvar helper doesn't really
3108          // matter since the offset is never negative)
3109          BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0);
3110          BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0);
3111          if (selfValue != otherValue) {
3112            return NO;
3113          }
3114          break;
3115        }
3116        case GPBDataTypeSFixed32:
3117        case GPBDataTypeInt32:
3118        case GPBDataTypeSInt32:
3119        case GPBDataTypeEnum:
3120        case GPBDataTypeFixed32:
3121        case GPBDataTypeUInt32:
3122        case GPBDataTypeFloat: {
3123          GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
3124          // These are all 32bit, signed/unsigned doesn't matter for equality.
3125          uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset];
3126          uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset];
3127          if (*selfValPtr != *otherValPtr) {
3128            return NO;
3129          }
3130          break;
3131        }
3132        case GPBDataTypeSFixed64:
3133        case GPBDataTypeInt64:
3134        case GPBDataTypeSInt64:
3135        case GPBDataTypeFixed64:
3136        case GPBDataTypeUInt64:
3137        case GPBDataTypeDouble: {
3138          GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
3139          // These are all 64bit, signed/unsigned doesn't matter for equality.
3140          uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset];
3141          uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset];
3142          if (*selfValPtr != *otherValPtr) {
3143            return NO;
3144          }
3145          break;
3146        }
3147        case GPBDataTypeBytes:
3148        case GPBDataTypeString:
3149        case GPBDataTypeMessage:
3150        case GPBDataTypeGroup: {
3151          // Type doesn't matter here, they all implement -isEqual:.
3152          id *selfValPtr = (id *)&selfStorage[fieldOffset];
3153          id *otherValPtr = (id *)&otherStorage[fieldOffset];
3154          if (![*selfValPtr isEqual:*otherValPtr]) {
3155            return NO;
3156          }
3157          break;
3158        }
3159      }  // switch()
3160    }  // if(mapOrArray)...else
3161  }  // for(fields)
3162
3163  // nil and empty are equal
3164  if (extensionMap_.count != 0 || otherMsg->extensionMap_.count != 0) {
3165    if (![extensionMap_ isEqual:otherMsg->extensionMap_]) {
3166      return NO;
3167    }
3168  }
3169
3170  // Mutation while another thread is doing read only access is invalid, so the only thing we
3171  // need to guard against is concurrent r/o access, so we can grab the values (and retain them)
3172  // so we have a version to compare against safely incase the second access causes the transform
3173  // between internal states.
3174#pragma clang diagnostic push
3175#pragma clang diagnostic ignored "-Wdeprecated-declarations"
3176  GPBUnknownFieldSet *selfUnknownFields;
3177  NSData *selfUnknownFieldData;
3178  @synchronized(self) {
3179    selfUnknownFields = [unknownFields_ retain];
3180    selfUnknownFieldData = [unknownFieldData_ retain];
3181  }
3182  GPBUnknownFieldSet *otherUnknownFields;
3183  NSData *otherUnknownFieldData;
3184  @synchronized(otherMsg) {
3185    otherUnknownFields = [otherMsg->unknownFields_ retain];
3186    otherUnknownFieldData = [otherMsg->unknownFieldData_ retain];
3187  }
3188#pragma clang diagnostic pop
3189#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
3190  if (selfUnknownFields) {
3191    NSAssert(selfUnknownFieldData == nil, @"Internal error both unknown states were set");
3192  }
3193  if (otherUnknownFields) {
3194    NSAssert(otherUnknownFieldData == nil, @"Internal error both unknown states were set");
3195  }
3196#endif
3197  // Since a developer can set the legacy unknownFieldSet, treat nil and empty as the same.
3198  if (selfUnknownFields && selfUnknownFields.countOfFields == 0) {
3199    [selfUnknownFields release];
3200    selfUnknownFields = nil;
3201  }
3202  if (otherUnknownFields && otherUnknownFields.countOfFields == 0) {
3203    [otherUnknownFields release];
3204    otherUnknownFields = nil;
3205  }
3206
3207  BOOL result = YES;
3208
3209  if (selfUnknownFieldData && otherUnknownFieldData) {
3210    // Both had data, compare it.
3211    result = [selfUnknownFieldData isEqual:otherUnknownFieldData];
3212  } else if (selfUnknownFields && otherUnknownFields) {
3213    // Both had fields set, compare them.
3214    result = [selfUnknownFields isEqual:otherUnknownFields];
3215  } else {
3216    // At this point, we're done to one have a set/nothing, and the other having data/nothing.
3217#pragma clang diagnostic push
3218#pragma clang diagnostic ignored "-Wdeprecated-declarations"
3219    GPBUnknownFieldSet *theSet = selfUnknownFields ? selfUnknownFields : otherUnknownFields;
3220    NSData *theData = selfUnknownFieldData ? selfUnknownFieldData : otherUnknownFieldData;
3221    if (theSet) {
3222      if (theData) {
3223        GPBUnknownFieldSet *tempSet = [[GPBUnknownFieldSet alloc] init];
3224        MergeUnknownFieldDataIntoFieldSet(self, theData, tempSet);
3225        result = [tempSet isEqual:theSet];
3226        [tempSet release];
3227      } else {
3228        result = NO;
3229      }
3230    } else {
3231      // It was a data/nothing and nothing, so they equal if the other didn't have data.
3232      result = theData == nil;
3233    }
3234#pragma clang diagnostic pop
3235  }
3236
3237  [selfUnknownFields release];
3238  [selfUnknownFieldData release];
3239  [otherUnknownFields release];
3240  [otherUnknownFieldData release];
3241  return result;
3242}
3243
3244// It is very difficult to implement a generic hash for ProtoBuf messages that
3245// will perform well. If you need hashing on your ProtoBufs (eg you are using
3246// them as dictionary keys) you will probably want to implement a ProtoBuf
3247// message specific hash as a category on your protobuf class. Do not make it a
3248// category on GPBMessage as you will conflict with this hash, and will possibly
3249// override hash for all generated protobufs. A good implementation of hash will
3250// be really fast, so we would recommend only hashing protobufs that have an
3251// identifier field of some kind that you can easily hash. If you implement
3252// hash, we would strongly recommend overriding isEqual: in your category as
3253// well, as the default implementation of isEqual: is extremely slow, and may
3254// drastically affect performance in large sets.
3255- (NSUInteger)hash {
3256  GPBDescriptor *descriptor = [[self class] descriptor];
3257  const NSUInteger prime = 19;
3258  uint8_t *storage = (uint8_t *)messageStorage_;
3259
3260  // Start with the descriptor and then mix it with some instance info.
3261  // Hopefully that will give a spread based on classes and what fields are set.
3262  NSUInteger result = (NSUInteger)descriptor;
3263
3264  for (GPBFieldDescriptor *field in descriptor->fields_) {
3265    if (GPBFieldIsMapOrArray(field)) {
3266      // Exact type doesn't matter, just check if there are any elements.
3267      NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
3268      NSUInteger count = mapOrArray.count;
3269      if (count) {
3270        // NSArray/NSDictionary use count, use the field number and the count.
3271        result = prime * result + GPBFieldNumber(field);
3272        result = prime * result + count;
3273      }
3274    } else if (GPBGetHasIvarField(self, field)) {
3275      // Just using the field number seemed simple/fast, but then a small
3276      // message class where all the same fields are always set (to different
3277      // things would end up all with the same hash, so pull in some data).
3278      GPBDataType fieldDataType = GPBGetFieldDataType(field);
3279      size_t fieldOffset = field->description_->offset;
3280      switch (fieldDataType) {
3281        case GPBDataTypeBool: {
3282          // Bools are stored in has_bits to avoid needing explicit space in
3283          // the storage structure.
3284          // (the field number passed to the HasIvar helper doesn't really
3285          // matter since the offset is never negative)
3286          BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0);
3287          result = prime * result + value;
3288          break;
3289        }
3290        case GPBDataTypeSFixed32:
3291        case GPBDataTypeInt32:
3292        case GPBDataTypeSInt32:
3293        case GPBDataTypeEnum:
3294        case GPBDataTypeFixed32:
3295        case GPBDataTypeUInt32:
3296        case GPBDataTypeFloat: {
3297          GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
3298          // These are all 32bit, just mix it in.
3299          uint32_t *valPtr = (uint32_t *)&storage[fieldOffset];
3300          result = prime * result + *valPtr;
3301          break;
3302        }
3303        case GPBDataTypeSFixed64:
3304        case GPBDataTypeInt64:
3305        case GPBDataTypeSInt64:
3306        case GPBDataTypeFixed64:
3307        case GPBDataTypeUInt64:
3308        case GPBDataTypeDouble: {
3309          GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
3310          // These are all 64bit, just mix what fits into an NSUInteger in.
3311          uint64_t *valPtr = (uint64_t *)&storage[fieldOffset];
3312          result = prime * result + (NSUInteger)(*valPtr);
3313          break;
3314        }
3315        case GPBDataTypeBytes:
3316        case GPBDataTypeString: {
3317          // Type doesn't matter here, they both implement -hash:.
3318          id *valPtr = (id *)&storage[fieldOffset];
3319          result = prime * result + [*valPtr hash];
3320          break;
3321        }
3322
3323        case GPBDataTypeMessage:
3324        case GPBDataTypeGroup: {
3325          GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset];
3326          // Could call -hash on the sub message, but that could recurse pretty
3327          // deep; follow the lead of NSArray/NSDictionary and don't really
3328          // recurse for hash, instead use the field number and the descriptor
3329          // of the sub message.  Yes, this could suck for a bunch of messages
3330          // where they all only differ in the sub messages, but if you are
3331          // using a message with sub messages for something that needs -hash,
3332          // odds are you are also copying them as keys, and that deep copy
3333          // will also suck.
3334          result = prime * result + GPBFieldNumber(field);
3335          result = prime * result + (NSUInteger)[[*valPtr class] descriptor];
3336          break;
3337        }
3338      }  // switch()
3339    }
3340  }
3341
3342  // Unknowns and extensions are not included.
3343
3344  return result;
3345}
3346
3347#pragma mark - Description Support
3348
3349- (NSString *)description {
3350  NSString *textFormat = GPBTextFormatForMessage(self, @"    ");
3351  NSString *description =
3352      [NSString stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat];
3353  return description;
3354}
3355
3356#if defined(DEBUG) && DEBUG
3357
3358// Xcode 5.1 added support for custom quick look info.
3359// 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
3360- (id)debugQuickLookObject {
3361  return GPBTextFormatForMessage(self, nil);
3362}
3363
3364#endif  // DEBUG
3365
3366#pragma mark - SerializedSize
3367
3368- (size_t)serializedSize {
3369  GPBDescriptor *descriptor = [[self class] descriptor];
3370  size_t result = 0;
3371
3372  // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate()
3373  // avoids doing the has check again.
3374
3375  // Fields.
3376  for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
3377    GPBFieldType fieldType = fieldDescriptor.fieldType;
3378    GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor);
3379
3380    // Single Fields
3381    if (fieldType == GPBFieldTypeSingle) {
3382      BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor);
3383      if (!selfHas) {
3384        continue;  // Nothing to do.
3385      }
3386
3387      uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor);
3388
3389      switch (fieldDataType) {
3390#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                              \
3391  case GPBDataType##NAME: {                                                 \
3392    TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \
3393    result += GPBCompute##NAME##Size(fieldNumber, fieldVal);                \
3394    break;                                                                  \
3395  }
3396#define CASE_SINGLE_OBJECT(NAME)                                                \
3397  case GPBDataType##NAME: {                                                     \
3398    id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \
3399    result += GPBCompute##NAME##Size(fieldNumber, fieldVal);                    \
3400    break;                                                                      \
3401  }
3402        CASE_SINGLE_POD(Bool, BOOL, Bool)
3403        CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
3404        CASE_SINGLE_POD(SFixed32, int32_t, Int32)
3405        CASE_SINGLE_POD(Float, float, Float)
3406        CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
3407        CASE_SINGLE_POD(SFixed64, int64_t, Int64)
3408        CASE_SINGLE_POD(Double, double, Double)
3409        CASE_SINGLE_POD(Int32, int32_t, Int32)
3410        CASE_SINGLE_POD(Int64, int64_t, Int64)
3411        CASE_SINGLE_POD(SInt32, int32_t, Int32)
3412        CASE_SINGLE_POD(SInt64, int64_t, Int64)
3413        CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
3414        CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
3415        CASE_SINGLE_OBJECT(Bytes)
3416        CASE_SINGLE_OBJECT(String)
3417        CASE_SINGLE_OBJECT(Message)
3418        CASE_SINGLE_OBJECT(Group)
3419        CASE_SINGLE_POD(Enum, int32_t, Int32)
3420#undef CASE_SINGLE_POD
3421#undef CASE_SINGLE_OBJECT
3422      }
3423
3424      // Repeated Fields
3425    } else if (fieldType == GPBFieldTypeRepeated) {
3426      id genericArray = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
3427      NSUInteger count = [genericArray count];
3428      if (count == 0) {
3429        continue;  // Nothing to add.
3430      }
3431      __block size_t dataSize = 0;
3432
3433      switch (fieldDataType) {
3434#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, )
3435#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME)           \
3436  case GPBDataType##NAME: {                                                            \
3437    GPB##ARRAY_TYPE##Array *array = genericArray;                                      \
3438    [array enumerate##ARRAY_ACCESSOR_NAME##                                            \
3439        ValuesWithBlock:^(TYPE value, __unused NSUInteger idx, __unused BOOL * stop) { \
3440          dataSize += GPBCompute##NAME##SizeNoTag(value);                              \
3441        }];                                                                            \
3442    break;                                                                             \
3443  }
3444#define CASE_REPEATED_OBJECT(NAME)                    \
3445  case GPBDataType##NAME: {                           \
3446    for (id value in genericArray) {                  \
3447      dataSize += GPBCompute##NAME##SizeNoTag(value); \
3448    }                                                 \
3449    break;                                            \
3450  }
3451        CASE_REPEATED_POD(Bool, BOOL, Bool)
3452        CASE_REPEATED_POD(Fixed32, uint32_t, UInt32)
3453        CASE_REPEATED_POD(SFixed32, int32_t, Int32)
3454        CASE_REPEATED_POD(Float, float, Float)
3455        CASE_REPEATED_POD(Fixed64, uint64_t, UInt64)
3456        CASE_REPEATED_POD(SFixed64, int64_t, Int64)
3457        CASE_REPEATED_POD(Double, double, Double)
3458        CASE_REPEATED_POD(Int32, int32_t, Int32)
3459        CASE_REPEATED_POD(Int64, int64_t, Int64)
3460        CASE_REPEATED_POD(SInt32, int32_t, Int32)
3461        CASE_REPEATED_POD(SInt64, int64_t, Int64)
3462        CASE_REPEATED_POD(UInt32, uint32_t, UInt32)
3463        CASE_REPEATED_POD(UInt64, uint64_t, UInt64)
3464        CASE_REPEATED_OBJECT(Bytes)
3465        CASE_REPEATED_OBJECT(String)
3466        CASE_REPEATED_OBJECT(Message)
3467        CASE_REPEATED_OBJECT(Group)
3468        CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw)
3469#undef CASE_REPEATED_POD
3470#undef CASE_REPEATED_POD_EXTRA
3471#undef CASE_REPEATED_OBJECT
3472      }  // switch
3473      result += dataSize;
3474      size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor));
3475      if (fieldDataType == GPBDataTypeGroup) {
3476        // Groups have both a start and an end tag.
3477        tagSize *= 2;
3478      }
3479      if (fieldDescriptor.isPackable) {
3480        result += tagSize;
3481        result += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
3482      } else {
3483        result += count * tagSize;
3484      }
3485
3486      // Map<> Fields
3487    } else {  // fieldType == GPBFieldTypeMap
3488      if (GPBDataTypeIsObject(fieldDataType) &&
3489          (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) {
3490        // If key type was string, then the map is an NSDictionary.
3491        NSDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
3492        if (map) {
3493          result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor);
3494        }
3495      } else {
3496        // Type will be GPB*GroupDictionary, exact type doesn't matter.
3497        GPBInt32Int32Dictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
3498        result += [map computeSerializedSizeAsField:fieldDescriptor];
3499      }
3500    }
3501  }  // for(fields)
3502
3503  // Add any unknown fields.
3504  @synchronized(self) {
3505    if (unknownFieldData_) {
3506#if defined(DEBUG) && DEBUG
3507      NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set");
3508#endif
3509      result += [unknownFieldData_ length];
3510    } else {
3511      if (descriptor.wireFormat) {
3512        result += [unknownFields_ serializedSizeAsMessageSet];
3513      } else {
3514        result += [unknownFields_ serializedSize];
3515      }
3516    }
3517  }  // @synchronized(self)
3518
3519  // Add any extensions.
3520  for (GPBExtensionDescriptor *extension in extensionMap_) {
3521    id value = [extensionMap_ objectForKey:extension];
3522    result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value);
3523  }
3524
3525  return result;
3526}
3527
3528#pragma mark - Resolve Methods Support
3529
3530typedef struct ResolveIvarAccessorMethodResult {
3531  IMP impToAdd;
3532  SEL encodingSelector;
3533} ResolveIvarAccessorMethodResult;
3534
3535// |field| can be __unsafe_unretained because they are created at startup
3536// and are essentially global. No need to pay for retain/release when
3537// they are captured in blocks.
3538static void ResolveIvarGet(__unsafe_unretained GPBFieldDescriptor *field,
3539                           ResolveIvarAccessorMethodResult *result) {
3540  GPBDataType fieldDataType = GPBGetFieldDataType(field);
3541  switch (fieldDataType) {
3542#define CASE_GET(NAME, TYPE, TRUE_NAME)                        \
3543  case GPBDataType##NAME: {                                    \
3544    result->impToAdd = imp_implementationWithBlock(^(id obj) { \
3545      return GPBGetMessage##TRUE_NAME##Field(obj, field);      \
3546    });                                                        \
3547    result->encodingSelector = @selector(get##NAME);           \
3548    break;                                                     \
3549  }
3550#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME)                 \
3551  case GPBDataType##NAME: {                                    \
3552    result->impToAdd = imp_implementationWithBlock(^(id obj) { \
3553      return GPBGetObjectIvarWithField(obj, field);            \
3554    });                                                        \
3555    result->encodingSelector = @selector(get##NAME);           \
3556    break;                                                     \
3557  }
3558    CASE_GET(Bool, BOOL, Bool)
3559    CASE_GET(Fixed32, uint32_t, UInt32)
3560    CASE_GET(SFixed32, int32_t, Int32)
3561    CASE_GET(Float, float, Float)
3562    CASE_GET(Fixed64, uint64_t, UInt64)
3563    CASE_GET(SFixed64, int64_t, Int64)
3564    CASE_GET(Double, double, Double)
3565    CASE_GET(Int32, int32_t, Int32)
3566    CASE_GET(Int64, int64_t, Int64)
3567    CASE_GET(SInt32, int32_t, Int32)
3568    CASE_GET(SInt64, int64_t, Int64)
3569    CASE_GET(UInt32, uint32_t, UInt32)
3570    CASE_GET(UInt64, uint64_t, UInt64)
3571    CASE_GET_OBJECT(Bytes, id, Object)
3572    CASE_GET_OBJECT(String, id, Object)
3573    CASE_GET_OBJECT(Message, id, Object)
3574    CASE_GET_OBJECT(Group, id, Object)
3575    CASE_GET(Enum, int32_t, Enum)
3576#undef CASE_GET
3577  }
3578}
3579
3580// See comment about __unsafe_unretained on ResolveIvarGet.
3581static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field,
3582                           ResolveIvarAccessorMethodResult *result) {
3583  GPBDataType fieldDataType = GPBGetFieldDataType(field);
3584  switch (fieldDataType) {
3585#define CASE_SET(NAME, TYPE, TRUE_NAME)                                    \
3586  case GPBDataType##NAME: {                                                \
3587    result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \
3588      return GPBSet##TRUE_NAME##IvarWithFieldPrivate(obj, field, value);   \
3589    });                                                                    \
3590    result->encodingSelector = @selector(set##NAME:);                      \
3591    break;                                                                 \
3592  }
3593#define CASE_SET_COPY(NAME)                                                      \
3594  case GPBDataType##NAME: {                                                      \
3595    result->impToAdd = imp_implementationWithBlock(^(id obj, id value) {         \
3596      return GPBSetRetainedObjectIvarWithFieldPrivate(obj, field, [value copy]); \
3597    });                                                                          \
3598    result->encodingSelector = @selector(set##NAME:);                            \
3599    break;                                                                       \
3600  }
3601    CASE_SET(Bool, BOOL, Bool)
3602    CASE_SET(Fixed32, uint32_t, UInt32)
3603    CASE_SET(SFixed32, int32_t, Int32)
3604    CASE_SET(Float, float, Float)
3605    CASE_SET(Fixed64, uint64_t, UInt64)
3606    CASE_SET(SFixed64, int64_t, Int64)
3607    CASE_SET(Double, double, Double)
3608    CASE_SET(Int32, int32_t, Int32)
3609    CASE_SET(Int64, int64_t, Int64)
3610    CASE_SET(SInt32, int32_t, Int32)
3611    CASE_SET(SInt64, int64_t, Int64)
3612    CASE_SET(UInt32, uint32_t, UInt32)
3613    CASE_SET(UInt64, uint64_t, UInt64)
3614    CASE_SET_COPY(Bytes)
3615    CASE_SET_COPY(String)
3616    CASE_SET(Message, id, Object)
3617    CASE_SET(Group, id, Object)
3618    CASE_SET(Enum, int32_t, Enum)
3619#undef CASE_SET
3620  }
3621}
3622
3623// Highly optimized routines for determining selector types.
3624// Meant to only be used by GPBMessage when resolving selectors in
3625// `+ (BOOL)resolveInstanceMethod:(SEL)sel`.
3626// These routines are intended to make negative decisions as fast as possible.
3627GPB_INLINE char GPBFastToUpper(char c) { return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c; }
3628
3629GPB_INLINE BOOL GPBIsGetSelForField(const char *selName, GPBFieldDescriptor *descriptor) {
3630  // Does 'selName' == '<name>'?
3631  // selName and <name> have to be at least two characters long (i.e. ('a', '\0')" is the shortest
3632  // selector you can have).
3633  return (selName[0] == descriptor->description_->name[0]) &&
3634         (selName[1] == descriptor->description_->name[1]) &&
3635         (strcmp(selName + 1, descriptor->description_->name + 1) == 0);
3636}
3637
3638GPB_INLINE BOOL GPBIsSetSelForField(const char *selName, size_t selNameLength,
3639                                    GPBFieldDescriptor *descriptor) {
3640  // Does 'selName' == 'set<Name>:'?
3641  // Do fastest compares up front
3642  const size_t kSetLength = strlen("set");
3643  // kSetLength is 3 and one for the colon.
3644  if (selNameLength <= kSetLength + 1) {
3645    return NO;
3646  }
3647  if (selName[kSetLength] != GPBFastToUpper(descriptor->description_->name[0])) {
3648    return NO;
3649  }
3650
3651  // NB we check for "set" and the colon later in this routine because we have already checked for
3652  // starting with "s" and ending with ":" in `+resolveInstanceMethod:` before we get here.
3653  if (selName[0] != 's' || selName[1] != 'e' || selName[2] != 't') {
3654    return NO;
3655  }
3656
3657  if (selName[selNameLength - 1] != ':') {
3658    return NO;
3659  }
3660
3661  // Slow path.
3662  size_t nameLength = strlen(descriptor->description_->name);
3663  size_t setSelLength = nameLength + kSetLength + 1;
3664  if (selNameLength != setSelLength) {
3665    return NO;
3666  }
3667  if (strncmp(&selName[kSetLength + 1], descriptor->description_->name + 1, nameLength - 1) != 0) {
3668    return NO;
3669  }
3670
3671  return YES;
3672}
3673
3674GPB_INLINE BOOL GPBFieldHasHas(GPBFieldDescriptor *descriptor) {
3675  // It gets has/setHas selectors if...
3676  //  - not in a oneof (negative has index)
3677  //  - not clearing on zero
3678  return (descriptor->description_->hasIndex >= 0) &&
3679         ((descriptor->description_->flags & GPBFieldClearHasIvarOnZero) == 0);
3680}
3681
3682GPB_INLINE BOOL GPBIsHasSelForField(const char *selName, size_t selNameLength,
3683                                    GPBFieldDescriptor *descriptor) {
3684  // Does 'selName' == 'has<Name>'?
3685  // Do fastest compares up front.
3686  const size_t kHasLength = strlen("has");
3687  if (selNameLength <= kHasLength) {
3688    return NO;
3689  }
3690  if (selName[0] != 'h' || selName[1] != 'a' || selName[2] != 's') {
3691    return NO;
3692  }
3693  if (selName[kHasLength] != GPBFastToUpper(descriptor->description_->name[0])) {
3694    return NO;
3695  }
3696  if (!GPBFieldHasHas(descriptor)) {
3697    return NO;
3698  }
3699
3700  // Slow path.
3701  size_t nameLength = strlen(descriptor->description_->name);
3702  size_t setSelLength = nameLength + kHasLength;
3703  if (selNameLength != setSelLength) {
3704    return NO;
3705  }
3706
3707  if (strncmp(&selName[kHasLength + 1], descriptor->description_->name + 1, nameLength - 1) != 0) {
3708    return NO;
3709  }
3710  return YES;
3711}
3712
3713GPB_INLINE BOOL GPBIsCountSelForField(const char *selName, size_t selNameLength,
3714                                      GPBFieldDescriptor *descriptor) {
3715  // Does 'selName' == '<name>_Count'?
3716  // Do fastest compares up front.
3717  if (selName[0] != descriptor->description_->name[0]) {
3718    return NO;
3719  }
3720  const size_t kCountLength = strlen("_Count");
3721  if (selNameLength <= kCountLength) {
3722    return NO;
3723  }
3724
3725  if (selName[selNameLength - kCountLength] != '_') {
3726    return NO;
3727  }
3728
3729  // Slow path.
3730  size_t nameLength = strlen(descriptor->description_->name);
3731  size_t setSelLength = nameLength + kCountLength;
3732  if (selNameLength != setSelLength) {
3733    return NO;
3734  }
3735  if (strncmp(selName, descriptor->description_->name, nameLength) != 0) {
3736    return NO;
3737  }
3738  if (strncmp(&selName[nameLength], "_Count", kCountLength) != 0) {
3739    return NO;
3740  }
3741  return YES;
3742}
3743
3744GPB_INLINE BOOL GPBIsSetHasSelForField(const char *selName, size_t selNameLength,
3745                                       GPBFieldDescriptor *descriptor) {
3746  // Does 'selName' == 'setHas<Name>:'?
3747  // Do fastest compares up front.
3748  const size_t kSetHasLength = strlen("setHas");
3749  // kSetHasLength is 6 and one for the colon.
3750  if (selNameLength <= kSetHasLength + 1) {
3751    return NO;
3752  }
3753  if (selName[selNameLength - 1] != ':') {
3754    return NO;
3755  }
3756  if (selName[kSetHasLength] != GPBFastToUpper(descriptor->description_->name[0])) {
3757    return NO;
3758  }
3759  if (selName[0] != 's' || selName[1] != 'e' || selName[2] != 't' || selName[3] != 'H' ||
3760      selName[4] != 'a' || selName[5] != 's') {
3761    return NO;
3762  }
3763
3764  if (!GPBFieldHasHas(descriptor)) {
3765    return NO;
3766  }
3767  // Slow path.
3768  size_t nameLength = strlen(descriptor->description_->name);
3769  size_t setHasSelLength = nameLength + kSetHasLength + 1;
3770  if (selNameLength != setHasSelLength) {
3771    return NO;
3772  }
3773  if (strncmp(&selName[kSetHasLength + 1], descriptor->description_->name + 1, nameLength - 1) !=
3774      0) {
3775    return NO;
3776  }
3777
3778  return YES;
3779}
3780
3781GPB_INLINE BOOL GPBIsCaseOfSelForOneOf(const char *selName, size_t selNameLength,
3782                                       GPBOneofDescriptor *descriptor) {
3783  // Does 'selName' == '<name>OneOfCase'?
3784  // Do fastest compares up front.
3785  if (selName[0] != descriptor->name_[0]) {
3786    return NO;
3787  }
3788  const size_t kOneOfCaseLength = strlen("OneOfCase");
3789  if (selNameLength <= kOneOfCaseLength) {
3790    return NO;
3791  }
3792  if (selName[selNameLength - kOneOfCaseLength] != 'O') {
3793    return NO;
3794  }
3795
3796  // Slow path.
3797  size_t nameLength = strlen(descriptor->name_);
3798  size_t setSelLength = nameLength + kOneOfCaseLength;
3799  if (selNameLength != setSelLength) {
3800    return NO;
3801  }
3802  if (strncmp(&selName[nameLength], "OneOfCase", kOneOfCaseLength) != 0) {
3803    return NO;
3804  }
3805  if (strncmp(selName, descriptor->name_, nameLength) != 0) {
3806    return NO;
3807  }
3808  return YES;
3809}
3810
3811+ (BOOL)resolveInstanceMethod:(SEL)sel {
3812  const GPBDescriptor *descriptor = [self descriptor];
3813  if (!descriptor) {
3814    return [super resolveInstanceMethod:sel];
3815  }
3816  ResolveIvarAccessorMethodResult result = {NULL, NULL};
3817
3818  const char *selName = sel_getName(sel);
3819  const size_t selNameLength = strlen(selName);
3820  // A setter has a leading 's' and a trailing ':' (e.g. 'setFoo:' or 'setHasFoo:').
3821  BOOL couldBeSetter = selName[0] == 's' && selName[selNameLength - 1] == ':';
3822  if (couldBeSetter) {
3823    // See comment about __unsafe_unretained on ResolveIvarGet.
3824    for (__unsafe_unretained GPBFieldDescriptor *field in descriptor->fields_) {
3825      BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
3826      if (GPBIsSetSelForField(selName, selNameLength, field)) {
3827        if (isMapOrArray) {
3828          // Local for syntax so the block can directly capture it and not the
3829          // full lookup.
3830          result.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
3831            GPBSetObjectIvarWithFieldPrivate(obj, field, value);
3832          });
3833          result.encodingSelector = @selector(setArray:);
3834        } else {
3835          ResolveIvarSet(field, &result);
3836        }
3837        break;
3838      } else if (!isMapOrArray && GPBIsSetHasSelForField(selName, selNameLength, field)) {
3839        result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
3840          if (value) {
3841            [NSException raise:NSInvalidArgumentException
3842                        format:@"%@: %@ can only be set to NO (to clear field).", [obj class],
3843                               NSStringFromSelector(sel)];
3844          }
3845          GPBClearMessageField(obj, field);
3846        });
3847        result.encodingSelector = @selector(setBool:);
3848        break;
3849      }
3850    }
3851  } else {
3852    // See comment about __unsafe_unretained on ResolveIvarGet.
3853    for (__unsafe_unretained GPBFieldDescriptor *field in descriptor->fields_) {
3854      BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
3855      if (GPBIsGetSelForField(selName, field)) {
3856        if (isMapOrArray) {
3857          if (field.fieldType == GPBFieldTypeRepeated) {
3858            result.impToAdd = imp_implementationWithBlock(^(id obj) {
3859              return GetArrayIvarWithField(obj, field);
3860            });
3861          } else {
3862            result.impToAdd = imp_implementationWithBlock(^(id obj) {
3863              return GetMapIvarWithField(obj, field);
3864            });
3865          }
3866          result.encodingSelector = @selector(getArray);
3867        } else {
3868          ResolveIvarGet(field, &result);
3869        }
3870        break;
3871      }
3872      if (!isMapOrArray) {
3873        if (GPBIsHasSelForField(selName, selNameLength, field)) {
3874          int32_t index = GPBFieldHasIndex(field);
3875          uint32_t fieldNum = GPBFieldNumber(field);
3876          result.impToAdd = imp_implementationWithBlock(^(id obj) {
3877            return GPBGetHasIvar(obj, index, fieldNum);
3878          });
3879          result.encodingSelector = @selector(getBool);
3880          break;
3881        } else {
3882          GPBOneofDescriptor *oneof = field->containingOneof_;
3883          if (oneof && GPBIsCaseOfSelForOneOf(selName, selNameLength, oneof)) {
3884            int32_t index = GPBFieldHasIndex(field);
3885            result.impToAdd = imp_implementationWithBlock(^(id obj) {
3886              return GPBGetHasOneof(obj, index);
3887            });
3888            result.encodingSelector = @selector(getEnum);
3889            break;
3890          }
3891        }
3892      } else {
3893        if (GPBIsCountSelForField(selName, selNameLength, field)) {
3894          result.impToAdd = imp_implementationWithBlock(^(id obj) {
3895            // Type doesn't matter, all *Array and *Dictionary types support
3896            // -count.
3897            NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(obj, field);
3898            return [arrayOrMap count];
3899          });
3900          result.encodingSelector = @selector(getArrayCount);
3901          break;
3902        }
3903      }
3904    }
3905  }
3906
3907  if (result.impToAdd) {
3908    const char *encoding = GPBMessageEncodingForSelector(result.encodingSelector, YES);
3909    Class msgClass = descriptor.messageClass;
3910    BOOL methodAdded = class_addMethod(msgClass, sel, result.impToAdd, encoding);
3911    // class_addMethod() is documented as also failing if the method was already
3912    // added; so we check if the method is already there and return success so
3913    // the method dispatch will still happen.  Why would it already be added?
3914    // Two threads could cause the same method to be bound at the same time,
3915    // but only one will actually bind it; the other still needs to return true
3916    // so things will dispatch.
3917    if (!methodAdded) {
3918      methodAdded = GPBClassHasSel(msgClass, sel);
3919    }
3920    return methodAdded;
3921  }
3922  return [super resolveInstanceMethod:sel];
3923}
3924
3925+ (BOOL)resolveClassMethod:(SEL)sel {
3926  // Extensions scoped to a Message and looked up via class methods.
3927  if (GPBResolveExtensionClassMethod(self, sel)) {
3928    return YES;
3929  }
3930  return [super resolveClassMethod:sel];
3931}
3932
3933#pragma mark - NSCoding Support
3934
3935+ (BOOL)supportsSecureCoding {
3936  return YES;
3937}
3938
3939- (instancetype)initWithCoder:(NSCoder *)aDecoder {
3940  self = [self init];
3941  if (self) {
3942    NSData *data = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey];
3943    if (data.length) {
3944      GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
3945      @try {
3946        [self mergeFromCodedInputStream:input extensionRegistry:nil endingTag:0];
3947      } @finally {
3948        [input release];
3949      }
3950    }
3951  }
3952  return self;
3953}
3954
3955- (void)encodeWithCoder:(NSCoder *)aCoder {
3956#if defined(DEBUG) && DEBUG
3957  if (extensionMap_.count) {
3958    // Hint to go along with the docs on GPBMessage about this.
3959    //
3960    // Note: This is incomplete, in that it only checked the "root" message,
3961    // if a sub message in a field has extensions, the issue still exists. A
3962    // recursive check could be done here (like the work in
3963    // GPBMessageDropUnknownFieldsRecursively()), but that has the potential to
3964    // be expensive and could slow down serialization in DEBUG enough to cause
3965    // developers other problems.
3966    NSLog(@"Warning: writing out a GPBMessage (%@) via NSCoding and it"
3967          @" has %ld extensions; when read back in, those fields will be"
3968          @" in the unknownFields property instead.",
3969          [self class], (long)extensionMap_.count);
3970  }
3971#endif
3972  NSData *data = [self data];
3973  if (data.length) {
3974    [aCoder encodeObject:data forKey:kGPBDataCoderKey];
3975  }
3976}
3977
3978#pragma mark - KVC Support
3979
3980+ (BOOL)accessInstanceVariablesDirectly {
3981  // Make sure KVC doesn't use instance variables.
3982  return NO;
3983}
3984
3985@end
3986
3987#pragma mark - Messages from GPBUtilities.h but defined here for access to helpers.
3988
3989// Only exists for public api, no core code should use this.
3990id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) {
3991#if defined(DEBUG) && DEBUG
3992  if (field.fieldType != GPBFieldTypeRepeated) {
3993    [NSException raise:NSInvalidArgumentException
3994                format:@"%@.%@ is not a repeated field.", [self class], field.name];
3995  }
3996#endif
3997  return GetOrCreateArrayIvarWithField(self, field);
3998}
3999
4000// Only exists for public api, no core code should use this.
4001id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) {
4002#if defined(DEBUG) && DEBUG
4003  if (field.fieldType != GPBFieldTypeMap) {
4004    [NSException raise:NSInvalidArgumentException
4005                format:@"%@.%@ is not a map<> field.", [self class], field.name];
4006  }
4007#endif
4008  return GetOrCreateMapIvarWithField(self, field);
4009}
4010
4011id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
4012  NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here");
4013  if (!GPBFieldDataTypeIsMessage(field)) {
4014    if (GPBGetHasIvarField(self, field)) {
4015      uint8_t *storage = (uint8_t *)self->messageStorage_;
4016      id *typePtr = (id *)&storage[field->description_->offset];
4017      return *typePtr;
4018    }
4019    // Not set...non messages (string/data), get their default.
4020    return field.defaultValue.valueMessage;
4021  }
4022
4023  uint8_t *storage = (uint8_t *)self->messageStorage_;
4024  _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset];
4025  id msg = atomic_load(typePtr);
4026  if (msg) {
4027    return msg;
4028  }
4029
4030  id expected = nil;
4031  id autocreated = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
4032  if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) {
4033    // Value was set, return it.
4034    return autocreated;
4035  }
4036
4037  // Some other thread set it, release the one created and return what got set.
4038  GPBClearMessageAutocreator(autocreated);
4039  [autocreated release];
4040  return expected;
4041}
4042
4043NSData *GPBMessageUnknownFieldsData(GPBMessage *self) {
4044  NSData *result = nil;
4045  @synchronized(self) {
4046#pragma clang diagnostic push
4047#pragma clang diagnostic ignored "-Wdeprecated-declarations"
4048    GPBUnknownFieldSet *unknownFields = self->unknownFields_;
4049#pragma clang diagnostic pop
4050    if (unknownFields) {
4051#if defined(DEBUG) && DEBUG
4052      NSCAssert(self->unknownFieldData_ == nil, @"Internal error both unknown states were set");
4053#endif
4054      if (self.descriptor.isWireFormat) {
4055        NSMutableData *mutableData =
4056            [NSMutableData dataWithLength:unknownFields.serializedSizeAsMessageSet];
4057        GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:mutableData];
4058        [unknownFields writeAsMessageSetTo:output];
4059        [output flush];
4060        [output release];
4061        result = mutableData;
4062      } else {
4063        result = [unknownFields data];
4064      }
4065    } else {
4066      // Internally we can borrow it without a copy since this is immediately used by callers
4067      // and multithreaded access with any mutation is not allow on messages.
4068      result = self->unknownFieldData_;
4069    }
4070  }  // @synchronized(self)
4071  return result;
4072}
4073
4074#pragma clang diagnostic pop
4075