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