[ObjC] Start of the internal api for `GPBUnknownFields`
Add in the support for pushing the data back onto a `GPBMessage`.
PiperOrigin-RevId: 649125923
diff --git a/objectivec/BUILD.bazel b/objectivec/BUILD.bazel
index 7f154ff..11dd630 100644
--- a/objectivec/BUILD.bazel
+++ b/objectivec/BUILD.bazel
@@ -59,6 +59,10 @@
objc_library(
name = "objectivec",
+ srcs = [
+ # Private headers that aren't used from the generated sources.
+ "GPBUnknownFields_PackagePrivate.h",
+ ],
hdrs = [
"GPBAny.pbobjc.h",
"GPBApi.pbobjc.h",
diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h
index 12908eb..e988992 100644
--- a/objectivec/GPBMessage.h
+++ b/objectivec/GPBMessage.h
@@ -16,6 +16,7 @@
@class GPBExtensionDescriptor;
@class GPBFieldDescriptor;
@class GPBUnknownFieldSet;
+@class GPBUnknownFields;
NS_ASSUME_NONNULL_BEGIN
@@ -502,6 +503,18 @@
**/
- (void)clearUnknownFields;
+/**
+ * Merges in the data from an `GPBUnknownFields`, meaning the data from the unknown fields gets
+ * re-parsed so any known fields will be propertly set.
+ *
+ * If the intent is to replace the message's unknown fields, call `-clearUnknownFields` first.
+ *
+ * @param unknownFields The unknown fields to merge the data from.
+ * @param extensionRegistry The extension registry to use to look up extensions, can be `nil`.
+ **/
+- (void)mergeUnknownFields:(GPBUnknownFields *)unknownFields
+ extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m
index 516f0d7..b2c3ba7 100644
--- a/objectivec/GPBMessage.m
+++ b/objectivec/GPBMessage.m
@@ -22,6 +22,7 @@
#import "GPBExtensionRegistry.h"
#import "GPBRootObject_PackagePrivate.h"
#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUnknownFields_PackagePrivate.h"
#import "GPBUtilities_PackagePrivate.h"
// Returns a new instance that was automatically created by |autocreator| for
@@ -1255,6 +1256,16 @@
self.unknownFields = nil;
}
+- (void)mergeUnknownFields:(GPBUnknownFields *)unknownFields
+ extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry {
+ NSData *data = [unknownFields serializeAsData];
+ if (![self mergeFromData:data extensionRegistry:extensionRegistry error:NULL]) {
+#if defined(DEBUG) && DEBUG
+ NSAssert(0, @"Internal error within the library, failed to parse data from unknown fields.");
+#endif
+ };
+}
+
- (BOOL)isInitialized {
GPBDescriptor *descriptor = [self descriptor];
for (GPBFieldDescriptor *field in descriptor->fields_) {
diff --git a/objectivec/GPBUnknownField.m b/objectivec/GPBUnknownField.m
index 767bc5b..f98de4c 100644
--- a/objectivec/GPBUnknownField.m
+++ b/objectivec/GPBUnknownField.m
@@ -7,10 +7,12 @@
#import "GPBUnknownField.h"
#import "GPBUnknownField_PackagePrivate.h"
+#import "GPBWireFormat.h"
#import "GPBArray.h"
#import "GPBCodedOutputStream_PackagePrivate.h"
#import "GPBUnknownFieldSet.h"
+#import "GPBUnknownFields_PackagePrivate.h"
#define ASSERT_FIELD_TYPE(type) \
if (type_ != type) { \
@@ -287,57 +289,90 @@
}
- (void)writeToOutput:(GPBCodedOutputStream *)output {
- ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
- NSUInteger count = storage_.legacy.mutableVarintList.count;
- if (count > 0) {
- [output writeUInt64Array:number_ values:storage_.legacy.mutableVarintList tag:0];
- }
- count = storage_.legacy.mutableFixed32List.count;
- if (count > 0) {
- [output writeFixed32Array:number_ values:storage_.legacy.mutableFixed32List tag:0];
- }
- count = storage_.legacy.mutableFixed64List.count;
- if (count > 0) {
- [output writeFixed64Array:number_ values:storage_.legacy.mutableFixed64List tag:0];
- }
- count = storage_.legacy.mutableLengthDelimitedList.count;
- if (count > 0) {
- [output writeBytesArray:number_ values:storage_.legacy.mutableLengthDelimitedList];
- }
- count = storage_.legacy.mutableGroupList.count;
- if (count > 0) {
- [output writeUnknownGroupArray:number_ values:storage_.legacy.mutableGroupList];
+ switch (type_) {
+ case GPBUnknownFieldTypeVarint:
+ [output writeUInt64:number_ value:storage_.intValue];
+ break;
+ case GPBUnknownFieldTypeFixed32:
+ [output writeFixed32:number_ value:(uint32_t)storage_.intValue];
+ break;
+ case GPBUnknownFieldTypeFixed64:
+ [output writeFixed64:number_ value:storage_.intValue];
+ break;
+ case GPBUnknownFieldTypeLengthDelimited:
+ [output writeBytes:number_ value:storage_.lengthDelimited];
+ break;
+ case GPBUnknownFieldTypeGroup:
+ [output writeRawVarint32:GPBWireFormatMakeTag(number_, GPBWireFormatStartGroup)];
+ [storage_.group writeToCodedOutputStream:output];
+ [output writeRawVarint32:GPBWireFormatMakeTag(number_, GPBWireFormatEndGroup)];
+ break;
+ case GPBUnknownFieldTypeLegacy: {
+ NSUInteger count = storage_.legacy.mutableVarintList.count;
+ if (count > 0) {
+ [output writeUInt64Array:number_ values:storage_.legacy.mutableVarintList tag:0];
+ }
+ count = storage_.legacy.mutableFixed32List.count;
+ if (count > 0) {
+ [output writeFixed32Array:number_ values:storage_.legacy.mutableFixed32List tag:0];
+ }
+ count = storage_.legacy.mutableFixed64List.count;
+ if (count > 0) {
+ [output writeFixed64Array:number_ values:storage_.legacy.mutableFixed64List tag:0];
+ }
+ count = storage_.legacy.mutableLengthDelimitedList.count;
+ if (count > 0) {
+ [output writeBytesArray:number_ values:storage_.legacy.mutableLengthDelimitedList];
+ }
+ count = storage_.legacy.mutableGroupList.count;
+ if (count > 0) {
+ [output writeUnknownGroupArray:number_ values:storage_.legacy.mutableGroupList];
+ }
+ }
}
}
- (size_t)serializedSize {
- ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLegacy);
- __block size_t result = 0;
- int32_t number = number_;
- [storage_.legacy.mutableVarintList
- enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
- result += GPBComputeUInt64Size(number, value);
- }];
+ switch (type_) {
+ case GPBUnknownFieldTypeVarint:
+ return GPBComputeUInt64Size(number_, storage_.intValue);
+ case GPBUnknownFieldTypeFixed32:
+ return GPBComputeFixed32Size(number_, (uint32_t)storage_.intValue);
+ case GPBUnknownFieldTypeFixed64:
+ return GPBComputeFixed64Size(number_, storage_.intValue);
+ case GPBUnknownFieldTypeLengthDelimited:
+ return GPBComputeBytesSize(number_, storage_.lengthDelimited);
+ case GPBUnknownFieldTypeGroup:
+ return (GPBComputeTagSize(number_) * 2) + [storage_.group serializedSize];
+ case GPBUnknownFieldTypeLegacy: {
+ __block size_t result = 0;
+ int32_t number = number_;
+ [storage_.legacy.mutableVarintList
+ enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
+ result += GPBComputeUInt64Size(number, value);
+ }];
- [storage_.legacy.mutableFixed32List
- enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
- result += GPBComputeFixed32Size(number, value);
- }];
+ [storage_.legacy.mutableFixed32List
+ enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
+ result += GPBComputeFixed32Size(number, value);
+ }];
- [storage_.legacy.mutableFixed64List
- enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
- result += GPBComputeFixed64Size(number, value);
- }];
+ [storage_.legacy.mutableFixed64List
+ enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
+ result += GPBComputeFixed64Size(number, value);
+ }];
- for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
- result += GPBComputeBytesSize(number, data);
+ for (NSData *data in storage_.legacy.mutableLengthDelimitedList) {
+ result += GPBComputeBytesSize(number, data);
+ }
+
+ for (GPBUnknownFieldSet *set in storage_.legacy.mutableGroupList) {
+ result += GPBComputeUnknownGroupSize(number, set);
+ }
+
+ return result;
+ }
}
-
- for (GPBUnknownFieldSet *set in storage_.legacy.mutableGroupList) {
- result += GPBComputeUnknownGroupSize(number, set);
- }
-
- return result;
}
- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output {
diff --git a/objectivec/GPBUnknownFields.m b/objectivec/GPBUnknownFields.m
index aed1bc9..8856ac5 100644
--- a/objectivec/GPBUnknownFields.m
+++ b/objectivec/GPBUnknownFields.m
@@ -6,6 +6,8 @@
// https://developers.google.com/open-source/licenses/bsd
#import "GPBUnknownFields.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBCodedOutputStream_PackagePrivate.h"
#import "GPBUnknownField_PackagePrivate.h"
#define CHECK_FIELD_NUMBER(number) \
@@ -137,6 +139,44 @@
return [fields_ countByEnumeratingWithState:state objects:stackbuf count:len];
}
+#pragma mark - Internal Methods
+
+- (size_t)serializedSize {
+ size_t result = 0;
+ for (GPBUnknownField *field in self->fields_) {
+ result += [field serializedSize];
+ }
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output {
+ for (GPBUnknownField *field in fields_) {
+ [field writeToOutput:output];
+ }
+}
+
+- (NSData *)serializeAsData {
+ if (fields_.count == 0) {
+ return [NSData data];
+ }
+ size_t expectedSize = [self serializedSize];
+ NSMutableData *data = [NSMutableData dataWithLength:expectedSize];
+ GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data];
+ @try {
+ [self writeToCodedOutputStream:stream];
+ [stream flush];
+ } @catch (NSException *exception) {
+#if defined(DEBUG) && DEBUG
+ NSLog(@"Internal exception while building GPBUnknownFields serialized data: %@", exception);
+#endif
+ }
+#if defined(DEBUG) && DEBUG
+ NSAssert([stream bytesWritten] == expectedSize, @"Internal error within the library");
+#endif
+ [stream release];
+ return data;
+}
+
@end
@implementation GPBUnknownFields (AccessHelpers)
diff --git a/objectivec/GPBUnknownFields_PackagePrivate.h b/objectivec/GPBUnknownFields_PackagePrivate.h
new file mode 100644
index 0000000..dc63d3a
--- /dev/null
+++ b/objectivec/GPBUnknownFields_PackagePrivate.h
@@ -0,0 +1,20 @@
+// 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>
+
+#import "GPBUnknownFields.h"
+
+@class GPBCodedOutputStream;
+
+@interface GPBUnknownFields ()
+
+- (size_t)serializedSize;
+- (nonnull NSData *)serializeAsData;
+- (void)writeToCodedOutputStream:(nonnull GPBCodedOutputStream *)output;
+
+@end
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
index 32bfb22..850e26b 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
@@ -76,6 +76,7 @@
F43ADD432C2F381F005312E5 /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD422C2F381F005312E5 /* GPBCompileTest25.m */; };
F43ADD502C333D6C005312E5 /* GPBUnknownFields+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD4F2C333D6B005312E5 /* GPBUnknownFields+Additions.swift */; };
F43ADD562C345CED005312E5 /* GPBUnknownField+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD552C345CED005312E5 /* GPBUnknownField+Additions.swift */; };
+ F43ADD5C2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD5B2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h */; };
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 */; };
@@ -218,6 +219,7 @@
F43ADD422C2F381F005312E5 /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
F43ADD4F2C333D6B005312E5 /* GPBUnknownFields+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownFields+Additions.swift"; sourceTree = "<group>"; };
F43ADD552C345CED005312E5 /* GPBUnknownField+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownField+Additions.swift"; sourceTree = "<group>"; };
+ F43ADD5B2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields_PackagePrivate.h; 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; };
@@ -422,6 +424,7 @@
7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */,
7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */,
F43ADD552C345CED005312E5 /* GPBUnknownField+Additions.swift */,
+ F43ADD5B2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h */,
F43ADD2F2C2F2B91005312E5 /* GPBUnknownFields.h */,
F43ADD2E2C2F2B91005312E5 /* GPBUnknownFields.m */,
F43ADD4F2C333D6B005312E5 /* GPBUnknownFields+Additions.swift */,
@@ -582,6 +585,7 @@
buildActionMask = 2147483647;
files = (
F43ADD312C2F2B91005312E5 /* GPBUnknownFields.h in Headers */,
+ F43ADD5C2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
index a01147a..63516bf 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -75,6 +75,7 @@
F43ADD472C2F387A005312E5 /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD462C2F387A005312E5 /* GPBCompileTest25.m */; };
F43ADD522C333E58005312E5 /* GPBUnknownFields+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD512C333E58005312E5 /* GPBUnknownFields+Additions.swift */; };
F43ADD582C345D0D005312E5 /* GPBUnknownField+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD572C345D0D005312E5 /* GPBUnknownField+Additions.swift */; };
+ F43ADD5E2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD5D2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h */; };
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 */; };
@@ -218,6 +219,7 @@
F43ADD462C2F387A005312E5 /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
F43ADD512C333E58005312E5 /* GPBUnknownFields+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownFields+Additions.swift"; sourceTree = "<group>"; };
F43ADD572C345D0D005312E5 /* GPBUnknownField+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownField+Additions.swift"; sourceTree = "<group>"; };
+ F43ADD5D2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields_PackagePrivate.h; 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; };
@@ -427,6 +429,7 @@
7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */,
7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */,
F43ADD572C345D0D005312E5 /* GPBUnknownField+Additions.swift */,
+ F43ADD5D2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h */,
F43ADD372C2F2D06005312E5 /* GPBUnknownFields.h */,
F43ADD362C2F2D06005312E5 /* GPBUnknownFields.m */,
F43ADD512C333E58005312E5 /* GPBUnknownFields+Additions.swift */,
@@ -586,6 +589,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ F43ADD5E2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
index 76c4466..7910048 100644
--- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
@@ -76,6 +76,7 @@
F43ADD492C2F389D005312E5 /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD482C2F389D005312E5 /* GPBCompileTest25.m */; };
F43ADD542C333EE5005312E5 /* GPBUnknownFields+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD532C333EE5005312E5 /* GPBUnknownFields+Additions.swift */; };
F43ADD5A2C345D36005312E5 /* GPBUnknownField+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD592C345D36005312E5 /* GPBUnknownField+Additions.swift */; };
+ F43ADD602C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD5F2C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h */; };
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 */; };
@@ -219,6 +220,7 @@
F43ADD482C2F389D005312E5 /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
F43ADD532C333EE5005312E5 /* GPBUnknownFields+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownFields+Additions.swift"; sourceTree = "<group>"; };
F43ADD592C345D36005312E5 /* GPBUnknownField+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownField+Additions.swift"; sourceTree = "<group>"; };
+ F43ADD5F2C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields_PackagePrivate.h; 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; };
@@ -428,6 +430,7 @@
7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */,
7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */,
F43ADD592C345D36005312E5 /* GPBUnknownField+Additions.swift */,
+ F43ADD5F2C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h */,
F43ADD3C2C2F2D3D005312E5 /* GPBUnknownFields.h */,
F43ADD3B2C2F2D3D005312E5 /* GPBUnknownFields.m */,
F43ADD532C333EE5005312E5 /* GPBUnknownFields+Additions.swift */,
@@ -588,6 +591,7 @@
buildActionMask = 2147483647;
files = (
F43ADD3E2C2F2D3D005312E5 /* GPBUnknownFields.h in Headers */,
+ F43ADD602C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h
index 1072f88..03ac8f9 100644
--- a/objectivec/Tests/GPBTestUtilities.h
+++ b/objectivec/Tests/GPBTestUtilities.h
@@ -20,6 +20,22 @@
return [NSData dataWithBytes:str length:strlen(str)];
}
+static inline NSData *_DataFromBytesInternal(int32_t unused, ...) {
+ NSMutableData *values = [NSMutableData dataWithCapacity:0];
+ va_list list;
+ va_start(list, unused);
+ int32_t n;
+ while ((n = va_arg(list, int32_t)) != 256) {
+ NSCAssert(n >= 0 && n < 256, @"Only 8 bit values");
+ uint8_t u = (uint8_t)n;
+ [values appendBytes:&u length:1];
+ }
+ va_end(list);
+ return values;
+}
+
+#define DataFromBytes(...) _DataFromBytesInternal(0, __VA_ARGS__, 256)
+
// Helper for uses of C arrays in tests cases.
#ifndef GPBARRAYSIZE
#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
diff --git a/objectivec/Tests/GPBUnknownFieldsTest.m b/objectivec/Tests/GPBUnknownFieldsTest.m
index 552c21d..01f3668 100644
--- a/objectivec/Tests/GPBUnknownFieldsTest.m
+++ b/objectivec/Tests/GPBUnknownFieldsTest.m
@@ -5,9 +5,12 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
+#import <Foundation/Foundation.h>
+
#import "GPBTestUtilities.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFields.h"
+#import "GPBUnknownFields_PackagePrivate.h"
#import "objectivec/Tests/Unittest.pbobjc.h"
@interface UnknownFieldsTest : GPBTestCase
@@ -511,4 +514,66 @@
XCTAssertThrowsSpecificNamed([ufs fields:-1], NSException, NSInvalidArgumentException);
}
+- (void)testSerialize {
+ // Don't need to test CodedOutputStream, just make sure things basically end up there.
+ {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ XCTAssertEqualObjects([ufs serializeAsData], [NSData data]);
+ }
+ {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addFieldNumber:1 varint:1];
+ XCTAssertEqualObjects([ufs serializeAsData], DataFromBytes(0x08, 0x01));
+ }
+ {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addFieldNumber:1 fixed32:1];
+ XCTAssertEqualObjects([ufs serializeAsData], DataFromBytes(0x0d, 0x01, 0x00, 0x00, 0x00));
+ }
+ {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addFieldNumber:1 fixed64:1];
+ XCTAssertEqualObjects([ufs serializeAsData],
+ DataFromBytes(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
+ }
+ {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")];
+ XCTAssertEqualObjects([ufs serializeAsData], DataFromBytes(0x0a, 0x03, 0x66, 0x6f, 0x6f));
+ }
+ {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addGroupWithFieldNumber:1]; // Empty group
+ XCTAssertEqualObjects([ufs serializeAsData], DataFromBytes(0x0b, 0x0c));
+ }
+ {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ GPBUnknownFields* group = [ufs addGroupWithFieldNumber:1]; // With some fields
+ [group addFieldNumber:10 varint:10];
+ [group addFieldNumber:11 fixed32:32];
+ [group addFieldNumber:12 fixed32:32];
+ XCTAssertEqualObjects([ufs serializeAsData],
+ DataFromBytes(0x0b, 0x50, 0x0a, 0x5d, 0x20, 0x00, 0x00, 0x00, 0x65, 0x20,
+ 0x00, 0x00, 0x00, 0x0c));
+ }
+}
+
+- (void)testMessageMergeUnknowns {
+ GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
+ [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalInt64 varint:100];
+ [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalFixed32 fixed32:200];
+ [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalFixed64 fixed64:300];
+ [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalBytes lengthDelimited:DataFromCStr("foo")];
+ GPBUnknownFields* group = [ufs addGroupWithFieldNumber:TestAllTypes_FieldNumber_OptionalGroup];
+ [group addFieldNumber:TestAllTypes_OptionalGroup_FieldNumber_A varint:55];
+
+ TestAllTypes* msg = [TestAllTypes message];
+ [msg mergeUnknownFields:ufs extensionRegistry:nil];
+ XCTAssertEqual(msg.optionalInt64, 100);
+ XCTAssertEqual(msg.optionalFixed32, 200);
+ XCTAssertEqual(msg.optionalFixed64, 300);
+ XCTAssertEqualObjects(msg.optionalBytes, DataFromCStr("foo"));
+ XCTAssertEqual(msg.optionalGroup.a, 55);
+}
+
@end