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