[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
pull/17276/head
Thomas Van Lenten 9 months ago committed by Copybara-Service
parent a4f9ddd8fc
commit 47f633eae6
  1. 2
      objectivec/BUILD.bazel
  2. 1
      objectivec/GPBProtocolBuffers.h
  3. 1
      objectivec/GPBProtocolBuffers.m
  4. 106
      objectivec/GPBUnknownField.h
  5. 452
      objectivec/GPBUnknownField.m
  6. 12
      objectivec/GPBUnknownField_PackagePrivate.h
  7. 155
      objectivec/GPBUnknownFields.h
  8. 199
      objectivec/GPBUnknownFields.m
  9. 16
      objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
  10. 14
      objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
  11. 16
      objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
  12. 15
      objectivec/Tests/GPBCompileTest25.m
  13. 514
      objectivec/Tests/GPBUnknownFieldsTest.m

@ -84,6 +84,7 @@ objc_library(
"GPBRootObject.h",
"GPBRuntimeTypes.h",
"GPBUnknownField.h",
"GPBUnknownFields.h",
"GPBUnknownFieldSet.h",
"GPBUtilities.h",
"GPBWellKnownTypes.h",
@ -138,6 +139,7 @@ objc_library(
"GPBType.pbobjc.m",
"GPBUnknownField.m",
"GPBUnknownFieldSet.m",
"GPBUnknownFields.m",
"GPBUtilities.m",
"GPBWellKnownTypes.m",
"GPBWireFormat.m",

@ -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"

@ -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"

@ -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 @@ __attribute__((objc_subclassing_restricted))
/** 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;

@ -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];
}
for (GPBUnknownFieldSet *set in mutableGroupList_) {
[description appendFormat:@"\t%@\n", set];
[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;
}
[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];
}
}

@ -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

@ -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

@ -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

@ -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 */,

@ -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 */,

@ -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 */,

@ -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;

@ -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
Loading…
Cancel
Save