[ObjC] Introduce the new `GPBUnknownFields` type.
`GPBUnknownFields` will be the eventually replacement for `GPBUnknownFieldSet`. This
introduces the type and the changes to `GPBUnknownField`.
The new api will preserve the wire ordering of unknown fields. This is now checked
in conformance tests.
While this adds the type changes and tests them, it does not yet wire the changes
in to the rest of the Runtime, so the conformance tests still done pass.
`GPBUnknownFieldSet` also hasn't been deprecated yet, that will come in later with
the wiring in to the runtime.
PiperOrigin-RevId: 648361455
diff --git a/objectivec/BUILD.bazel b/objectivec/BUILD.bazel
index 4aa4b20..7f154ff 100644
--- a/objectivec/BUILD.bazel
+++ b/objectivec/BUILD.bazel
@@ -84,6 +84,7 @@
"GPBRootObject.h",
"GPBRuntimeTypes.h",
"GPBUnknownField.h",
+ "GPBUnknownFields.h",
"GPBUnknownFieldSet.h",
"GPBUtilities.h",
"GPBWellKnownTypes.h",
@@ -138,6 +139,7 @@
"GPBType.pbobjc.m",
"GPBUnknownField.m",
"GPBUnknownFieldSet.m",
+ "GPBUnknownFields.m",
"GPBUtilities.m",
"GPBWellKnownTypes.m",
"GPBWireFormat.m",
diff --git a/objectivec/GPBProtocolBuffers.h b/objectivec/GPBProtocolBuffers.h
index 9e081b0..fd38fde 100644
--- a/objectivec/GPBProtocolBuffers.h
+++ b/objectivec/GPBProtocolBuffers.h
@@ -19,6 +19,7 @@
#import "GPBRootObject.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFieldSet.h"
+#import "GPBUnknownFields.h"
#import "GPBUtilities.h"
#import "GPBWellKnownTypes.h"
#import "GPBWireFormat.h"
diff --git a/objectivec/GPBProtocolBuffers.m b/objectivec/GPBProtocolBuffers.m
index b43cf7f..07cd400 100644
--- a/objectivec/GPBProtocolBuffers.m
+++ b/objectivec/GPBProtocolBuffers.m
@@ -26,6 +26,7 @@
#import "GPBRootObject.m"
#import "GPBUnknownField.m"
#import "GPBUnknownFieldSet.m"
+#import "GPBUnknownFields.m"
#import "GPBUtilities.m"
#import "GPBWellKnownTypes.m"
#import "GPBWireFormat.m"
diff --git a/objectivec/GPBUnknownField.h b/objectivec/GPBUnknownField.h
index 8835f4d..a145593 100644
--- a/objectivec/GPBUnknownField.h
+++ b/objectivec/GPBUnknownField.h
@@ -11,8 +11,25 @@
@class GPBUInt32Array;
@class GPBUInt64Array;
@class GPBUnknownFieldSet;
+@class GPBUnknownFields;
NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(uint8_t, GPBUnknownFieldType) {
+ GPBUnknownFieldTypeVarint,
+ GPBUnknownFieldTypeFixed32,
+ GPBUnknownFieldTypeFixed64,
+ GPBUnknownFieldTypeLengthDelimited, // Length prefixed
+ GPBUnknownFieldTypeGroup, // Tag delimited
+
+ /**
+ * This type is only used with fields from `GPBUnknownFieldsSet`. Some methods
+ * only work with instances with this type and other apis require the other
+ * type(s). It is a programming error to use the wrong methods.
+ **/
+ GPBUnknownFieldTypeLegacy,
+};
+
/**
* Store an unknown field. These are used in conjunction with
* GPBUnknownFieldSet.
@@ -26,48 +43,127 @@
/** The field number the data is stored under. */
@property(nonatomic, readonly, assign) int32_t number;
-/** An array of varint values for this field. */
+/** The type of the field. */
+@property(nonatomic, readonly, assign) GPBUnknownFieldType type;
+
+/**
+ * Fetch the varint value.
+ *
+ * It is a programming error to call this when the `type` is not a varint.
+ */
+@property(nonatomic, readonly, assign) uint64_t varint;
+
+/**
+ * Fetch the fixed32 value.
+ *
+ * It is a programming error to call this when the `type` is not a fixed32.
+ */
+@property(nonatomic, readonly, assign) uint32_t fixed32;
+
+/**
+ * Fetch the fixed64 value.
+ *
+ * It is a programming error to call this when the `type` is not a fixed64.
+ */
+@property(nonatomic, readonly, assign) uint64_t fixed64;
+
+/**
+ * Fetch the length delimited (length prefixed) value.
+ *
+ * It is a programming error to call this when the `type` is not a length
+ * delimited.
+ */
+@property(nonatomic, readonly, strong, nonnull) NSData *lengthDelimited;
+
+/**
+ * Fetch the group (tag delimited) value.
+ *
+ * It is a programming error to call this when the `type` is not a group.
+ */
+@property(nonatomic, readonly, strong, nonnull) GPBUnknownFields *group;
+
+/**
+ * An array of varint values for this field.
+ *
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ */
@property(nonatomic, readonly, strong) GPBUInt64Array *varintList;
-/** An array of fixed32 values for this field. */
+/**
+ * An array of fixed32 values for this field.
+ *
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ */
@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List;
-/** An array of fixed64 values for this field. */
+/**
+ * An array of fixed64 values for this field.
+ *
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ */
@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List;
-/** An array of data values for this field. */
+/**
+ * An array of data values for this field.
+ *
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ */
@property(nonatomic, readonly, strong) NSArray<NSData *> *lengthDelimitedList;
-/** An array of groups of values for this field. */
+/**
+ * An array of groups of values for this field.
+ *
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ */
@property(nonatomic, readonly, strong) NSArray<GPBUnknownFieldSet *> *groupList;
/**
* Add a value to the varintList.
*
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ *
* @param value The value to add.
**/
- (void)addVarint:(uint64_t)value;
/**
* Add a value to the fixed32List.
*
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ *
* @param value The value to add.
**/
- (void)addFixed32:(uint32_t)value;
/**
* Add a value to the fixed64List.
*
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ *
* @param value The value to add.
**/
- (void)addFixed64:(uint64_t)value;
/**
* Add a value to the lengthDelimitedList.
*
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ *
* @param value The value to add.
**/
- (void)addLengthDelimited:(NSData *)value;
/**
* Add a value to the groupList.
*
+ * Only valid for type == GPBUnknownFieldTypeLegacy, it is a programming error
+ * to use with any other type.
+ *
* @param value The value to add.
**/
- (void)addGroup:(GPBUnknownFieldSet *)value;
diff --git a/objectivec/GPBUnknownField.m b/objectivec/GPBUnknownField.m
index 69f834f..767bc5b 100644
--- a/objectivec/GPBUnknownField.m
+++ b/objectivec/GPBUnknownField.m
@@ -5,42 +5,114 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
+#import "GPBUnknownField.h"
#import "GPBUnknownField_PackagePrivate.h"
#import "GPBArray.h"
#import "GPBCodedOutputStream_PackagePrivate.h"
#import "GPBUnknownFieldSet.h"
+#define ASSERT_FIELD_TYPE(type) \
+ if (type_ != type) { \
+ [NSException raise:NSInternalInconsistencyException \
+ format:@"GPBUnknownField is the wrong type"]; \
+ }
+
@implementation GPBUnknownField {
@protected
int32_t number_;
- GPBUInt64Array *mutableVarintList_;
- GPBUInt32Array *mutableFixed32List_;
- GPBUInt64Array *mutableFixed64List_;
- NSMutableArray<NSData *> *mutableLengthDelimitedList_;
- NSMutableArray<GPBUnknownFieldSet *> *mutableGroupList_;
+ GPBUnknownFieldType type_;
+
+ union {
+ uint64_t intValue; // type == Varint, Fixed32, Fixed64
+ NSData *lengthDelimited; // type == LengthDelimited
+ GPBUnknownFields *group; // type == Group
+ struct { // type == Legacy
+ GPBUInt64Array *mutableVarintList;
+ GPBUInt32Array *mutableFixed32List;
+ GPBUInt64Array *mutableFixed64List;
+ NSMutableArray<NSData *> *mutableLengthDelimitedList;
+ NSMutableArray<GPBUnknownFieldSet *> *mutableGroupList;
+ } legacy;
+ } storage_;
}
@synthesize number = number_;
-@synthesize varintList = mutableVarintList_;
-@synthesize fixed32List = mutableFixed32List_;
-@synthesize fixed64List = mutableFixed64List_;
-@synthesize lengthDelimitedList = mutableLengthDelimitedList_;
-@synthesize groupList = mutableGroupList_;
+@synthesize type = type_;
- (instancetype)initWithNumber:(int32_t)number {
if ((self = [super init])) {
number_ = number;
+ type_ = GPBUnknownFieldTypeLegacy;
+ }
+ return self;
+}
+
+- (instancetype)initWithNumber:(int32_t)number varint:(uint64_t)varint {
+ if ((self = [super init])) {
+ number_ = number;
+ type_ = GPBUnknownFieldTypeVarint;
+ storage_.intValue = varint;
+ }
+ return self;
+}
+
+- (instancetype)initWithNumber:(int32_t)number fixed32:(uint32_t)fixed32 {
+ if ((self = [super init])) {
+ number_ = number;
+ type_ = GPBUnknownFieldTypeFixed32;
+ storage_.intValue = fixed32;
+ }
+ return self;
+}
+
+- (instancetype)initWithNumber:(int32_t)number fixed64:(uint64_t)fixed64 {
+ if ((self = [super init])) {
+ number_ = number;
+ type_ = GPBUnknownFieldTypeFixed64;
+ storage_.intValue = fixed64;
+ }
+ return self;
+}
+
+- (instancetype)initWithNumber:(int32_t)number lengthDelimited:(nonnull NSData *)data {
+ if ((self = [super init])) {
+ number_ = number;
+ type_ = GPBUnknownFieldTypeLengthDelimited;
+ storage_.lengthDelimited = [data copy];
+ }
+ return self;
+}
+
+- (instancetype)initWithNumber:(int32_t)number group:(nonnull GPBUnknownFields *)group {
+ if ((self = [super init])) {
+ number_ = number;
+ type_ = GPBUnknownFieldTypeGroup;
+ storage_.group = [group retain];
}
return self;
}
- (void)dealloc {
- [mutableVarintList_ release];
- [mutableFixed32List_ release];
- [mutableFixed64List_ release];
- [mutableLengthDelimitedList_ release];
- [mutableGroupList_ release];
+ switch (type_) {
+ case GPBUnknownFieldTypeVarint:
+ case GPBUnknownFieldTypeFixed32:
+ case GPBUnknownFieldTypeFixed64:
+ break;
+ case GPBUnknownFieldTypeLengthDelimited:
+ [storage_.lengthDelimited release];
+ break;
+ case GPBUnknownFieldTypeGroup:
+ [storage_.group release];
+ break;
+ case GPBUnknownFieldTypeLegacy:
+ [storage_.legacy.mutableVarintList release];
+ [storage_.legacy.mutableFixed32List release];
+ [storage_.legacy.mutableFixed64List release];
+ [storage_.legacy.mutableLengthDelimitedList release];
+ [storage_.legacy.mutableGroupList release];
+ break;
+ }
[super dealloc];
}
@@ -51,22 +123,96 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
+- (uint64_t)varint {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeVarint);
+ return storage_.intValue;
+}
+
+- (uint32_t)fixed32 {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeFixed32);
+ return (uint32_t)storage_.intValue;
+}
+
+- (uint64_t)fixed64 {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeFixed64);
+ return storage_.intValue;
+}
+
+- (NSData *)lengthDelimited {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLengthDelimited);
+ return storage_.lengthDelimited;
+}
+
+- (GPBUnknownFields *)group {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeGroup);
+ return storage_.group;
+}
+
+- (GPBUInt64Array *)varintList {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ return storage_.legacy.mutableVarintList;
+}
+
+- (GPBUInt32Array *)fixed32List {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ return storage_.legacy.mutableFixed32List;
+}
+
+- (GPBUInt64Array *)fixed64List {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ return storage_.legacy.mutableFixed64List;
+}
+
+- (NSArray<NSData *> *)lengthDelimitedList {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ return storage_.legacy.mutableLengthDelimitedList;
+}
+
+- (NSArray<GPBUnknownFieldSet *> *)groupList {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ return storage_.legacy.mutableGroupList;
+}
+
- (id)copyWithZone:(NSZone *)zone {
- GPBUnknownField *result = [[GPBUnknownField allocWithZone:zone] initWithNumber:number_];
- result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone];
- result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone];
- result->mutableLengthDelimitedList_ = [mutableLengthDelimitedList_ mutableCopyWithZone:zone];
- result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone];
- if (mutableGroupList_.count) {
- result->mutableGroupList_ =
- [[NSMutableArray allocWithZone:zone] initWithCapacity:mutableGroupList_.count];
- for (GPBUnknownFieldSet *group in mutableGroupList_) {
- GPBUnknownFieldSet *copied = [group copyWithZone:zone];
- [result->mutableGroupList_ addObject:copied];
- [copied release];
+ switch (type_) {
+ case GPBUnknownFieldTypeVarint:
+ return [[GPBUnknownField allocWithZone:zone] initWithNumber:number_ varint:storage_.intValue];
+ case GPBUnknownFieldTypeFixed32:
+ return [[GPBUnknownField allocWithZone:zone] initWithNumber:number_
+ fixed32:(uint32_t)storage_.intValue];
+ case GPBUnknownFieldTypeFixed64:
+ return [[GPBUnknownField allocWithZone:zone] initWithNumber:number_
+ fixed64:storage_.intValue];
+ case GPBUnknownFieldTypeLengthDelimited:
+ return [[GPBUnknownField allocWithZone:zone]
+ initWithNumber:number_
+ lengthDelimited:[storage_.lengthDelimited copyWithZone:zone]];
+ case GPBUnknownFieldTypeGroup:
+ return
+ [[GPBUnknownField allocWithZone:zone] initWithNumber:number_
+ group:[storage_.group copyWithZone:zone]];
+ case GPBUnknownFieldTypeLegacy: {
+ GPBUnknownField *result = [[GPBUnknownField allocWithZone:zone] initWithNumber:number_];
+ result->storage_.legacy.mutableFixed32List =
+ [storage_.legacy.mutableFixed32List copyWithZone:zone];
+ result->storage_.legacy.mutableFixed64List =
+ [storage_.legacy.mutableFixed64List copyWithZone:zone];
+ result->storage_.legacy.mutableLengthDelimitedList =
+ [storage_.legacy.mutableLengthDelimitedList mutableCopyWithZone:zone];
+ result->storage_.legacy.mutableVarintList =
+ [storage_.legacy.mutableVarintList copyWithZone:zone];
+ if (storage_.legacy.mutableGroupList.count) {
+ result->storage_.legacy.mutableGroupList = [[NSMutableArray allocWithZone:zone]
+ initWithCapacity:storage_.legacy.mutableGroupList.count];
+ for (GPBUnknownFieldSet *group in storage_.legacy.mutableGroupList) {
+ GPBUnknownFieldSet *copied = [group copyWithZone:zone];
+ [result->storage_.legacy.mutableGroupList addObject:copied];
+ [copied release];
+ }
+ }
+ return result;
}
}
- return result;
}
- (BOOL)isEqual:(id)object {
@@ -74,82 +220,120 @@
if (![object isKindOfClass:[GPBUnknownField class]]) return NO;
GPBUnknownField *field = (GPBUnknownField *)object;
if (number_ != field->number_) return NO;
- BOOL equalVarint = (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) ||
- [mutableVarintList_ isEqual:field->mutableVarintList_];
- if (!equalVarint) return NO;
- BOOL equalFixed32 = (mutableFixed32List_.count == 0 && field->mutableFixed32List_.count == 0) ||
- [mutableFixed32List_ isEqual:field->mutableFixed32List_];
- if (!equalFixed32) return NO;
- BOOL equalFixed64 = (mutableFixed64List_.count == 0 && field->mutableFixed64List_.count == 0) ||
- [mutableFixed64List_ isEqual:field->mutableFixed64List_];
- if (!equalFixed64) return NO;
- BOOL equalLDList =
- (mutableLengthDelimitedList_.count == 0 && field->mutableLengthDelimitedList_.count == 0) ||
- [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_];
- if (!equalLDList) return NO;
- BOOL equalGroupList = (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) ||
- [mutableGroupList_ isEqual:field->mutableGroupList_];
- if (!equalGroupList) return NO;
- return YES;
+ if (type_ != field->type_) return NO;
+ switch (type_) {
+ case GPBUnknownFieldTypeVarint:
+ case GPBUnknownFieldTypeFixed32:
+ case GPBUnknownFieldTypeFixed64:
+ return storage_.intValue == field->storage_.intValue;
+ case GPBUnknownFieldTypeLengthDelimited:
+ return [storage_.lengthDelimited isEqual:field->storage_.lengthDelimited];
+ case GPBUnknownFieldTypeGroup:
+ return [storage_.group isEqual:field->storage_.group];
+ case GPBUnknownFieldTypeLegacy: {
+ BOOL equalVarint =
+ (storage_.legacy.mutableVarintList.count == 0 &&
+ field->storage_.legacy.mutableVarintList.count == 0) ||
+ [storage_.legacy.mutableVarintList isEqual:field->storage_.legacy.mutableVarintList];
+ if (!equalVarint) return NO;
+ BOOL equalFixed32 =
+ (storage_.legacy.mutableFixed32List.count == 0 &&
+ field->storage_.legacy.mutableFixed32List.count == 0) ||
+ [storage_.legacy.mutableFixed32List isEqual:field->storage_.legacy.mutableFixed32List];
+ if (!equalFixed32) return NO;
+ BOOL equalFixed64 =
+ (storage_.legacy.mutableFixed64List.count == 0 &&
+ field->storage_.legacy.mutableFixed64List.count == 0) ||
+ [storage_.legacy.mutableFixed64List isEqual:field->storage_.legacy.mutableFixed64List];
+ if (!equalFixed64) return NO;
+ BOOL equalLDList = (storage_.legacy.mutableLengthDelimitedList.count == 0 &&
+ field->storage_.legacy.mutableLengthDelimitedList.count == 0) ||
+ [storage_.legacy.mutableLengthDelimitedList
+ isEqual:field->storage_.legacy.mutableLengthDelimitedList];
+ if (!equalLDList) return NO;
+ BOOL equalGroupList =
+ (storage_.legacy.mutableGroupList.count == 0 &&
+ field->storage_.legacy.mutableGroupList.count == 0) ||
+ [storage_.legacy.mutableGroupList isEqual:field->storage_.legacy.mutableGroupList];
+ if (!equalGroupList) return NO;
+ return YES;
+ }
+ }
}
- (NSUInteger)hash {
- // Just mix the hashes of the possible sub arrays.
const int prime = 31;
- NSUInteger result = prime + [mutableVarintList_ hash];
- result = prime * result + [mutableFixed32List_ hash];
- result = prime * result + [mutableFixed64List_ hash];
- result = prime * result + [mutableLengthDelimitedList_ hash];
- result = prime * result + [mutableGroupList_ hash];
+ NSUInteger result = prime * number_ + type_;
+ switch (type_) {
+ case GPBUnknownFieldTypeVarint:
+ case GPBUnknownFieldTypeFixed32:
+ case GPBUnknownFieldTypeFixed64:
+ result = prime * result + (NSUInteger)storage_.intValue;
+ break;
+ case GPBUnknownFieldTypeLengthDelimited:
+ result = prime * result + [storage_.lengthDelimited hash];
+ break;
+ case GPBUnknownFieldTypeGroup:
+ result = prime * result + [storage_.group hash];
+ case GPBUnknownFieldTypeLegacy:
+ result = prime * result + [storage_.legacy.mutableVarintList hash];
+ result = prime * result + [storage_.legacy.mutableFixed32List hash];
+ result = prime * result + [storage_.legacy.mutableFixed64List hash];
+ result = prime * result + [storage_.legacy.mutableLengthDelimitedList hash];
+ result = prime * result + [storage_.legacy.mutableGroupList hash];
+ break;
+ }
return result;
}
- (void)writeToOutput:(GPBCodedOutputStream *)output {
- NSUInteger count = mutableVarintList_.count;
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ NSUInteger count = storage_.legacy.mutableVarintList.count;
if (count > 0) {
- [output writeUInt64Array:number_ values:mutableVarintList_ tag:0];
+ [output writeUInt64Array:number_ values:storage_.legacy.mutableVarintList tag:0];
}
- count = mutableFixed32List_.count;
+ count = storage_.legacy.mutableFixed32List.count;
if (count > 0) {
- [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0];
+ [output writeFixed32Array:number_ values:storage_.legacy.mutableFixed32List tag:0];
}
- count = mutableFixed64List_.count;
+ count = storage_.legacy.mutableFixed64List.count;
if (count > 0) {
- [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0];
+ [output writeFixed64Array:number_ values:storage_.legacy.mutableFixed64List tag:0];
}
- count = mutableLengthDelimitedList_.count;
+ count = storage_.legacy.mutableLengthDelimitedList.count;
if (count > 0) {
- [output writeBytesArray:number_ values:mutableLengthDelimitedList_];
+ [output writeBytesArray:number_ values:storage_.legacy.mutableLengthDelimitedList];
}
- count = mutableGroupList_.count;
+ count = storage_.legacy.mutableGroupList.count;
if (count > 0) {
- [output writeUnknownGroupArray:number_ values:mutableGroupList_];
+ [output writeUnknownGroupArray:number_ values:storage_.legacy.mutableGroupList];
}
}
- (size_t)serializedSize {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
__block size_t result = 0;
int32_t number = number_;
- [mutableVarintList_
+ [storage_.legacy.mutableVarintList
enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
result += GPBComputeUInt64Size(number, value);
}];
- [mutableFixed32List_
+ [storage_.legacy.mutableFixed32List
enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
result += GPBComputeFixed32Size(number, value);
}];
- [mutableFixed64List_
+ [storage_.legacy.mutableFixed64List
enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
result += GPBComputeFixed64Size(number, value);
}];
- for (NSData *data in mutableLengthDelimitedList_) {
+ for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
result += GPBComputeBytesSize(number, data);
}
- for (GPBUnknownFieldSet *set in mutableGroupList_) {
+ for (GPBUnknownFieldSet *set in storage_.legacy.mutableGroupList) {
result += GPBComputeUnknownGroupSize(number, set);
}
@@ -157,14 +341,16 @@
}
- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output {
- for (NSData *data in mutableLengthDelimitedList_) {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
[output writeRawMessageSetExtension:number_ value:data];
}
}
- (size_t)serializedSizeAsMessageSetExtension {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
size_t result = 0;
- for (NSData *data in mutableLengthDelimitedList_) {
+ for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
result += GPBComputeRawMessageSetExtensionSize(number_, data);
}
return result;
@@ -172,121 +358,145 @@
- (NSString *)description {
NSMutableString *description =
- [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_];
- [mutableVarintList_
- enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
- [description appendFormat:@"\t%llu\n", value];
- }];
-
- [mutableFixed32List_
- enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
- [description appendFormat:@"\t%u\n", value];
- }];
-
- [mutableFixed64List_
- enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
- [description appendFormat:@"\t%llu\n", value];
- }];
-
- for (NSData *data in mutableLengthDelimitedList_) {
- [description appendFormat:@"\t%@\n", data];
+ [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d", [self class], self, number_];
+ switch (type_) {
+ case GPBUnknownFieldTypeVarint:
+ [description appendFormat:@" varint: %llu", storage_.intValue];
+ break;
+ case GPBUnknownFieldTypeFixed32:
+ [description appendFormat:@" fixed32: %u", (uint32_t)storage_.intValue];
+ break;
+ case GPBUnknownFieldTypeFixed64:
+ [description appendFormat:@" fixed64: %llu", storage_.intValue];
+ break;
+ case GPBUnknownFieldTypeLengthDelimited:
+ [description appendFormat:@" fixed64: %@", storage_.lengthDelimited];
+ break;
+ case GPBUnknownFieldTypeGroup:
+ [description appendFormat:@" group: %@", storage_.group];
+ break;
+ case GPBUnknownFieldTypeLegacy:
+ [description appendString:@" {\n"];
+ [storage_.legacy.mutableVarintList
+ enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
+ [description appendFormat:@"\t%llu\n", value];
+ }];
+ [storage_.legacy.mutableFixed32List
+ enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
+ [description appendFormat:@"\t%u\n", value];
+ }];
+ [storage_.legacy.mutableFixed64List
+ enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
+ [description appendFormat:@"\t%llu\n", value];
+ }];
+ for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
+ [description appendFormat:@"\t%@\n", data];
+ }
+ for (GPBUnknownFieldSet *set in storage_.legacy.mutableGroupList) {
+ [description appendFormat:@"\t%@\n", set];
+ }
+ [description appendString:@"}"];
+ break;
}
-
- for (GPBUnknownFieldSet *set in mutableGroupList_) {
- [description appendFormat:@"\t%@\n", set];
- }
- [description appendString:@"}"];
return description;
}
- (void)mergeFromField:(GPBUnknownField *)other {
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
GPBUInt64Array *otherVarintList = other.varintList;
if (otherVarintList.count > 0) {
- if (mutableVarintList_ == nil) {
- mutableVarintList_ = [otherVarintList copy];
+ if (storage_.legacy.mutableVarintList == nil) {
+ storage_.legacy.mutableVarintList = [otherVarintList copy];
} else {
- [mutableVarintList_ addValuesFromArray:otherVarintList];
+ [storage_.legacy.mutableVarintList addValuesFromArray:otherVarintList];
}
}
GPBUInt32Array *otherFixed32List = other.fixed32List;
if (otherFixed32List.count > 0) {
- if (mutableFixed32List_ == nil) {
- mutableFixed32List_ = [otherFixed32List copy];
+ if (storage_.legacy.mutableFixed32List == nil) {
+ storage_.legacy.mutableFixed32List = [otherFixed32List copy];
} else {
- [mutableFixed32List_ addValuesFromArray:otherFixed32List];
+ [storage_.legacy.mutableFixed32List addValuesFromArray:otherFixed32List];
}
}
GPBUInt64Array *otherFixed64List = other.fixed64List;
if (otherFixed64List.count > 0) {
- if (mutableFixed64List_ == nil) {
- mutableFixed64List_ = [otherFixed64List copy];
+ if (storage_.legacy.mutableFixed64List == nil) {
+ storage_.legacy.mutableFixed64List = [otherFixed64List copy];
} else {
- [mutableFixed64List_ addValuesFromArray:otherFixed64List];
+ [storage_.legacy.mutableFixed64List addValuesFromArray:otherFixed64List];
}
}
NSArray *otherLengthDelimitedList = other.lengthDelimitedList;
if (otherLengthDelimitedList.count > 0) {
- if (mutableLengthDelimitedList_ == nil) {
- mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy];
+ if (storage_.legacy.mutableLengthDelimitedList == nil) {
+ storage_.legacy.mutableLengthDelimitedList = [otherLengthDelimitedList mutableCopy];
} else {
- [mutableLengthDelimitedList_ addObjectsFromArray:otherLengthDelimitedList];
+ [storage_.legacy.mutableLengthDelimitedList addObjectsFromArray:otherLengthDelimitedList];
}
}
NSArray *otherGroupList = other.groupList;
if (otherGroupList.count > 0) {
- if (mutableGroupList_ == nil) {
- mutableGroupList_ = [[NSMutableArray alloc] initWithCapacity:otherGroupList.count];
+ if (storage_.legacy.mutableGroupList == nil) {
+ storage_.legacy.mutableGroupList =
+ [[NSMutableArray alloc] initWithCapacity:otherGroupList.count];
}
// Make our own mutable copies.
for (GPBUnknownFieldSet *group in otherGroupList) {
GPBUnknownFieldSet *copied = [group copy];
- [mutableGroupList_ addObject:copied];
+ [storage_.legacy.mutableGroupList addObject:copied];
[copied release];
}
}
}
- (void)addVarint:(uint64_t)value {
- if (mutableVarintList_ == nil) {
- mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1];
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ if (storage_.legacy.mutableVarintList == nil) {
+ storage_.legacy.mutableVarintList = [[GPBUInt64Array alloc] initWithValues:&value count:1];
} else {
- [mutableVarintList_ addValue:value];
+ [storage_.legacy.mutableVarintList addValue:value];
}
}
- (void)addFixed32:(uint32_t)value {
- if (mutableFixed32List_ == nil) {
- mutableFixed32List_ = [[GPBUInt32Array alloc] initWithValues:&value count:1];
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ if (storage_.legacy.mutableFixed32List == nil) {
+ storage_.legacy.mutableFixed32List = [[GPBUInt32Array alloc] initWithValues:&value count:1];
} else {
- [mutableFixed32List_ addValue:value];
+ [storage_.legacy.mutableFixed32List addValue:value];
}
}
- (void)addFixed64:(uint64_t)value {
- if (mutableFixed64List_ == nil) {
- mutableFixed64List_ = [[GPBUInt64Array alloc] initWithValues:&value count:1];
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ if (storage_.legacy.mutableFixed64List == nil) {
+ storage_.legacy.mutableFixed64List = [[GPBUInt64Array alloc] initWithValues:&value count:1];
} else {
- [mutableFixed64List_ addValue:value];
+ [storage_.legacy.mutableFixed64List addValue:value];
}
}
- (void)addLengthDelimited:(NSData *)value {
- if (mutableLengthDelimitedList_ == nil) {
- mutableLengthDelimitedList_ = [[NSMutableArray alloc] initWithObjects:&value count:1];
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ if (storage_.legacy.mutableLengthDelimitedList == nil) {
+ storage_.legacy.mutableLengthDelimitedList = [[NSMutableArray alloc] initWithObjects:&value
+ count:1];
} else {
- [mutableLengthDelimitedList_ addObject:value];
+ [storage_.legacy.mutableLengthDelimitedList addObject:value];
}
}
- (void)addGroup:(GPBUnknownFieldSet *)value {
- if (mutableGroupList_ == nil) {
- mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1];
+ ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
+ if (storage_.legacy.mutableGroupList == nil) {
+ storage_.legacy.mutableGroupList = [[NSMutableArray alloc] initWithObjects:&value count:1];
} else {
- [mutableGroupList_ addObject:value];
+ [storage_.legacy.mutableGroupList addObject:value];
}
}
diff --git a/objectivec/GPBUnknownField_PackagePrivate.h b/objectivec/GPBUnknownField_PackagePrivate.h
index 17304f3..e95358f 100644
--- a/objectivec/GPBUnknownField_PackagePrivate.h
+++ b/objectivec/GPBUnknownField_PackagePrivate.h
@@ -13,12 +13,18 @@
@interface GPBUnknownField ()
-- (void)writeToOutput:(GPBCodedOutputStream *)output;
+- (nonnull instancetype)initWithNumber:(int32_t)number varint:(uint64_t)varint;
+- (nonnull instancetype)initWithNumber:(int32_t)number fixed32:(uint32_t)fixed32;
+- (nonnull instancetype)initWithNumber:(int32_t)number fixed64:(uint64_t)fixed64;
+- (nonnull instancetype)initWithNumber:(int32_t)number lengthDelimited:(nonnull NSData *)data;
+- (nonnull instancetype)initWithNumber:(int32_t)number group:(nonnull GPBUnknownFields *)group;
+
+- (void)writeToOutput:(nonnull GPBCodedOutputStream *)output;
- (size_t)serializedSize;
-- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output;
+- (void)writeAsMessageSetExtensionToOutput:(nonnull GPBCodedOutputStream *)output;
- (size_t)serializedSizeAsMessageSetExtension;
-- (void)mergeFromField:(GPBUnknownField *)other;
+- (void)mergeFromField:(nonnull GPBUnknownField *)other;
@end
diff --git a/objectivec/GPBUnknownFields.h b/objectivec/GPBUnknownFields.h
new file mode 100644
index 0000000..07c4dbf
--- /dev/null
+++ b/objectivec/GPBUnknownFields.h
@@ -0,0 +1,155 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+#import <Foundation/Foundation.h>
+
+@class GPBUnknownField;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * A collection of unknown field numbers and their values.
+ *
+ * Note: `NSFastEnumeration` is supported to iterate over the `GPBUnknownFields`
+ * in order.
+ *
+ * Reminder: Any field number can occur multiple times. For example, if a .proto
+ * file were updated to a have a new (unpacked) repeated field, then each value
+ * would appear independently. Likewise, it is possible that a number appears
+ * multiple times with different data types, i.e. - unpacked vs. package repeated
+ * fields from concatenating binary blobs of data.
+ */
+__attribute__((objc_subclassing_restricted))
+@interface GPBUnknownFields : NSObject<NSCopying, NSFastEnumeration>
+
+/**
+ * Initializes a new empty instance.
+ **/
+- (instancetype)init;
+
+/**
+ * The number of fields in this set. A single field number can appear in
+ * multiple `GPBUnknownField` values as it might be a repeated field (it is
+ * also possible that they have different `type` values (for example package vs
+ * unpacked repeated fields).
+ *
+ * Note: `NSFastEnumeration` is supported to iterate over the fields in order.
+ **/
+@property(nonatomic, readonly, assign) NSUInteger count;
+
+/** If the set is empty or not. */
+@property(nonatomic, readonly, assign) BOOL empty;
+
+/**
+ * Removes all the fields current in the set.
+ **/
+- (void)clear;
+
+/**
+ * Fetches the subset of all the unknown fields that are for the given field
+ * number.
+ *
+ * @returns An `NSArray` of `GPBUnknownField`s or `nil` if there were none.
+ */
+- (nullable NSArray<GPBUnknownField *> *)fields:(int32_t)fieldNumber;
+
+/**
+ * Add a new varint unknown field.
+ *
+ * @param fieldNumber The field number to use.
+ * @param value The value to add.
+ **/
+- (void)addFieldNumber:(int32_t)fieldNumber varint:(uint64_t)value;
+
+/**
+ * Add a new fixed32 unknown field.
+ *
+ * @param fieldNumber The field number to use.
+ * @param value The value to add.
+ **/
+- (void)addFieldNumber:(int32_t)fieldNumber fixed32:(uint32_t)value;
+
+/**
+ * Add a new fixed64 unknown field.
+ *
+ * @param fieldNumber The field number to use.
+ * @param value The value to add.
+ **/
+- (void)addFieldNumber:(int32_t)fieldNumber fixed64:(uint64_t)value;
+
+/**
+ * Add a new length delimited (length prefixed) unknown field.
+ *
+ * @param fieldNumber The field number to use.
+ * @param value The value to add.
+ **/
+- (void)addFieldNumber:(int32_t)fieldNumber lengthDelimited:(nonnull NSData *)value;
+
+/**
+ * Add a group (tag delimited) unknown field.
+ *
+ * @param fieldNumber The field number to use.
+ *
+ * @return A new `GPBUnknownFields` to set the field of the group too.
+ **/
+- (nonnull GPBUnknownFields *)addGroupWithFieldNumber:(int32_t)fieldNumber;
+
+@end
+
+@interface GPBUnknownFields (AccessHelpers)
+
+/**
+ * Fetches the first varint for the given field number.
+ *
+ * @param fieldNumber The field number to look for.
+ * @param outValue A pointer to receive the value if found
+ *
+ * @returns YES/NO on if there was a matching unknown field.
+ **/
+- (BOOL)getFirst:(int32_t)fieldNumber varint:(nonnull uint64_t *)outValue;
+
+/**
+ * Fetches the first fixed32 for the given field number.
+ *
+ * @param fieldNumber The field number to look for.
+ * @param outValue A pointer to receive the value if found
+ *
+ * @returns YES/NO on if there was a matching unknown field.
+ **/
+- (BOOL)getFirst:(int32_t)fieldNumber fixed32:(nonnull uint32_t *)outValue;
+
+/**
+ * Fetches the first fixed64 for the given field number.
+ *
+ * @param fieldNumber The field number to look for.
+ * @param outValue A pointer to receive the value if found
+ *
+ * @returns YES/NO on if there was a matching unknown field.
+ **/
+- (BOOL)getFirst:(int32_t)fieldNumber fixed64:(nonnull uint64_t *)outValue;
+
+/**
+ * Fetches the first length delimited (length prefixed) for the given field number.
+ *
+ * @param fieldNumber The field number to look for.
+ *
+ * @returns The first length delimited value for the given field number.
+ **/
+- (nullable NSData *)firstLengthDelimited:(int32_t)fieldNumber;
+
+/**
+ * Fetches the first group (tag delimited) field for the given field number.
+ *
+ * @param fieldNumber The field number to look for.
+ *
+ * @returns The first group for the given field number.
+ **/
+- (nullable GPBUnknownFields *)firstGroup:(int32_t)fieldNumber;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/objectivec/GPBUnknownFields.m b/objectivec/GPBUnknownFields.m
new file mode 100644
index 0000000..aed1bc9
--- /dev/null
+++ b/objectivec/GPBUnknownFields.m
@@ -0,0 +1,199 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+#import "GPBUnknownFields.h"
+#import "GPBUnknownField_PackagePrivate.h"
+
+#define CHECK_FIELD_NUMBER(number) \
+ if (number <= 0) { \
+ [NSException raise:NSInvalidArgumentException format:@"Not a valid field number."]; \
+ }
+
+@implementation GPBUnknownFields {
+ @package
+ NSMutableArray<GPBUnknownField *> *fields_;
+}
+
+// Direct access is use for speed, to avoid even internally declaring things
+// read/write, etc. The warning is enabled in the project to ensure code calling
+// protos can turn on -Wdirect-ivar-access without issues.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdirect-ivar-access"
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ fields_ = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+ GPBUnknownFields *copy = [[GPBUnknownFields alloc] init];
+ // Fields are r/o in this api, so just copy the array.
+ copy->fields_ = [fields_ mutableCopyWithZone:zone];
+ return copy;
+}
+
+- (void)dealloc {
+ [fields_ release];
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(id)object {
+ if (![object isKindOfClass:[GPBUnknownFields class]]) {
+ return NO;
+ }
+ GPBUnknownFields *ufs = (GPBUnknownFields *)object;
+ // The type is defined with order of fields mattering, so just compare the arrays.
+ return [fields_ isEqual:ufs->fields_];
+}
+
+- (NSUInteger)hash {
+ return [fields_ hash];
+}
+
+- (NSString *)description {
+ return [NSString
+ stringWithFormat:@"<%@ %p>: %lu fields", [self class], self, (unsigned long)fields_.count];
+}
+
+#pragma mark - Public Methods
+
+- (NSUInteger)count {
+ return fields_.count;
+}
+
+- (BOOL)empty {
+ return fields_.count == 0;
+}
+
+- (void)clear {
+ [fields_ removeAllObjects];
+}
+
+- (NSArray<GPBUnknownField *> *)fields:(int32_t)fieldNumber {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ NSMutableArray<GPBUnknownField *> *result = [[NSMutableArray alloc] init];
+ for (GPBUnknownField *field in fields_) {
+ if (field.number == fieldNumber) {
+ [result addObject:field];
+ }
+ }
+ if (result.count == 0) {
+ [result release];
+ return nil;
+ }
+ return [result autorelease];
+}
+
+- (void)addFieldNumber:(int32_t)fieldNumber varint:(uint64_t)value {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber varint:value];
+ [fields_ addObject:field];
+ [field release];
+}
+
+- (void)addFieldNumber:(int32_t)fieldNumber fixed32:(uint32_t)value {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber fixed32:value];
+ [fields_ addObject:field];
+ [field release];
+}
+
+- (void)addFieldNumber:(int32_t)fieldNumber fixed64:(uint64_t)value {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber fixed64:value];
+ [fields_ addObject:field];
+ [field release];
+}
+
+- (void)addFieldNumber:(int32_t)fieldNumber lengthDelimited:(NSData *)value {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber
+ lengthDelimited:value];
+ [fields_ addObject:field];
+ [field release];
+}
+
+- (GPBUnknownFields *)addGroupWithFieldNumber:(int32_t)fieldNumber {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ GPBUnknownFields *group = [[GPBUnknownFields alloc] init];
+ GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber group:group];
+ [fields_ addObject:field];
+ [field release];
+ return [group autorelease];
+}
+
+#pragma mark - NSFastEnumeration protocol
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
+ objects:(__unsafe_unretained id _Nonnull *)stackbuf
+ count:(NSUInteger)len {
+ return [fields_ countByEnumeratingWithState:state objects:stackbuf count:len];
+}
+
+@end
+
+@implementation GPBUnknownFields (AccessHelpers)
+
+- (BOOL)getFirst:(int32_t)fieldNumber varint:(nonnull uint64_t *)outValue {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ for (GPBUnknownField *field in fields_) {
+ if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeVarint) {
+ *outValue = field.varint;
+ return YES;
+ }
+ }
+ return NO;
+}
+
+- (BOOL)getFirst:(int32_t)fieldNumber fixed32:(nonnull uint32_t *)outValue {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ for (GPBUnknownField *field in fields_) {
+ if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeFixed32) {
+ *outValue = field.fixed32;
+ return YES;
+ }
+ }
+ return NO;
+}
+
+- (BOOL)getFirst:(int32_t)fieldNumber fixed64:(nonnull uint64_t *)outValue {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ for (GPBUnknownField *field in fields_) {
+ if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeFixed64) {
+ *outValue = field.fixed64;
+ return YES;
+ }
+ }
+ return NO;
+}
+
+- (nullable NSData *)firstLengthDelimited:(int32_t)fieldNumber {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ for (GPBUnknownField *field in fields_) {
+ if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeLengthDelimited) {
+ return field.lengthDelimited;
+ }
+ }
+ return nil;
+}
+
+- (nullable GPBUnknownFields *)firstGroup:(int32_t)fieldNumber {
+ CHECK_FIELD_NUMBER(fieldNumber);
+ for (GPBUnknownField *field in fields_) {
+ if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeGroup) {
+ return field.group;
+ }
+ }
+ return nil;
+}
+
+#pragma clang diagnostic pop
+
+@end
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
index c6466b2..b40bf9c 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
@@ -70,6 +70,10 @@
F4353D371AC06F10005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D301AC06F10005A6198 /* GPBDictionaryTests+String.m */; };
F4353D381AC06F10005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */; };
F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */; };
+ F43ADD302C2F2B91005312E5 /* GPBUnknownFields.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD2E2C2F2B91005312E5 /* GPBUnknownFields.m */; };
+ F43ADD312C2F2B91005312E5 /* GPBUnknownFields.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD2F2C2F2B91005312E5 /* GPBUnknownFields.h */; };
+ F43ADD332C2F2BAD005312E5 /* GPBUnknownFieldsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD322C2F2BAD005312E5 /* GPBUnknownFieldsTest.m */; };
+ F43ADD432C2F381F005312E5 /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD422C2F381F005312E5 /* GPBCompileTest25.m */; };
F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; };
F4487C4D1A9F8E0200531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
F4487C521A9F8E4D00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; };
@@ -206,6 +210,10 @@
F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = "<group>"; };
F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = "<group>"; };
F43725911AC9832D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = "<group>"; };
+ F43ADD2E2C2F2B91005312E5 /* GPBUnknownFields.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFields.m; sourceTree = "<group>"; };
+ F43ADD2F2C2F2B91005312E5 /* GPBUnknownFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields.h; sourceTree = "<group>"; };
+ F43ADD322C2F2BAD005312E5 /* GPBUnknownFieldsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldsTest.m; sourceTree = "<group>"; };
+ F43ADD422C2F381F005312E5 /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = "<group>"; };
F4411BE71AF12FD700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = "<group>"; };
F4487C511A9F8E0200531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -409,6 +417,8 @@
F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */,
7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */,
7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */,
+ F43ADD2F2C2F2B91005312E5 /* GPBUnknownFields.h */,
+ F43ADD2E2C2F2B91005312E5 /* GPBUnknownFields.m */,
F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */,
7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */,
7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */,
@@ -478,6 +488,7 @@
F40EE48A206BF8B00071091A /* GPBCompileTest22.m */,
F40EE487206BF8B00071091A /* GPBCompileTest23.m */,
F4A92AFC2B88E105001E4F69 /* GPBCompileTest24.m */,
+ F43ADD422C2F381F005312E5 /* GPBCompileTest25.m */,
5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */,
F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */,
@@ -502,6 +513,7 @@
8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */,
F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */,
7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */,
+ F43ADD322C2F2BAD005312E5 /* GPBUnknownFieldsTest.m */,
7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */,
7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */,
@@ -563,6 +575,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ F43ADD312C2F2B91005312E5 /* GPBUnknownFields.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -708,6 +721,7 @@
7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */,
F47CF93223D9006000C7B24C /* GPBWrappers.pbobjc.m in Sources */,
F47CF94123D902D500C7B24C /* GPBEmpty.pbobjc.m in Sources */,
+ F43ADD302C2F2B91005312E5 /* GPBUnknownFields.m in Sources */,
F47CF94623D902D500C7B24C /* GPBDuration.pbobjc.m in Sources */,
F47CF92F23D9006000C7B24C /* GPBSourceContext.pbobjc.m in Sources */,
7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */,
@@ -769,9 +783,11 @@
5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */,
F40EE4AC206BF8B90071091A /* GPBCompileTest02.m in Sources */,
+ F43ADD432C2F381F005312E5 /* GPBCompileTest25.m in Sources */,
F4353D351AC06F10005A6198 /* GPBDictionaryTests+Int32.m in Sources */,
F40EE4AF206BF8B90071091A /* GPBCompileTest05.m in Sources */,
F40EE4B8206BF8B90071091A /* GPBCompileTest14.m in Sources */,
+ F43ADD332C2F2BAD005312E5 /* GPBUnknownFieldsTest.m in Sources */,
8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */,
F40EE4AE206BF8B90071091A /* GPBCompileTest04.m in Sources */,
F40EE4BA206BF8B90071091A /* GPBCompileTest16.m in Sources */,
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
index 6e24f4c..2438b6a 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -70,6 +70,9 @@
F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */; };
F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */; };
F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */; };
+ F43ADD352C2F2CE9005312E5 /* GPBUnknownFieldsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD342C2F2CE9005312E5 /* GPBUnknownFieldsTest.m */; };
+ F43ADD412C2F2D60005312E5 /* GPBUnknownFields.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD362C2F2D06005312E5 /* GPBUnknownFields.m */; };
+ F43ADD472C2F387A005312E5 /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD462C2F387A005312E5 /* GPBCompileTest25.m */; };
F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; };
F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; };
@@ -207,6 +210,10 @@
F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = "<group>"; };
F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = "<group>"; };
F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = "<group>"; };
+ F43ADD342C2F2CE9005312E5 /* GPBUnknownFieldsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldsTest.m; sourceTree = "<group>"; };
+ F43ADD362C2F2D06005312E5 /* GPBUnknownFields.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFields.m; sourceTree = "<group>"; };
+ F43ADD372C2F2D06005312E5 /* GPBUnknownFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields.h; sourceTree = "<group>"; };
+ F43ADD462C2F387A005312E5 /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = "<group>"; };
F4411BE81AF1301700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = "<group>"; };
F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -415,6 +422,8 @@
F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */,
7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */,
7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */,
+ F43ADD372C2F2D06005312E5 /* GPBUnknownFields.h */,
+ F43ADD362C2F2D06005312E5 /* GPBUnknownFields.m */,
F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */,
7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */,
7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */,
@@ -484,6 +493,7 @@
F40EE4CF206BF9170071091A /* GPBCompileTest22.m */,
F40EE4CC206BF9170071091A /* GPBCompileTest23.m */,
F4A92AFE2B88E662001E4F69 /* GPBCompileTest24.m */,
+ F43ADD462C2F387A005312E5 /* GPBCompileTest25.m */,
5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */,
F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */,
@@ -508,6 +518,7 @@
8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */,
F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */,
7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */,
+ F43ADD342C2F2CE9005312E5 /* GPBUnknownFieldsTest.m */,
7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */,
7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */,
@@ -715,6 +726,7 @@
F47CF96D23D903C600C7B24C /* GPBAny.pbobjc.m in Sources */,
F47CF96623D903C600C7B24C /* GPBSourceContext.pbobjc.m in Sources */,
F47CF96C23D903C600C7B24C /* GPBType.pbobjc.m in Sources */,
+ F43ADD412C2F2D60005312E5 /* GPBUnknownFields.m in Sources */,
F47CF96423D903C600C7B24C /* GPBStruct.pbobjc.m in Sources */,
F47CF96723D903C600C7B24C /* GPBEmpty.pbobjc.m in Sources */,
F4487C731A9F906200531423 /* GPBArray.m in Sources */,
@@ -776,9 +788,11 @@
5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */,
F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */,
+ F43ADD472C2F387A005312E5 /* GPBCompileTest25.m in Sources */,
F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */,
F40EE4F4206BF91E0071091A /* GPBCompileTest05.m in Sources */,
F40EE4FD206BF91E0071091A /* GPBCompileTest14.m in Sources */,
+ F43ADD352C2F2CE9005312E5 /* GPBUnknownFieldsTest.m in Sources */,
8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */,
F40EE4F3206BF91E0071091A /* GPBCompileTest04.m in Sources */,
F40EE4FF206BF91E0071091A /* GPBCompileTest16.m in Sources */,
diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
index cc32112..d9d698d 100644
--- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
@@ -70,6 +70,10 @@
F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */; };
F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */; };
F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */; };
+ F43ADD3A2C2F2D26005312E5 /* GPBUnknownFieldsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD392C2F2D26005312E5 /* GPBUnknownFieldsTest.m */; };
+ F43ADD3D2C2F2D3D005312E5 /* GPBUnknownFields.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD3B2C2F2D3D005312E5 /* GPBUnknownFields.m */; };
+ F43ADD3E2C2F2D3D005312E5 /* GPBUnknownFields.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD3C2C2F2D3D005312E5 /* GPBUnknownFields.h */; };
+ F43ADD492C2F389D005312E5 /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD482C2F389D005312E5 /* GPBCompileTest25.m */; };
F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; };
F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; };
@@ -207,6 +211,10 @@
F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = "<group>"; };
F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = "<group>"; };
F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = "<group>"; };
+ F43ADD392C2F2D26005312E5 /* GPBUnknownFieldsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldsTest.m; sourceTree = "<group>"; };
+ F43ADD3B2C2F2D3D005312E5 /* GPBUnknownFields.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFields.m; sourceTree = "<group>"; };
+ F43ADD3C2C2F2D3D005312E5 /* GPBUnknownFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields.h; sourceTree = "<group>"; };
+ F43ADD482C2F389D005312E5 /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = "<group>"; };
F4411BE81AF1301700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = "<group>"; };
F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -415,6 +423,8 @@
F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */,
7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */,
7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */,
+ F43ADD3C2C2F2D3D005312E5 /* GPBUnknownFields.h */,
+ F43ADD3B2C2F2D3D005312E5 /* GPBUnknownFields.m */,
F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */,
7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */,
7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */,
@@ -484,6 +494,7 @@
F40EE4CF206BF9170071091A /* GPBCompileTest22.m */,
F40EE4CC206BF9170071091A /* GPBCompileTest23.m */,
F4A92B002B88E683001E4F69 /* GPBCompileTest24.m */,
+ F43ADD482C2F389D005312E5 /* GPBCompileTest25.m */,
5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */,
F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */,
@@ -508,6 +519,7 @@
8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */,
F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */,
7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */,
+ F43ADD392C2F2D26005312E5 /* GPBUnknownFieldsTest.m */,
7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */,
7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */,
@@ -569,6 +581,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ F43ADD3E2C2F2D3D005312E5 /* GPBUnknownFields.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -715,6 +728,7 @@
F4487C731A9F906200531423 /* GPBArray.m in Sources */,
F47CF98923D904E600C7B24C /* GPBStruct.pbobjc.m in Sources */,
F47CF98623D904E600C7B24C /* GPBEmpty.pbobjc.m in Sources */,
+ F43ADD3D2C2F2D3D005312E5 /* GPBUnknownFields.m in Sources */,
7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */,
F47CF98523D904E600C7B24C /* GPBApi.pbobjc.m in Sources */,
7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */,
@@ -776,9 +790,11 @@
5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */,
F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */,
+ F43ADD492C2F389D005312E5 /* GPBCompileTest25.m in Sources */,
F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */,
F40EE4F4206BF91E0071091A /* GPBCompileTest05.m in Sources */,
F40EE4FD206BF91E0071091A /* GPBCompileTest14.m in Sources */,
+ F43ADD3A2C2F2D26005312E5 /* GPBUnknownFieldsTest.m in Sources */,
8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */,
F40EE4F3206BF91E0071091A /* GPBCompileTest04.m in Sources */,
F40EE4FF206BF91E0071091A /* GPBCompileTest16.m in Sources */,
diff --git a/objectivec/Tests/GPBCompileTest25.m b/objectivec/Tests/GPBCompileTest25.m
new file mode 100644
index 0000000..450795b
--- /dev/null
+++ b/objectivec/Tests/GPBCompileTest25.m
@@ -0,0 +1,15 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+// This is a test including a single public header to ensure things build.
+// It helps test that imports are complete/ordered correctly.
+
+#import "GPBUnknownFields.h"
+
+// Something in the body of this file so the compiler/linker won't complain
+// about an empty .o file.
+__attribute__((visibility("default"))) char dummy_symbol_25 = 0;
diff --git a/objectivec/Tests/GPBUnknownFieldsTest.m b/objectivec/Tests/GPBUnknownFieldsTest.m
new file mode 100644
index 0000000..552c21d
--- /dev/null
+++ b/objectivec/Tests/GPBUnknownFieldsTest.m
@@ -0,0 +1,514 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+#import "GPBTestUtilities.h"
+#import "GPBUnknownField.h"
+#import "GPBUnknownFields.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+
+@interface UnknownFieldsTest : GPBTestCase
+@end
+
+@implementation UnknownFieldsTest
+
+- (void)testEmptyAndClear {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ XCTAssertTrue(ufs.empty);
+
+ [ufs addFieldNumber:1 varint:1];
+ XCTAssertFalse(ufs.empty);
+ [ufs clear];
+ XCTAssertTrue(ufs.empty);
+
+ [ufs addFieldNumber:1 fixed32:1];
+ XCTAssertFalse(ufs.empty);
+ [ufs clear];
+ XCTAssertTrue(ufs.empty);
+
+ [ufs addFieldNumber:1 fixed64:1];
+ XCTAssertFalse(ufs.empty);
+ [ufs clear];
+ XCTAssertTrue(ufs.empty);
+
+ [ufs addFieldNumber:1 lengthDelimited:[NSData data]];
+ XCTAssertFalse(ufs.empty);
+ [ufs clear];
+ XCTAssertTrue(ufs.empty);
+
+ GPBUnknownFields* group = [ufs addGroupWithFieldNumber:1];
+ XCTAssertNotNil(group);
+ XCTAssertFalse(ufs.empty);
+}
+
+- (void)testEqualityAndHash {
+ // Empty
+
+ GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease];
+ XCTAssertTrue([ufs1 isEqual:ufs1]);
+ XCTAssertFalse([ufs1 isEqual:@"foo"]);
+ GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease];
+ XCTAssertEqualObjects(ufs1, ufs2);
+ XCTAssertEqual([ufs1 hash], [ufs2 hash]);
+
+ // Varint
+
+ [ufs1 addFieldNumber:1 varint:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+ [ufs2 addFieldNumber:1 varint:1];
+ XCTAssertEqualObjects(ufs1, ufs2);
+ XCTAssertEqual([ufs1 hash], [ufs2 hash]);
+
+ // Fixed32
+
+ [ufs1 addFieldNumber:2 fixed32:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+ [ufs2 addFieldNumber:2 fixed32:1];
+ XCTAssertEqualObjects(ufs1, ufs2);
+ XCTAssertEqual([ufs1 hash], [ufs2 hash]);
+
+ // Fixed64
+
+ [ufs1 addFieldNumber:3 fixed64:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+ [ufs2 addFieldNumber:3 fixed64:1];
+ XCTAssertEqualObjects(ufs1, ufs2);
+ XCTAssertEqual([ufs1 hash], [ufs2 hash]);
+
+ // LengthDelimited
+
+ [ufs1 addFieldNumber:4 lengthDelimited:DataFromCStr("foo")];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+ [ufs2 addFieldNumber:4 lengthDelimited:DataFromCStr("foo")];
+ XCTAssertEqualObjects(ufs1, ufs2);
+ XCTAssertEqual([ufs1 hash], [ufs2 hash]);
+
+ // Group
+
+ GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:5];
+ [group1 addFieldNumber:10 varint:10];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+ GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:5];
+ [group2 addFieldNumber:10 varint:10];
+ XCTAssertEqualObjects(ufs1, ufs2);
+ XCTAssertEqual([ufs1 hash], [ufs2 hash]);
+}
+
+- (void)testInequality_Values {
+ // Same field number and type, different values.
+
+ GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease];
+ GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease];
+
+ [ufs1 addFieldNumber:1 varint:1];
+ [ufs2 addFieldNumber:1 varint:2];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 fixed32:1];
+ [ufs2 addFieldNumber:1 fixed32:2];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 fixed64:1];
+ [ufs2 addFieldNumber:1 fixed64:2];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")];
+ [ufs2 addFieldNumber:1 lengthDelimited:DataFromCStr("bar")];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1];
+ GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:1];
+ [group1 addFieldNumber:10 varint:10];
+ [group2 addFieldNumber:10 varint:20];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+ XCTAssertNotEqualObjects(group1, group2);
+}
+
+- (void)testInequality_FieldNumbers {
+ // Same type and value, different field numbers.
+
+ GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease];
+ GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease];
+
+ [ufs1 addFieldNumber:1 varint:1];
+ [ufs2 addFieldNumber:2 varint:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 fixed32:1];
+ [ufs2 addFieldNumber:2 fixed32:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 fixed64:1];
+ [ufs2 addFieldNumber:2 fixed64:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")];
+ [ufs2 addFieldNumber:2 lengthDelimited:DataFromCStr("fod")];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1];
+ GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:2];
+ [group1 addFieldNumber:10 varint:10];
+ [group2 addFieldNumber:10 varint:10];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+ XCTAssertEqualObjects(group1, group2);
+}
+
+- (void)testInequality_Types {
+ // Same field number and value when possible, different types.
+
+ GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease];
+ GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease];
+
+ [ufs1 addFieldNumber:1 varint:1];
+ [ufs2 addFieldNumber:1 fixed32:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 fixed32:1];
+ [ufs2 addFieldNumber:1 fixed64:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 fixed64:1];
+ [ufs2 addFieldNumber:1 varint:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ [ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")];
+ [ufs2 addFieldNumber:1 varint:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+
+ [ufs1 clear];
+ [ufs2 clear];
+ XCTAssertEqualObjects(ufs1, ufs2);
+
+ GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1];
+ [group1 addFieldNumber:10 varint:10];
+ [ufs2 addFieldNumber:1 varint:1];
+ XCTAssertNotEqualObjects(ufs1, ufs2);
+}
+
+- (void)testGetFirst {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ XCTAssertEqual(0U, ufs.count);
+ [ufs addFieldNumber:1 varint:1];
+ XCTAssertEqual(1U, ufs.count);
+ [ufs addFieldNumber:1 varint:2];
+ XCTAssertEqual(2U, ufs.count);
+ [ufs addFieldNumber:1 fixed32:3];
+ XCTAssertEqual(3U, ufs.count);
+ [ufs addFieldNumber:1 fixed32:4];
+ XCTAssertEqual(4U, ufs.count);
+ [ufs addFieldNumber:1 fixed64:5];
+ XCTAssertEqual(5U, ufs.count);
+ [ufs addFieldNumber:1 fixed64:6];
+ XCTAssertEqual(6U, ufs.count);
+ [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")];
+ XCTAssertEqual(7U, ufs.count);
+ [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("bar")];
+ XCTAssertEqual(8U, ufs.count);
+ GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1];
+ XCTAssertNotNil(group1);
+ XCTAssertEqual(9U, ufs.count);
+ GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:1];
+ XCTAssertNotNil(group2);
+ XCTAssertTrue(group1 != group2); // Different objects
+ XCTAssertEqual(10U, ufs.count);
+
+ [ufs addFieldNumber:11 varint:11];
+ [ufs addFieldNumber:12 fixed32:12];
+ [ufs addFieldNumber:13 fixed64:13];
+ [ufs addFieldNumber:14 lengthDelimited:DataFromCStr("foo2")];
+ GPBUnknownFields* group3 = [ufs addGroupWithFieldNumber:15];
+ XCTAssertNotNil(group3);
+ XCTAssertTrue(group3 != group1); // Different objects
+ XCTAssertTrue(group3 != group2); // Different objects
+ XCTAssertEqual(15U, ufs.count);
+
+ uint64_t varint = 0;
+ XCTAssertTrue([ufs getFirst:1 varint:&varint]);
+ XCTAssertEqual(1U, varint);
+ XCTAssertTrue([ufs getFirst:11 varint:&varint]);
+ XCTAssertEqual(11U, varint);
+ XCTAssertFalse([ufs getFirst:12 varint:&varint]); // Different type
+ XCTAssertFalse([ufs getFirst:99 varint:&varint]); // Not present
+
+ uint32_t fixed32 = 0;
+ XCTAssertTrue([ufs getFirst:1 fixed32:&fixed32]);
+ XCTAssertEqual(3U, fixed32);
+ XCTAssertTrue([ufs getFirst:12 fixed32:&fixed32]);
+ XCTAssertEqual(12U, fixed32);
+ XCTAssertFalse([ufs getFirst:11 fixed32:&fixed32]); // Different type
+ XCTAssertFalse([ufs getFirst:99 fixed32:&fixed32]); // Not present
+
+ uint64_t fixed64 = 0;
+ XCTAssertTrue([ufs getFirst:1 fixed64:&fixed64]);
+ XCTAssertEqual(5U, fixed64);
+ XCTAssertTrue([ufs getFirst:13 fixed64:&fixed64]);
+ XCTAssertEqual(13U, fixed64);
+ XCTAssertFalse([ufs getFirst:11 fixed64:&fixed64]); // Different type
+ XCTAssertFalse([ufs getFirst:99 fixed64:&fixed64]); // Not present
+
+ XCTAssertEqualObjects(DataFromCStr("foo"), [ufs firstLengthDelimited:1]);
+ XCTAssertEqualObjects(DataFromCStr("foo2"), [ufs firstLengthDelimited:14]);
+ XCTAssertNil([ufs firstLengthDelimited:11]); // Different type
+ XCTAssertNil([ufs firstLengthDelimited:99]); // Not present
+
+ XCTAssertTrue(group1 == [ufs firstGroup:1]); // Testing ptr, exact object
+ XCTAssertTrue(group3 == [ufs firstGroup:15]); // Testing ptr, exact object
+ XCTAssertNil([ufs firstGroup:11]); // Different type
+ XCTAssertNil([ufs firstGroup:99]); // Not present
+}
+
+- (void)testGetFields {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addFieldNumber:1 varint:1];
+ [ufs addFieldNumber:2 varint:2];
+ [ufs addFieldNumber:1 fixed32:3];
+ [ufs addFieldNumber:2 fixed32:4];
+ [ufs addFieldNumber:1 fixed64:5];
+ [ufs addFieldNumber:3 fixed64:6];
+ [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")];
+ [ufs addFieldNumber:2 lengthDelimited:DataFromCStr("bar")];
+ GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1];
+ GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:3];
+
+ NSArray<GPBUnknownField*>* fields1 = [ufs fields:1];
+ XCTAssertEqual(fields1.count, 5);
+ GPBUnknownField* field = fields1[0];
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint);
+ XCTAssertEqual(field.varint, 1);
+ field = fields1[1];
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32);
+ XCTAssertEqual(field.fixed32, 3);
+ field = fields1[2];
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64);
+ XCTAssertEqual(field.fixed64, 5);
+ field = fields1[3];
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited);
+ XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("foo"));
+ field = fields1[4];
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup);
+ XCTAssertTrue(field.group == group1); // Exact object.
+
+ NSArray<GPBUnknownField*>* fields2 = [ufs fields:2];
+ XCTAssertEqual(fields2.count, 3);
+ field = fields2[0];
+ XCTAssertEqual(field.number, 2);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint);
+ XCTAssertEqual(field.varint, 2);
+ field = fields2[1];
+ XCTAssertEqual(field.number, 2);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32);
+ XCTAssertEqual(field.fixed32, 4);
+ field = fields2[2];
+ XCTAssertEqual(field.number, 2);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited);
+ XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("bar"));
+
+ NSArray<GPBUnknownField*>* fields3 = [ufs fields:3];
+ XCTAssertEqual(fields3.count, 2);
+ field = fields3[0];
+ XCTAssertEqual(field.number, 3);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64);
+ XCTAssertEqual(field.fixed64, 6);
+ field = fields3[1];
+ XCTAssertEqual(field.number, 3);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup);
+ XCTAssertTrue(field.group == group2); // Exact object.
+
+ XCTAssertNil([ufs fields:99]); // Not present
+}
+
+- (void)testFastEnumeration {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addFieldNumber:1 varint:1];
+ [ufs addFieldNumber:2 varint:2];
+ [ufs addFieldNumber:1 fixed32:3];
+ [ufs addFieldNumber:2 fixed32:4];
+ [ufs addFieldNumber:1 fixed64:5];
+ [ufs addFieldNumber:3 fixed64:6];
+ [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")];
+ [ufs addFieldNumber:2 lengthDelimited:DataFromCStr("bar")];
+ GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1];
+ GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:3];
+
+ // The order added nothing to do with field numbers.
+ NSInteger loop = 0;
+ for (GPBUnknownField* field in ufs) {
+ ++loop;
+ switch (loop) {
+ case 1:
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint);
+ XCTAssertEqual(field.varint, 1);
+ break;
+ case 2:
+ XCTAssertEqual(field.number, 2);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint);
+ XCTAssertEqual(field.varint, 2);
+ break;
+ case 3:
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32);
+ XCTAssertEqual(field.fixed32, 3);
+ break;
+ case 4:
+ XCTAssertEqual(field.number, 2);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32);
+ XCTAssertEqual(field.fixed32, 4);
+ break;
+ case 5:
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64);
+ XCTAssertEqual(field.fixed64, 5);
+ break;
+ case 6:
+ XCTAssertEqual(field.number, 3);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64);
+ XCTAssertEqual(field.fixed64, 6);
+ break;
+ case 7:
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited);
+ XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("foo"));
+ break;
+ case 8:
+ XCTAssertEqual(field.number, 2);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited);
+ XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("bar"));
+ break;
+ case 9:
+ XCTAssertEqual(field.number, 1);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup);
+ XCTAssertTrue(field.group == group1); // Exact object.
+ break;
+ case 10:
+ XCTAssertEqual(field.number, 3);
+ XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup);
+ XCTAssertTrue(field.group == group2); // Exact object.
+ break;
+ default:
+ XCTFail(@"Unexpected");
+ break;
+ }
+ }
+ XCTAssertEqual(loop, 10);
+}
+
+- (void)testDescriptions {
+ // Exercise description for completeness.
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addFieldNumber:1 varint:1];
+ [ufs addFieldNumber:2 fixed32:1];
+ [ufs addFieldNumber:1 fixed64:1];
+ [ufs addFieldNumber:4 lengthDelimited:DataFromCStr("foo")];
+ [[ufs addGroupWithFieldNumber:5] addFieldNumber:10 varint:10];
+ XCTAssertTrue(ufs.description.length > 10);
+ for (GPBUnknownField* field in ufs) {
+ XCTAssertTrue(field.description.length > 10);
+ }
+}
+
+- (void)testInvalidFieldNumbers {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+
+ XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 varint:1], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 fixed32:1], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 fixed64:1], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 lengthDelimited:[NSData data]], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs addGroupWithFieldNumber:0], NSException,
+ NSInvalidArgumentException);
+
+ XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 varint:1], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 fixed32:1], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 fixed64:1], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 lengthDelimited:[NSData data]], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs addGroupWithFieldNumber:-1], NSException,
+ NSInvalidArgumentException);
+
+ uint64_t varint;
+ uint32_t fixed32;
+ uint64_t fixed64;
+ XCTAssertThrowsSpecificNamed([ufs getFirst:0 varint:&varint], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs getFirst:0 fixed32:&fixed32], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs getFirst:0 fixed64:&fixed64], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs firstLengthDelimited:0], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs firstGroup:0], NSException, NSInvalidArgumentException);
+
+ XCTAssertThrowsSpecificNamed([ufs getFirst:-1 varint:&varint], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs getFirst:-1 fixed32:&fixed32], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs getFirst:-1 fixed64:&fixed64], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs firstLengthDelimited:-1], NSException,
+ NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs firstGroup:-1], NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs fields:0], NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([ufs fields:-1], NSException, NSInvalidArgumentException);
+}
+
+@end