• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3//
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
7
8#import "GPBUnknownField.h"
9#import "GPBUnknownField_PackagePrivate.h"
10
11#import "GPBArray.h"
12#import "GPBCodedOutputStream.h"
13#import "GPBCodedOutputStream_PackagePrivate.h"
14#import "GPBUnknownFieldSet.h"
15#import "GPBUnknownFields.h"
16#import "GPBUnknownFields_PackagePrivate.h"
17#import "GPBWireFormat.h"
18
19#define ASSERT_FIELD_TYPE(type)                               \
20  if (type_ != type) {                                        \
21    [NSException raise:NSInternalInconsistencyException       \
22                format:@"GPBUnknownField is the wrong type"]; \
23  }
24
25@implementation GPBUnknownField
26
27@synthesize number = number_;
28@synthesize type = type_;
29
30- (instancetype)initWithNumber:(int32_t)number {
31  if ((self = [super init])) {
32    number_ = number;
33    type_ = GPBUnknownFieldTypeLegacy;
34  }
35  return self;
36}
37
38- (instancetype)initWithNumber:(int32_t)number varint:(uint64_t)varint {
39  if ((self = [super init])) {
40    number_ = number;
41    type_ = GPBUnknownFieldTypeVarint;
42    storage_.intValue = varint;
43  }
44  return self;
45}
46
47- (instancetype)initWithNumber:(int32_t)number fixed32:(uint32_t)fixed32 {
48  if ((self = [super init])) {
49    number_ = number;
50    type_ = GPBUnknownFieldTypeFixed32;
51    storage_.intValue = fixed32;
52  }
53  return self;
54}
55
56- (instancetype)initWithNumber:(int32_t)number fixed64:(uint64_t)fixed64 {
57  if ((self = [super init])) {
58    number_ = number;
59    type_ = GPBUnknownFieldTypeFixed64;
60    storage_.intValue = fixed64;
61  }
62  return self;
63}
64
65- (instancetype)initWithNumber:(int32_t)number lengthDelimited:(nonnull NSData *)data {
66  if ((self = [super init])) {
67    number_ = number;
68    type_ = GPBUnknownFieldTypeLengthDelimited;
69    storage_.lengthDelimited = [data copy];
70  }
71  return self;
72}
73
74- (instancetype)initWithNumber:(int32_t)number group:(nonnull GPBUnknownFields *)group {
75  if ((self = [super init])) {
76    number_ = number;
77    type_ = GPBUnknownFieldTypeGroup;
78    // Taking ownership of the group; so retain, not copy.
79    storage_.group = [group retain];
80  }
81  return self;
82}
83
84- (void)dealloc {
85  switch (type_) {
86    case GPBUnknownFieldTypeVarint:
87    case GPBUnknownFieldTypeFixed32:
88    case GPBUnknownFieldTypeFixed64:
89      break;
90    case GPBUnknownFieldTypeLengthDelimited:
91      [storage_.lengthDelimited release];
92      break;
93    case GPBUnknownFieldTypeGroup:
94      [storage_.group release];
95      break;
96    case GPBUnknownFieldTypeLegacy:
97      [storage_.legacy.mutableVarintList release];
98      [storage_.legacy.mutableFixed32List release];
99      [storage_.legacy.mutableFixed64List release];
100      [storage_.legacy.mutableLengthDelimitedList release];
101      [storage_.legacy.mutableGroupList release];
102      break;
103  }
104
105  [super dealloc];
106}
107
108// Direct access is use for speed, to avoid even internally declaring things
109// read/write, etc. The warning is enabled in the project to ensure code calling
110// protos can turn on -Wdirect-ivar-access without issues.
111#pragma clang diagnostic push
112#pragma clang diagnostic ignored "-Wdirect-ivar-access"
113
114- (uint64_t)varint {
115  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeVarint);
116  return storage_.intValue;
117}
118
119- (uint32_t)fixed32 {
120  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeFixed32);
121  return (uint32_t)storage_.intValue;
122}
123
124- (uint64_t)fixed64 {
125  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeFixed64);
126  return storage_.intValue;
127}
128
129- (NSData *)lengthDelimited {
130  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLengthDelimited);
131  return storage_.lengthDelimited;
132}
133
134- (GPBUnknownFields *)group {
135  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeGroup);
136  return storage_.group;
137}
138
139- (GPBUInt64Array *)varintList {
140  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
141  return storage_.legacy.mutableVarintList;
142}
143
144- (GPBUInt32Array *)fixed32List {
145  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
146  return storage_.legacy.mutableFixed32List;
147}
148
149- (GPBUInt64Array *)fixed64List {
150  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
151  return storage_.legacy.mutableFixed64List;
152}
153
154- (NSArray<NSData *> *)lengthDelimitedList {
155  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
156  return storage_.legacy.mutableLengthDelimitedList;
157}
158
159- (NSArray<GPBUnknownFieldSet *> *)groupList {
160  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
161  return storage_.legacy.mutableGroupList;
162}
163
164- (id)copyWithZone:(NSZone *)zone {
165  switch (type_) {
166    case GPBUnknownFieldTypeVarint:
167    case GPBUnknownFieldTypeFixed32:
168    case GPBUnknownFieldTypeFixed64:
169    case GPBUnknownFieldTypeLengthDelimited:
170      // In these modes, the object isn't mutable, so just return self.
171      return [self retain];
172    case GPBUnknownFieldTypeGroup: {
173      // The `GPBUnknownFields` for the group is mutable, so a new instance of this object and
174      // the group is needed.
175      GPBUnknownFields *copyGroup = [storage_.group copyWithZone:zone];
176      GPBUnknownField *copy = [[GPBUnknownField allocWithZone:zone] initWithNumber:number_
177                                                                             group:copyGroup];
178      [copyGroup release];
179      return copy;
180    }
181    case GPBUnknownFieldTypeLegacy: {
182#pragma clang diagnostic push
183#pragma clang diagnostic ignored "-Wdeprecated-declarations"
184      GPBUnknownField *result = [[GPBUnknownField allocWithZone:zone] initWithNumber:number_];
185      result->storage_.legacy.mutableFixed32List =
186          [storage_.legacy.mutableFixed32List copyWithZone:zone];
187      result->storage_.legacy.mutableFixed64List =
188          [storage_.legacy.mutableFixed64List copyWithZone:zone];
189      result->storage_.legacy.mutableLengthDelimitedList =
190          [storage_.legacy.mutableLengthDelimitedList mutableCopyWithZone:zone];
191      result->storage_.legacy.mutableVarintList =
192          [storage_.legacy.mutableVarintList copyWithZone:zone];
193      if (storage_.legacy.mutableGroupList.count) {
194        result->storage_.legacy.mutableGroupList = [[NSMutableArray allocWithZone:zone]
195            initWithCapacity:storage_.legacy.mutableGroupList.count];
196        for (GPBUnknownFieldSet *group in storage_.legacy.mutableGroupList) {
197          GPBUnknownFieldSet *copied = [group copyWithZone:zone];
198          [result->storage_.legacy.mutableGroupList addObject:copied];
199          [copied release];
200        }
201      }
202#pragma clang diagnostic pop
203      return result;
204    }
205  }
206}
207
208- (BOOL)isEqual:(id)object {
209  if (self == object) return YES;
210  if (![object isKindOfClass:[GPBUnknownField class]]) return NO;
211  GPBUnknownField *field = (GPBUnknownField *)object;
212  if (number_ != field->number_) return NO;
213  if (type_ != field->type_) return NO;
214  switch (type_) {
215    case GPBUnknownFieldTypeVarint:
216    case GPBUnknownFieldTypeFixed32:
217    case GPBUnknownFieldTypeFixed64:
218      return storage_.intValue == field->storage_.intValue;
219    case GPBUnknownFieldTypeLengthDelimited:
220      return [storage_.lengthDelimited isEqual:field->storage_.lengthDelimited];
221    case GPBUnknownFieldTypeGroup:
222      return [storage_.group isEqual:field->storage_.group];
223    case GPBUnknownFieldTypeLegacy: {
224      BOOL equalVarint =
225          (storage_.legacy.mutableVarintList.count == 0 &&
226           field->storage_.legacy.mutableVarintList.count == 0) ||
227          [storage_.legacy.mutableVarintList isEqual:field->storage_.legacy.mutableVarintList];
228      if (!equalVarint) return NO;
229      BOOL equalFixed32 =
230          (storage_.legacy.mutableFixed32List.count == 0 &&
231           field->storage_.legacy.mutableFixed32List.count == 0) ||
232          [storage_.legacy.mutableFixed32List isEqual:field->storage_.legacy.mutableFixed32List];
233      if (!equalFixed32) return NO;
234      BOOL equalFixed64 =
235          (storage_.legacy.mutableFixed64List.count == 0 &&
236           field->storage_.legacy.mutableFixed64List.count == 0) ||
237          [storage_.legacy.mutableFixed64List isEqual:field->storage_.legacy.mutableFixed64List];
238      if (!equalFixed64) return NO;
239      BOOL equalLDList = (storage_.legacy.mutableLengthDelimitedList.count == 0 &&
240                          field->storage_.legacy.mutableLengthDelimitedList.count == 0) ||
241                         [storage_.legacy.mutableLengthDelimitedList
242                             isEqual:field->storage_.legacy.mutableLengthDelimitedList];
243      if (!equalLDList) return NO;
244      BOOL equalGroupList =
245          (storage_.legacy.mutableGroupList.count == 0 &&
246           field->storage_.legacy.mutableGroupList.count == 0) ||
247          [storage_.legacy.mutableGroupList isEqual:field->storage_.legacy.mutableGroupList];
248      if (!equalGroupList) return NO;
249      return YES;
250    }
251  }
252}
253
254- (NSUInteger)hash {
255  const int prime = 31;
256  NSUInteger result = prime * number_ + type_;
257  switch (type_) {
258    case GPBUnknownFieldTypeVarint:
259    case GPBUnknownFieldTypeFixed32:
260    case GPBUnknownFieldTypeFixed64:
261      result = prime * result + (NSUInteger)storage_.intValue;
262      break;
263    case GPBUnknownFieldTypeLengthDelimited:
264      result = prime * result + [storage_.lengthDelimited hash];
265      break;
266    case GPBUnknownFieldTypeGroup:
267      result = prime * result + [storage_.group hash];
268    case GPBUnknownFieldTypeLegacy:
269      result = prime * result + [storage_.legacy.mutableVarintList hash];
270      result = prime * result + [storage_.legacy.mutableFixed32List hash];
271      result = prime * result + [storage_.legacy.mutableFixed64List hash];
272      result = prime * result + [storage_.legacy.mutableLengthDelimitedList hash];
273      result = prime * result + [storage_.legacy.mutableGroupList hash];
274      break;
275  }
276  return result;
277}
278
279- (void)writeToOutput:(GPBCodedOutputStream *)output {
280#pragma clang diagnostic push
281#pragma clang diagnostic ignored "-Wdeprecated-declarations"
282  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
283  NSUInteger count = storage_.legacy.mutableVarintList.count;
284  if (count > 0) {
285    [output writeUInt64Array:number_ values:storage_.legacy.mutableVarintList tag:0];
286  }
287  count = storage_.legacy.mutableFixed32List.count;
288  if (count > 0) {
289    [output writeFixed32Array:number_ values:storage_.legacy.mutableFixed32List tag:0];
290  }
291  count = storage_.legacy.mutableFixed64List.count;
292  if (count > 0) {
293    [output writeFixed64Array:number_ values:storage_.legacy.mutableFixed64List tag:0];
294  }
295  count = storage_.legacy.mutableLengthDelimitedList.count;
296  if (count > 0) {
297    [output writeBytesArray:number_ values:storage_.legacy.mutableLengthDelimitedList];
298  }
299  count = storage_.legacy.mutableGroupList.count;
300  if (count > 0) {
301    [output writeUnknownGroupArray:number_ values:storage_.legacy.mutableGroupList];
302  }
303#pragma clang diagnostic pop
304}
305
306- (size_t)serializedSize {
307  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
308#pragma clang diagnostic push
309#pragma clang diagnostic ignored "-Wdeprecated-declarations"
310  __block size_t result = 0;
311  int32_t number = number_;
312  [storage_.legacy.mutableVarintList
313      enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
314        result += GPBComputeUInt64Size(number, value);
315      }];
316
317  [storage_.legacy.mutableFixed32List
318      enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
319        result += GPBComputeFixed32Size(number, value);
320      }];
321
322  [storage_.legacy.mutableFixed64List
323      enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
324        result += GPBComputeFixed64Size(number, value);
325      }];
326
327  for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
328    result += GPBComputeBytesSize(number, data);
329  }
330
331  for (GPBUnknownFieldSet *set in storage_.legacy.mutableGroupList) {
332    result += GPBComputeUnknownGroupSize(number, set);
333  }
334#pragma clang diagnostic pop
335
336  return result;
337}
338
339- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output {
340  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
341  for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
342    [output writeRawMessageSetExtension:number_ value:data];
343  }
344}
345
346- (size_t)serializedSizeAsMessageSetExtension {
347  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
348  size_t result = 0;
349  for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
350    result += GPBComputeRawMessageSetExtensionSize(number_, data);
351  }
352  return result;
353}
354
355- (NSString *)description {
356  NSMutableString *description =
357      [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d", [self class], self, number_];
358  switch (type_) {
359    case GPBUnknownFieldTypeVarint:
360      [description appendFormat:@" varint: %llu", storage_.intValue];
361      break;
362    case GPBUnknownFieldTypeFixed32:
363      [description appendFormat:@" fixed32: %u", (uint32_t)storage_.intValue];
364      break;
365    case GPBUnknownFieldTypeFixed64:
366      [description appendFormat:@" fixed64: %llu", storage_.intValue];
367      break;
368    case GPBUnknownFieldTypeLengthDelimited:
369      [description appendFormat:@" fixed64: %@", storage_.lengthDelimited];
370      break;
371    case GPBUnknownFieldTypeGroup:
372      [description appendFormat:@" group: %@", storage_.group];
373      break;
374    case GPBUnknownFieldTypeLegacy:
375#pragma clang diagnostic push
376#pragma clang diagnostic ignored "-Wdeprecated-declarations"
377      [description appendString:@" {\n"];
378      [storage_.legacy.mutableVarintList
379          enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
380            [description appendFormat:@"\t%llu\n", value];
381          }];
382      [storage_.legacy.mutableFixed32List
383          enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
384            [description appendFormat:@"\t%u\n", value];
385          }];
386      [storage_.legacy.mutableFixed64List
387          enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
388            [description appendFormat:@"\t%llu\n", value];
389          }];
390      for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
391        [description appendFormat:@"\t%@\n", data];
392      }
393      for (GPBUnknownFieldSet *set in storage_.legacy.mutableGroupList) {
394        [description appendFormat:@"\t%@\n", set];
395      }
396      [description appendString:@"}"];
397#pragma clang diagnostic pop
398      break;
399  }
400  return description;
401}
402
403- (void)mergeFromField:(GPBUnknownField *)other {
404#pragma clang diagnostic push
405#pragma clang diagnostic ignored "-Wdeprecated-declarations"
406  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
407  GPBUInt64Array *otherVarintList = other.varintList;
408  if (otherVarintList.count > 0) {
409    if (storage_.legacy.mutableVarintList == nil) {
410      storage_.legacy.mutableVarintList = [otherVarintList copy];
411    } else {
412      [storage_.legacy.mutableVarintList addValuesFromArray:otherVarintList];
413    }
414  }
415
416  GPBUInt32Array *otherFixed32List = other.fixed32List;
417  if (otherFixed32List.count > 0) {
418    if (storage_.legacy.mutableFixed32List == nil) {
419      storage_.legacy.mutableFixed32List = [otherFixed32List copy];
420    } else {
421      [storage_.legacy.mutableFixed32List addValuesFromArray:otherFixed32List];
422    }
423  }
424
425  GPBUInt64Array *otherFixed64List = other.fixed64List;
426  if (otherFixed64List.count > 0) {
427    if (storage_.legacy.mutableFixed64List == nil) {
428      storage_.legacy.mutableFixed64List = [otherFixed64List copy];
429    } else {
430      [storage_.legacy.mutableFixed64List addValuesFromArray:otherFixed64List];
431    }
432  }
433
434  NSArray *otherLengthDelimitedList = other.lengthDelimitedList;
435  if (otherLengthDelimitedList.count > 0) {
436    if (storage_.legacy.mutableLengthDelimitedList == nil) {
437      storage_.legacy.mutableLengthDelimitedList = [otherLengthDelimitedList mutableCopy];
438    } else {
439      [storage_.legacy.mutableLengthDelimitedList addObjectsFromArray:otherLengthDelimitedList];
440    }
441  }
442
443  NSArray *otherGroupList = other.groupList;
444  if (otherGroupList.count > 0) {
445    if (storage_.legacy.mutableGroupList == nil) {
446      storage_.legacy.mutableGroupList =
447          [[NSMutableArray alloc] initWithCapacity:otherGroupList.count];
448    }
449    // Make our own mutable copies.
450    for (GPBUnknownFieldSet *group in otherGroupList) {
451      GPBUnknownFieldSet *copied = [group copy];
452      [storage_.legacy.mutableGroupList addObject:copied];
453      [copied release];
454    }
455  }
456#pragma clang diagnostic pop
457}
458
459- (void)addVarint:(uint64_t)value {
460  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
461  if (storage_.legacy.mutableVarintList == nil) {
462    storage_.legacy.mutableVarintList = [[GPBUInt64Array alloc] initWithValues:&value count:1];
463  } else {
464    [storage_.legacy.mutableVarintList addValue:value];
465  }
466}
467
468- (void)addFixed32:(uint32_t)value {
469  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
470  if (storage_.legacy.mutableFixed32List == nil) {
471    storage_.legacy.mutableFixed32List = [[GPBUInt32Array alloc] initWithValues:&value count:1];
472  } else {
473    [storage_.legacy.mutableFixed32List addValue:value];
474  }
475}
476
477- (void)addFixed64:(uint64_t)value {
478  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
479  if (storage_.legacy.mutableFixed64List == nil) {
480    storage_.legacy.mutableFixed64List = [[GPBUInt64Array alloc] initWithValues:&value count:1];
481  } else {
482    [storage_.legacy.mutableFixed64List addValue:value];
483  }
484}
485
486- (void)addLengthDelimited:(NSData *)value {
487  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
488  if (storage_.legacy.mutableLengthDelimitedList == nil) {
489    storage_.legacy.mutableLengthDelimitedList = [[NSMutableArray alloc] initWithObjects:&value
490                                                                                   count:1];
491  } else {
492    [storage_.legacy.mutableLengthDelimitedList addObject:value];
493  }
494}
495
496- (void)addGroup:(GPBUnknownFieldSet *)value {
497  ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
498  if (storage_.legacy.mutableGroupList == nil) {
499    storage_.legacy.mutableGroupList = [[NSMutableArray alloc] initWithObjects:&value count:1];
500  } else {
501    [storage_.legacy.mutableGroupList addObject:value];
502  }
503}
504
505#pragma clang diagnostic pop
506
507@end
508