Merge pull request #17587 from thomasvl/patch_objc_to_28

CherryPick the newer work for Objective-C over the the 28 branch.
pull/17618/head
zhangskz 4 months ago committed by GitHub
commit b045935521
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      conformance/failure_list_objc.txt
  2. 90
      objectivec/GPBCodedInputStream.m
  3. 4
      objectivec/GPBCodedInputStream_PackagePrivate.h
  4. 16
      objectivec/GPBDescriptor.m
  5. 596
      objectivec/GPBMessage.m
  6. 13
      objectivec/GPBMessage_PackagePrivate.h
  7. 21
      objectivec/GPBUnknownFieldSet.m
  8. 6
      objectivec/GPBUnknownFieldSet_PackagePrivate.h
  9. 11
      objectivec/GPBUnknownFields.m
  10. 4
      objectivec/GPBUtilities.h
  11. 84
      objectivec/GPBUtilities.m
  12. 143
      objectivec/Tests/GPBCodedInputStreamTests.m
  13. 17
      objectivec/Tests/GPBMessageTests+Serialization.m
  14. 107
      objectivec/Tests/GPBMessageTests.m
  15. 179
      objectivec/Tests/GPBUnknownFieldSetTest.m
  16. 159
      objectivec/Tests/GPBUnknownFieldsTest.m
  17. 93
      objectivec/Tests/GPBUtilitiesTests.m
  18. 117
      objectivec/Tests/GPBWireFormatTests.m
  19. 10
      objectivec/Tests/unittest_mset.proto
  20. 31
      objectivec/Tests/unittest_objc.proto
  21. 8
      src/google/protobuf/compiler/objectivec/extension.cc
  22. 6
      src/google/protobuf/compiler/objectivec/message.cc

@ -1,7 +1,2 @@
# JSON input or output tests are skipped (in conformance_objc.m) as mobile
# platforms don't support JSON wire format to avoid code bloat.
Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput
Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput
Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput
Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput

@ -13,6 +13,10 @@
#import "GPBUtilities_PackagePrivate.h"
#import "GPBWireFormat.h"
// TODO: Consider using on other functions to reduce bloat when
// some compiler optimizations are enabled.
#define GPB_NOINLINE __attribute__((noinline))
NSString *const GPBCodedInputStreamException = GPBNSStringifySymbol(GPBCodedInputStreamException);
NSString *const GPBCodedInputStreamUnderlyingErrorKey =
@ -28,7 +32,8 @@ NSString *const GPBCodedInputStreamErrorDomain =
// int CodedInputStream::default_recursion_limit_ = 100;
static const NSUInteger kDefaultRecursionLimit = 100;
static void RaiseException(NSInteger code, NSString *reason) {
GPB_NOINLINE
void GPBRaiseStreamError(NSInteger code, NSString *reason) {
NSDictionary *errorInfo = nil;
if ([reason length]) {
errorInfo = @{GPBErrorReasonKey : reason};
@ -44,7 +49,7 @@ static void RaiseException(NSInteger code, NSString *reason) {
GPB_INLINE void CheckRecursionLimit(GPBCodedInputStreamState *state) {
if (state->recursionDepth >= kDefaultRecursionLimit) {
RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
GPBRaiseStreamError(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
}
}
@ -56,19 +61,19 @@ GPB_INLINE void CheckFieldSize(uint64_t size) {
if (size > 0x7fffffff) {
// TODO: Maybe a different error code for this, but adding one is a breaking
// change so reuse an existing one.
RaiseException(GPBCodedInputStreamErrorInvalidSize, nil);
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSize, nil);
}
}
static void CheckSize(GPBCodedInputStreamState *state, size_t size) {
size_t newSize = state->bufferPos + size;
if (newSize > state->bufferSize) {
RaiseException(GPBCodedInputStreamErrorInvalidSize, nil);
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSize, nil);
}
if (newSize > state->currentLimit) {
// Fast forward to end of currentLimit;
state->bufferPos = state->currentLimit;
RaiseException(GPBCodedInputStreamErrorSubsectionLimitReached, nil);
GPBRaiseStreamError(GPBCodedInputStreamErrorSubsectionLimitReached, nil);
}
}
@ -110,7 +115,7 @@ static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
}
shift += 7;
}
RaiseException(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64");
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64");
return 0;
}
@ -201,11 +206,11 @@ int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) {
state->lastTag = ReadRawVarint32(state);
// Tags have to include a valid wireformat.
if (!GPBWireFormatIsValidTag(state->lastTag)) {
RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Invalid wireformat in tag.");
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Invalid wireformat in tag.");
}
// Zero is not a valid field number.
if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) {
RaiseException(GPBCodedInputStreamErrorInvalidTag,
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag,
@"A zero field number on the wire is invalid.");
}
return state->lastTag;
@ -231,7 +236,7 @@ NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state)
NSLog(@"UTF-8 failure, is some field type 'string' when it should be "
@"'bytes'?");
#endif
RaiseException(GPBCodedInputStreamErrorInvalidUTF8, nil);
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidUTF8, nil);
}
}
return result;
@ -262,11 +267,65 @@ NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *sta
return result;
}
static void SkipToEndGroupInternal(GPBCodedInputStreamState *state, uint32_t endGroupTag) {
CheckRecursionLimit(state);
++state->recursionDepth;
while (YES) {
uint32_t tag = GPBCodedInputStreamReadTag(state);
if (tag == endGroupTag || tag == 0) {
GPBCodedInputStreamCheckLastTagWas(state, endGroupTag); // Will fail for end of input.
--state->recursionDepth;
return;
}
switch (GPBWireFormatGetTagWireType(tag)) {
case GPBWireFormatVarint:
(void)ReadRawVarint64(state);
break;
case GPBWireFormatFixed64:
SkipRawData(state, sizeof(uint64_t));
break;
case GPBWireFormatLengthDelimited: {
uint64_t size = ReadRawVarint64(state);
CheckFieldSize(size);
size_t size2 = (size_t)size; // Cast safe on 32bit because of CheckFieldSize() above.
SkipRawData(state, size2);
break;
}
case GPBWireFormatStartGroup:
SkipToEndGroupInternal(state, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag),
GPBWireFormatEndGroup));
break;
case GPBWireFormatEndGroup:
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unmatched end group");
break;
case GPBWireFormatFixed32:
SkipRawData(state, sizeof(uint32_t));
break;
}
}
}
// This doesn't include the start group, but it collects all bytes until the end group including
// the end group tag.
NSData *GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(GPBCodedInputStreamState *state,
int32_t fieldNumber) {
// Better have just read the start of the group.
GPBCodedInputStreamCheckLastTagWas(state,
GPBWireFormatMakeTag(fieldNumber, GPBWireFormatStartGroup));
const uint8_t *start = state->bytes + state->bufferPos;
SkipToEndGroupInternal(state, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
// This will be after the end group tag.
const uint8_t *end = state->bytes + state->bufferPos;
return [[NSData alloc] initWithBytesNoCopy:(void *)start
length:(NSUInteger)(end - start)
freeWhenDone:NO];
}
size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit) {
byteLimit += state->bufferPos;
size_t oldLimit = state->currentLimit;
if (byteLimit > oldLimit) {
RaiseException(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil);
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil);
}
state->currentLimit = byteLimit;
return oldLimit;
@ -286,7 +345,7 @@ BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) {
void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, int32_t value) {
if (state->lastTag != value) {
RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read");
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read");
}
}
@ -429,9 +488,9 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, int32_t
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
CheckRecursionLimit(&state_);
++state_.recursionDepth;
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
GPBCodedInputStreamCheckLastTagWas(&state_,
GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
[message mergeFromCodedInputStream:self
extensionRegistry:extensionRegistry
endingTag:GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)];
--state_.recursionDepth;
}
@ -452,8 +511,7 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, int32_t
size_t length2 = (size_t)length; // Cast safe on 32bit because of CheckFieldSize() above.
size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length2);
++state_.recursionDepth;
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
GPBCodedInputStreamCheckLastTagWas(&state_, 0);
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry endingTag:0];
--state_.recursionDepth;
GPBCodedInputStreamPopLimit(&state_, oldLimit);
}

@ -53,6 +53,7 @@ typedef struct GPBCodedInputStreamState {
CF_EXTERN_C_BEGIN
void GPBRaiseStreamError(NSInteger code, NSString *reason);
int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state);
double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state);
@ -75,6 +76,9 @@ NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state)
__attribute((ns_returns_retained));
NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *state)
__attribute((ns_returns_retained));
NSData *GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(GPBCodedInputStreamState *state,
int32_t fieldNumber)
__attribute((ns_returns_retained));
size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit);
void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, size_t oldLimit);

@ -267,6 +267,10 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, NSArray *allMessageField
fields:(NSArray *)fields
storageSize:(uint32_t)storageSize
wireFormat:(BOOL)wireFormat {
#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
// This is also checked by the generator.
NSAssert(!wireFormat || fields.count == 0, @"Internal error: MessageSets should not have fields");
#endif
if ((self = [super init])) {
messageClass_ = messageClass;
messageName_ = [messageName copy];
@ -1139,8 +1143,18 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
GPBRuntimeMatchFailure();
}
#if defined(DEBUG) && DEBUG
#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
NSAssert(usesClassRefs, @"Internal error: all extensions should have class refs");
// These are also checked by the generator.
if ((desc->options & GPBExtensionSetWireFormat) != 0) {
NSAssert(desc->dataType == GPBDataTypeMessage,
@"Internal error: If a MessageSet extension is set, the data type must be a message.");
NSAssert((desc->options & GPBExtensionRepeated) == 0,
@"Internal Error: MessageSet extension can't be repeated.");
// NOTE: Could also check that the exteneded class is a MessageSet, but that would force the
// ObjC runtime to start up that class and that isn't desirable here.
}
#endif
if ((self = [super init])) {

@ -5,9 +5,9 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#import <Foundation/Foundation.h>
#import "GPBMessage_PackagePrivate.h"
#import "GPBMessage.h"
#import <Foundation/Foundation.h>
#import <objc/message.h>
#import <objc/runtime.h>
#import <os/lock.h>
@ -20,11 +20,18 @@
#import "GPBDictionary_PackagePrivate.h"
#import "GPBExtensionInternals.h"
#import "GPBExtensionRegistry.h"
#import "GPBMessage_PackagePrivate.h"
#import "GPBRootObject_PackagePrivate.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFieldSet.h"
#import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownFields_PackagePrivate.h"
#import "GPBUtilities_PackagePrivate.h"
// TODO: Consider using on other functions to reduce bloat when
// some compiler optimizations are enabled.
#define GPB_NOINLINE __attribute__((noinline))
// Returns a new instance that was automatically created by |autocreator| for
// its field |field|.
static GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, GPBMessage *autocreator,
@ -64,7 +71,16 @@ NSString *const GPBMessageExceptionMessageTooLarge =
@interface GPBMessage () {
@package
// Only one of these two is ever set, GPBUnknownFieldSet is being deprecated and will
// eventually be removed, but because that api support mutation, once the property is
// fetch it must continue to be used so any mutations will be honored in future operations
// on the message.
// Read only operations that access these two/cause things to migration between them should
// be protected with an @synchronized(self) block (that way the code also doesn't have to
// worry about throws).
NSMutableData *unknownFieldData_;
GPBUnknownFieldSet *unknownFields_;
NSMutableDictionary *extensionMap_;
// Readonly access to autocreatedExtensionMap_ is protected via readOnlyLock_.
NSMutableDictionary *autocreatedExtensionMap_;
@ -103,7 +119,6 @@ static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *fiel
static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone)
__attribute__((ns_returns_retained));
static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self);
#if defined(DEBUG) && DEBUG
static NSError *MessageError(NSInteger code, NSDictionary *userInfo) {
@ -133,6 +148,178 @@ static NSError *ErrorFromException(NSException *exception) {
return error;
}
// Helper to encode varints onto the mutable data, the max size need is 10 bytes.
GPB_NOINLINE
static uint8_t *EncodeVarintU64(uint64_t val, uint8_t *ptr) {
do {
uint8_t byte = val & 0x7fU;
val >>= 7;
if (val) byte |= 0x80U;
*(ptr++) = byte;
} while (val);
return ptr;
}
// Helper to encode varints onto the mutable data, the max size need is 5 bytes.
GPB_NOINLINE
static uint8_t *EncodeVarintU32(uint32_t val, uint8_t *ptr) {
do {
uint8_t byte = val & 0x7fU;
val >>= 7;
if (val) byte |= 0x80U;
*(ptr++) = byte;
} while (val);
return ptr;
}
// Helper to encode signed int32 values as varints onto the mutable data, the max size need is 10
// bytes.
GPB_NOINLINE
static uint8_t *EncodeVarintS32(int32_t val, uint8_t *ptr) {
if (val >= 0) {
return EncodeVarintU32((uint32_t)val, ptr);
} else {
// Must sign-extend
int64_t extended = val;
return EncodeVarintU64((uint64_t)extended, ptr);
}
}
GPB_NOINLINE
static void AddUnknownFieldVarint32(GPBMessage *self, uint32_t fieldNumber, int32_t value) {
if (self->unknownFields_) {
[self->unknownFields_ mergeVarintField:fieldNumber value:value];
return;
}
uint8_t buf[20];
uint8_t *ptr = buf;
ptr = EncodeVarintU32(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint), ptr);
ptr = EncodeVarintS32(value, ptr);
if (self->unknownFieldData_ == nil) {
self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:ptr - buf];
GPBBecomeVisibleToAutocreator(self);
}
[self->unknownFieldData_ appendBytes:buf length:ptr - buf];
}
GPB_NOINLINE
static void AddUnknownFieldLengthDelimited(GPBMessage *self, uint32_t fieldNumber, NSData *value) {
if (self->unknownFields_) {
[self->unknownFields_ mergeLengthDelimited:fieldNumber value:value];
return;
}
uint8_t buf[20];
uint8_t *ptr = buf;
ptr = EncodeVarintU32(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatLengthDelimited), ptr);
ptr = EncodeVarintU64((uint64_t)value.length, ptr);
if (self->unknownFieldData_ == nil) {
self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:(ptr - buf) + value.length];
GPBBecomeVisibleToAutocreator(self);
}
[self->unknownFieldData_ appendBytes:buf length:ptr - buf];
[self->unknownFieldData_ appendData:value];
}
GPB_NOINLINE
static void AddUnknownMessageSetEntry(GPBMessage *self, uint32_t typeId, NSData *value) {
if (self->unknownFields_) {
// Legacy Set does this odd storage for MessageSet.
[self->unknownFields_ mergeLengthDelimited:typeId value:value];
return;
}
uint8_t buf[60];
uint8_t *ptr = buf;
ptr = EncodeVarintU32(GPBWireFormatMessageSetItemTag, ptr);
ptr = EncodeVarintU32(GPBWireFormatMessageSetTypeIdTag, ptr);
ptr = EncodeVarintU32(typeId, ptr);
ptr = EncodeVarintU32(GPBWireFormatMessageSetMessageTag, ptr);
ptr = EncodeVarintU64((uint64_t)value.length, ptr);
uint8_t *split = ptr;
ptr = EncodeVarintU32(GPBWireFormatMessageSetItemEndTag, ptr);
uint8_t *end = ptr;
if (self->unknownFieldData_ == nil) {
self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:(end - buf) + value.length];
GPBBecomeVisibleToAutocreator(self);
}
[self->unknownFieldData_ appendBytes:buf length:split - buf];
[self->unknownFieldData_ appendData:value];
[self->unknownFieldData_ appendBytes:split length:end - split];
}
GPB_NOINLINE
static void ParseUnknownField(GPBMessage *self, uint32_t tag, GPBCodedInputStream *input) {
if (self->unknownFields_) {
if (![self->unknownFields_ mergeFieldFrom:tag input:input]) {
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected end-group tag");
}
return;
}
uint8_t buf[20];
uint8_t *ptr = buf;
ptr = EncodeVarintU32(tag, ptr); // All will need the tag
NSData *bytesToAppend = nil;
GPBCodedInputStreamState *state = &input->state_;
switch (GPBWireFormatGetTagWireType(tag)) {
case GPBWireFormatVarint: {
ptr = EncodeVarintU64(GPBCodedInputStreamReadUInt64(state), ptr);
break;
}
case GPBWireFormatFixed64: {
uint64_t value = GPBCodedInputStreamReadFixed64(state);
*(ptr++) = (uint8_t)(value) & 0xFF;
*(ptr++) = (uint8_t)(value >> 8) & 0xFF;
*(ptr++) = (uint8_t)(value >> 16) & 0xFF;
*(ptr++) = (uint8_t)(value >> 24) & 0xFF;
*(ptr++) = (uint8_t)(value >> 32) & 0xFF;
*(ptr++) = (uint8_t)(value >> 40) & 0xFF;
*(ptr++) = (uint8_t)(value >> 48) & 0xFF;
*(ptr++) = (uint8_t)(value >> 56) & 0xFF;
break;
}
case GPBWireFormatLengthDelimited: {
bytesToAppend = GPBCodedInputStreamReadRetainedBytes(state);
ptr = EncodeVarintU64((uint64_t)bytesToAppend.length, ptr);
break;
}
case GPBWireFormatStartGroup: {
bytesToAppend = GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(
state, GPBWireFormatGetTagFieldNumber(tag));
break;
}
case GPBWireFormatEndGroup:
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected end-group tag");
break;
case GPBWireFormatFixed32: {
uint32_t value = GPBCodedInputStreamReadFixed32(state);
*(ptr++) = (uint8_t)(value) & 0xFF;
*(ptr++) = (uint8_t)(value >> 8) & 0xFF;
*(ptr++) = (uint8_t)(value >> 16) & 0xFF;
*(ptr++) = (uint8_t)(value >> 24) & 0xFF;
break;
}
}
if (self->unknownFieldData_ == nil) {
self->unknownFieldData_ =
[[NSMutableData alloc] initWithCapacity:(ptr - buf) + bytesToAppend.length];
GPBBecomeVisibleToAutocreator(self);
}
[self->unknownFieldData_ appendBytes:buf length:ptr - buf];
if (bytesToAppend) {
[self->unknownFieldData_ appendData:bytesToAppend];
[bytesToAppend release];
}
}
static void CheckExtension(GPBMessage *self, GPBExtensionDescriptor *extension) {
if (![self isKindOfClass:extension.containingMessageClass]) {
[NSException raise:NSInvalidArgumentException
@ -729,8 +916,7 @@ static void DecodeSingleValueFromInputStream(GPBExtensionDescriptor *extension,
if (!enumDescriptor.isClosed || enumDescriptor.enumVerifier(val)) {
nsValue = [[NSNumber alloc] initWithInt:val];
} else {
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(messageToGetExtension);
[unknownFields mergeVarintField:extension->description_->fieldNumber value:val];
AddUnknownFieldVarint32(messageToGetExtension, extension->description_->fieldNumber, val);
nsValue = nil;
}
break;
@ -743,14 +929,12 @@ static void DecodeSingleValueFromInputStream(GPBExtensionDescriptor *extension,
extensionRegistry:extensionRegistry];
} else {
// description->dataType == GPBDataTypeMessage
if (GPBExtensionIsWireFormat(description)) {
// For MessageSet fields the message length will have already been
// read.
[targetMessage mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
} else {
#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
NSCAssert(!GPBExtensionIsWireFormat(description),
@"Internal error: got a MessageSet extension when not expected.");
#endif
[input readMessage:targetMessage extensionRegistry:extensionRegistry];
}
}
// Nothing to add below since the caller provided the message (and added it).
nsValue = nil;
break;
@ -922,12 +1106,50 @@ void GPBClearMessageAutocreator(GPBMessage *self) {
self->autocreatorExtension_ = nil;
}
static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
if (!self->unknownFields_) {
self->unknownFields_ = [[GPBUnknownFieldSet alloc] init];
GPBBecomeVisibleToAutocreator(self);
GPB_NOINLINE
static void MergeUnknownFieldDataIntoFieldSet(GPBMessage *self, NSData *data,
GPBUnknownFieldSet *targetSet) {
GPBUnknownFieldSet *unknownFields = targetSet ? targetSet : self->unknownFields_;
#if defined(DEBUG) && DEBUG
NSCAssert(unknownFields != nil, @"Internal error: unknown fields not initialized.");
#endif
BOOL isMessageSet = self.descriptor.isWireFormat;
GPBUnknownFieldSet *decodeInto = isMessageSet ? [[GPBUnknownFieldSet alloc] init] : unknownFields;
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
@try {
[decodeInto mergeFromCodedInputStream:input];
} @catch (NSException *exception) {
#if defined(DEBUG) && DEBUG
NSLog(@"%@: Internal exception while parsing the unknown fields into a Set: %@", [self class],
exception);
#endif
}
[input release];
if (isMessageSet) {
// Need to transform the groups back into how Message feeds the data into a MessageSet when
// doing a full MessageSet based decode.
GPBUnknownField *groupField = [decodeInto getField:GPBWireFormatMessageSetItem];
for (GPBUnknownFieldSet *group in groupField.groupList) {
GPBUnknownField *typeIdField = [group getField:GPBWireFormatMessageSetTypeId];
GPBUnknownField *messageField = [group getField:GPBWireFormatMessageSetMessage];
if (typeIdField.varintList.count != 1 || messageField.lengthDelimitedList.count != 1) {
#if defined(DEBUG) && DEBUG
NSCAssert(NO, @"Internal error: MessageSet group missing typeId or message.");
#endif
continue;
}
int32_t fieldNumber = (int32_t)[typeIdField.varintList valueAtIndex:0];
GPBUnknownField *messageSetField = [[GPBUnknownField alloc] initWithNumber:fieldNumber];
[messageSetField addLengthDelimited:messageField.lengthDelimitedList[0]];
[unknownFields addField:messageSetField];
[messageSetField release];
}
[decodeInto release];
}
return self->unknownFields_;
}
@implementation GPBMessage
@ -1027,7 +1249,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
error:(NSError **)errorPtr {
if ((self = [self init])) {
@try {
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
if (errorPtr) {
*errorPtr = nil;
}
@ -1164,8 +1386,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init];
[self copyFieldsInto:result zone:zone descriptor:descriptor];
// Make immutable copies of the extra bits.
@synchronized(self) {
result->unknownFields_ = [unknownFields_ copyWithZone:zone];
result->unknownFieldData_ = [unknownFieldData_ mutableCopyWithZone:zone];
}
result->extensionMap_ = CloneExtensionMap(extensionMap_, zone);
return result;
}
@ -1239,6 +1465,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
[extensionMap_ release];
extensionMap_ = nil;
[unknownFieldData_ release];
unknownFieldData_ = nil;
[unknownFields_ release];
unknownFields_ = nil;
@ -1442,12 +1670,21 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
sortedExtensions:sortedExtensions];
}
}
@synchronized(self) {
if (unknownFieldData_) {
#if defined(DEBUG) && DEBUG
NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set");
#endif
[output writeRawData:unknownFieldData_];
} else {
if (descriptor.isWireFormat) {
[unknownFields_ writeAsMessageSetTo:output];
} else {
[unknownFields_ writeToCodedOutputStream:output];
}
}
} // @synchronized(self)
}
- (void)writeDelimitedToOutputStream:(NSOutputStream *)output {
GPBCodedOutputStream *codedOutput = [[GPBCodedOutputStream alloc] initWithOutputStream:output];
@ -2078,8 +2315,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
- (void)mergeFromData:(NSData *)data extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
@try {
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
[input checkLastTagWas:0];
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
} @finally {
[input release];
}
@ -2088,9 +2324,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
- (BOOL)mergeFromData:(NSData *)data
extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
error:(NSError **)errorPtr {
GPBBecomeVisibleToAutocreator(self);
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
@try {
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
[input checkLastTagWas:0];
if (errorPtr) {
*errorPtr = nil;
@ -2167,11 +2404,25 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
#pragma mark - Unknown Field Support
- (GPBUnknownFieldSet *)unknownFields {
@synchronized(self) {
if (unknownFieldData_) {
#if defined(DEBUG) && DEBUG
NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set");
#endif
unknownFields_ = [[GPBUnknownFieldSet alloc] init];
MergeUnknownFieldDataIntoFieldSet(self, unknownFieldData_, nil);
[unknownFieldData_ release];
unknownFieldData_ = nil;
}
return unknownFields_;
} // @synchronized(self)
}
- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields {
if (unknownFields != unknownFields_) {
if (unknownFields != unknownFields_ || unknownFieldData_ != nil) {
// Changing sets or clearing.
[unknownFieldData_ release];
unknownFieldData_ = nil;
[unknownFields_ release];
unknownFields_ = [unknownFields copy];
GPBBecomeVisibleToAutocreator(self);
@ -2182,89 +2433,90 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
uint32_t typeId = 0;
NSData *rawBytes = nil;
GPBExtensionDescriptor *extension = nil;
GPBCodedInputStreamState *state = &input->state_;
BOOL gotType = NO;
BOOL gotBytes = NO;
while (true) {
uint32_t tag = GPBCodedInputStreamReadTag(state);
if (tag == 0) {
if (tag == GPBWireFormatMessageSetItemEndTag || tag == 0) {
break;
}
if (tag == GPBWireFormatMessageSetTypeIdTag) {
typeId = GPBCodedInputStreamReadUInt32(state);
if (typeId != 0) {
extension = [extensionRegistry extensionForDescriptor:[self descriptor] fieldNumber:typeId];
uint32_t tmp = GPBCodedInputStreamReadUInt32(state);
// Spec says only use the first value.
if (!gotType) {
gotType = YES;
typeId = tmp;
}
} else if (tag == GPBWireFormatMessageSetMessageTag) {
if (gotBytes) {
// Skip over the payload instead of collecting it.
[input skipField:tag];
} else {
rawBytes = [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease];
gotBytes = YES;
}
} else {
// Don't capture unknowns within the message set impl group.
if (![input skipField:tag]) {
break;
}
}
}
[input checkLastTagWas:GPBWireFormatMessageSetItemEndTag];
// If we get here because of end of input (tag zero) or the wrong end tag (within the skipField:),
// this will error.
GPBCodedInputStreamCheckLastTagWas(state, GPBWireFormatMessageSetItemEndTag);
if (!gotType || !gotBytes) {
// upb_Decoder_DecodeMessageSetItem does't keep this partial as an unknown field, it just drops
// it, so do the same thing.
return;
}
if (rawBytes != nil && typeId != 0) {
if (extension != nil) {
GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor:[self descriptor]
fieldNumber:typeId];
if (extension) {
#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
NSAssert(extension.dataType == GPBDataTypeMessage,
@"Internal Error: MessageSet extension must be a message field.");
NSAssert(GPBExtensionIsWireFormat(extension->description_),
@"Internal Error: MessageSet extension must have message_set_wire_format set.");
NSAssert(!GPBExtensionIsRepeated(extension->description_),
@"Internal Error: MessageSet extension can't be repeated.");
#endif
// Look up the existing one to merge to or create a new one.
GPBMessage *targetMessage = [self getExistingExtension:extension];
if (!targetMessage) {
GPBDescriptor *descriptor = [extension.msgClass descriptor];
targetMessage = [[descriptor.messageClass alloc] init];
[self setExtension:extension value:targetMessage];
[targetMessage release];
}
GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc] initWithData:rawBytes];
@try {
ExtensionMergeFromInputStream(extension, extension.packable, newInput, extensionRegistry,
self);
[targetMessage mergeFromCodedInputStream:newInput
extensionRegistry:extensionRegistry
endingTag:0];
} @finally {
[newInput release];
}
} else {
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
// The extension isn't in the registry, but it was well formed, so the whole group structure
// get preserved as an unknown field.
// rawBytes was created via a NoCopy, so it can be reusing a
// subrange of another NSData that might go out of scope as things
// unwind, so a copy is needed to ensure what is saved in the
// unknown fields stays valid.
NSData *cloned = [NSData dataWithData:rawBytes];
[unknownFields mergeMessageSetMessage:typeId data:cloned];
}
}
}
- (BOOL)parseUnknownField:(GPBCodedInputStream *)input
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
tag:(uint32_t)tag {
GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag);
GPBDescriptor *descriptor = [self descriptor];
GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor:descriptor
fieldNumber:fieldNumber];
if (extension == nil) {
if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) {
[self parseMessageSet:input extensionRegistry:extensionRegistry];
return YES;
}
} else {
if (extension.wireType == wireType) {
ExtensionMergeFromInputStream(extension, extension.packable, input, extensionRegistry, self);
return YES;
}
// Primitive, repeated types can be packed on unpacked on the wire, and are
// parsed either way.
if ([extension isRepeated] && !GPBDataTypeIsObject(extension->description_->dataType) &&
(extension.alternateWireType == wireType)) {
ExtensionMergeFromInputStream(extension, !extension.packable, input, extensionRegistry, self);
return YES;
}
}
if ([GPBUnknownFieldSet isFieldTag:tag]) {
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
return [unknownFields mergeFieldFrom:tag input:input];
} else {
return NO;
AddUnknownMessageSetEntry(self, typeId, cloned);
}
}
- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
[unknownFields addUnknownMapEntry:fieldNum value:data];
AddUnknownFieldLengthDelimited(self, fieldNum, data);
}
#pragma mark - MergeFromCodedInputStream Support
@ -2337,8 +2589,7 @@ static void MergeSingleFieldFromCodedInputStream(GPBMessage *self, GPBFieldDescr
if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
GPBSetInt32IvarWithFieldPrivate(self, field, val);
} else {
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
[unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
AddUnknownFieldVarint32(self, GPBFieldNumber(field), val);
}
}
} // switch
@ -2387,8 +2638,7 @@ static void MergeRepeatedPackedFieldFromCodedInputStream(GPBMessage *self,
if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
[(GPBEnumArray *)genericArray addRawValue:val];
} else {
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
[unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
AddUnknownFieldVarint32(self, GPBFieldNumber(field), val);
}
break;
}
@ -2456,8 +2706,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
[(GPBEnumArray *)genericArray addRawValue:val];
} else {
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
[unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
AddUnknownFieldVarint32(self, GPBFieldNumber(field), val);
}
break;
}
@ -2465,18 +2714,27 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
}
- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
endingTag:(uint32_t)endingTag {
#if defined(DEBUG) && DEBUG
NSAssert(endingTag == 0 || GPBWireFormatGetTagWireType(endingTag) == GPBWireFormatEndGroup,
@"endingTag should have been an endGroup tag");
#endif // DEBUG
GPBDescriptor *descriptor = [self descriptor];
GPBCodedInputStreamState *state = &input->state_;
uint32_t tag = 0;
NSUInteger startingIndex = 0;
NSArray *fields = descriptor->fields_;
BOOL isMessageSetWireFormat = descriptor.isWireFormat;
NSUInteger numFields = fields.count;
while (YES) {
BOOL merged = NO;
tag = GPBCodedInputStreamReadTag(state);
if (tag == 0) {
break; // Reached end.
if (tag == endingTag || tag == 0) {
// If we got to the end (tag zero), when we were expecting the end group, this will
// raise the error.
GPBCodedInputStreamCheckLastTagWas(state, endingTag);
return;
}
for (NSUInteger i = 0; i < numFields; ++i) {
if (startingIndex >= numFields) startingIndex = 0;
@ -2514,8 +2772,9 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
}
} // for(i < numFields)
if (!merged && (tag != 0)) {
// Primitive, repeated types can be packed on unpacked on the wire, and
if (merged) continue; // On to the next tag
// Primitive, repeated types can be packed or unpacked on the wire, and
// are parsed either way. The above loop covered tag in the preferred
// for, so this need to check the alternate form.
for (NSUInteger i = 0; i < numFields; ++i) {
@ -2540,20 +2799,39 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
startingIndex += 1;
}
}
}
if (!merged) {
if (tag == 0) {
// zero signals EOF / limit reached
return;
if (merged) continue; // On to the next tag
if (isMessageSetWireFormat) {
if (GPBWireFormatMessageSetItemTag == tag) {
[self parseMessageSet:input extensionRegistry:extensionRegistry];
continue; // On to the next tag
}
} else {
if (![self parseUnknownField:input extensionRegistry:extensionRegistry tag:tag]) {
// it's an endgroup tag
return;
// ObjC Runtime currently doesn't track if a message supported extensions, so the check is
// always done.
GPBExtensionDescriptor *extension =
[extensionRegistry extensionForDescriptor:descriptor
fieldNumber:GPBWireFormatGetTagFieldNumber(tag)];
if (extension) {
GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
if (extension.wireType == wireType) {
ExtensionMergeFromInputStream(extension, extension.packable, input, extensionRegistry,
self);
continue; // On to the next tag
}
// Primitive, repeated types can be packed on unpacked on the wire, and are
// parsed either way.
if ([extension isRepeated] && !GPBDataTypeIsObject(extension->description_->dataType) &&
(extension.alternateWireType == wireType)) {
ExtensionMergeFromInputStream(extension, !extension.packable, input, extensionRegistry,
self);
continue; // On to the next tag
}
}
}
} // if(!merged)
ParseUnknownField(self, tag, input);
} // while(YES)
}
@ -2675,10 +2953,29 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
} // for(fields)
// Unknown fields.
if (!unknownFields_) {
[self setUnknownFields:other.unknownFields];
if (unknownFields_) {
#if defined(DEBUG) && DEBUG
NSAssert(unknownFieldData_ == nil, @"Internal error both unknown states were set");
#endif
@synchronized(other) {
if (other->unknownFields_) {
#if defined(DEBUG) && DEBUG
NSAssert(other->unknownFieldData_ == nil, @"Internal error both unknown states were set");
#endif
[unknownFields_ mergeUnknownFields:other->unknownFields_];
} else if (other->unknownFieldData_) {
MergeUnknownFieldDataIntoFieldSet(self, other->unknownFieldData_, nil);
}
} // @synchronized(other)
} else {
NSData *otherData = GPBMessageUnknownFieldsData(other);
if (otherData) {
if (unknownFieldData_) {
[unknownFieldData_ appendData:otherData];
} else {
[unknownFields_ mergeUnknownFields:other.unknownFields];
unknownFieldData_ = [otherData mutableCopy];
}
}
}
// Extensions
@ -2850,15 +3147,72 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
}
}
// nil and empty are equal
GPBUnknownFieldSet *otherUnknowns = otherMsg->unknownFields_;
if ([unknownFields_ countOfFields] != 0 || [otherUnknowns countOfFields] != 0) {
if (![unknownFields_ isEqual:otherUnknowns]) {
return NO;
// Mutation while another thread is doing read only access is invalid, so the only thing we
// need to guard against is concurrent r/o access, so we can grab the values (and retain them)
// so we have a version to compare against safely incase the second access causes the transform
// between internal states.
GPBUnknownFieldSet *selfUnknownFields;
NSData *selfUnknownFieldData;
@synchronized(self) {
selfUnknownFields = [unknownFields_ retain];
selfUnknownFieldData = [unknownFieldData_ retain];
}
GPBUnknownFieldSet *otherUnknownFields;
NSData *otherUnknownFieldData;
@synchronized(otherMsg) {
otherUnknownFields = [otherMsg->unknownFields_ retain];
otherUnknownFieldData = [otherMsg->unknownFieldData_ retain];
}
#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
if (selfUnknownFields) {
NSAssert(selfUnknownFieldData == nil, @"Internal error both unknown states were set");
}
if (otherUnknownFields) {
NSAssert(otherUnknownFieldData == nil, @"Internal error both unknown states were set");
}
#endif
// Since a developer can set the legacy unknownFieldSet, treat nil and empty as the same.
if (selfUnknownFields && selfUnknownFields.countOfFields == 0) {
[selfUnknownFields release];
selfUnknownFields = nil;
}
if (otherUnknownFields && otherUnknownFields.countOfFields == 0) {
[otherUnknownFields release];
otherUnknownFields = nil;
}
BOOL result = YES;
if (selfUnknownFieldData && otherUnknownFieldData) {
// Both had data, compare it.
result = [selfUnknownFieldData isEqual:otherUnknownFieldData];
} else if (selfUnknownFields && otherUnknownFields) {
// Both had fields set, compare them.
result = [selfUnknownFields isEqual:otherUnknownFields];
} else {
// At this point, we're done to one have a set/nothing, and the other having data/nothing.
GPBUnknownFieldSet *theSet = selfUnknownFields ? selfUnknownFields : otherUnknownFields;
NSData *theData = selfUnknownFieldData ? selfUnknownFieldData : otherUnknownFieldData;
if (theSet) {
if (theData) {
GPBUnknownFieldSet *tempSet = [[GPBUnknownFieldSet alloc] init];
MergeUnknownFieldDataIntoFieldSet(self, theData, tempSet);
result = [tempSet isEqual:theSet];
[tempSet release];
} else {
result = NO;
}
} else {
// It was a data/nothing and nothing, so they equal if the other didn't have data.
result = theData == nil;
}
}
return YES;
[selfUnknownFields release];
[selfUnknownFieldData release];
[otherUnknownFields release];
[otherUnknownFieldData release];
return result;
}
// It is very difficult to implement a generic hash for ProtoBuf messages that
@ -3121,11 +3475,20 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
} // for(fields)
// Add any unknown fields.
@synchronized(self) {
if (unknownFieldData_) {
#if defined(DEBUG) && DEBUG
NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set");
#endif
result += [unknownFieldData_ length];
} else {
if (descriptor.wireFormat) {
result += [unknownFields_ serializedSizeAsMessageSet];
} else {
result += [unknownFields_ serializedSize];
}
}
} // @synchronized(self)
// Add any extensions.
for (GPBExtensionDescriptor *extension in extensionMap_) {
@ -3554,8 +3917,7 @@ GPB_INLINE BOOL GPBIsCaseOfSelForOneOf(const char *selName, size_t selNameLength
if (data.length) {
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
@try {
[self mergeFromCodedInputStream:input extensionRegistry:nil];
[input checkLastTagWas:0];
[self mergeFromCodedInputStream:input extensionRegistry:nil endingTag:0];
} @finally {
[input release];
}
@ -3652,4 +4014,32 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
return expected;
}
NSData *GPBMessageUnknownFieldsData(GPBMessage *self) {
NSData *result = nil;
@synchronized(self) {
GPBUnknownFieldSet *unknownFields = self->unknownFields_;
if (unknownFields) {
#if defined(DEBUG) && DEBUG
NSCAssert(self->unknownFieldData_ == nil, @"Internal error both unknown states were set");
#endif
if (self.descriptor.isWireFormat) {
NSMutableData *mutableData =
[NSMutableData dataWithLength:unknownFields.serializedSizeAsMessageSet];
GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:mutableData];
[unknownFields writeAsMessageSetTo:output];
[output flush];
[output release];
result = mutableData;
} else {
result = [unknownFields data];
}
} else {
// Internally we can borrow it without a copy since this is immediately used by callers
// and multithreaded access with any mutation is not allow on messages.
result = self->unknownFieldData_;
}
} // @synchronized(self)
return result;
}
#pragma clang diagnostic pop

@ -47,15 +47,15 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr;
// Parses a message of this type from the input and merges it with this
// message.
//
// `endingTag` should be zero if expected to consume to the end of input, but if
// the input is supposed to be a Group, it should be the endgroup tag to look for.
//
// Warning: This does not verify that all required fields are present in
// the input message.
// Note: The caller should call
// -[CodedInputStream checkLastTagWas:] after calling this to
// verify that the last tag seen was the appropriate end-group tag,
// or zero for EOF.
// NOTE: This will throw if there is an error while parsing.
- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry;
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
endingTag:(uint32_t)endingTag;
- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data;
@ -81,4 +81,7 @@ void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary);
// autocreated reference to this message.
void GPBClearMessageAutocreator(GPBMessage *self);
// The data (or null) from the unknown fields of a message;
NSData *GPBMessageUnknownFieldsData(GPBMessage *self);
CF_EXTERN_C_END

@ -154,7 +154,10 @@ static void CopyWorker(__unused const void *key, const void *value, void *contex
- (NSString *)description {
NSMutableString *description =
[NSMutableString stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" ");
#pragma clang diagnostic pop
[description appendString:textFormat];
[description appendString:@"}"];
return description;
@ -212,10 +215,6 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(__unused const void *ke
return data;
}
+ (BOOL)isFieldTag:(int32_t)tag {
return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup;
}
- (void)addField:(GPBUnknownField *)field {
int32_t number = [field number];
checkNumber(number);
@ -272,6 +271,11 @@ static void GPBUnknownFieldSetMergeUnknownFields(__unused const void *key, const
[[self mutableFieldForNumber:number create:YES] addVarint:value];
}
- (void)mergeLengthDelimited:(int32_t)fieldNum value:(NSData *)value {
checkNumber(fieldNum);
[[self mutableFieldForNumber:fieldNum create:YES] addLengthDelimited:value];
}
- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input {
NSAssert(GPBWireFormatIsValidTag(tag), @"Got passed an invalid tag");
int32_t number = GPBWireFormatGetTagFieldNumber(tag);
@ -314,15 +318,6 @@ static void GPBUnknownFieldSetMergeUnknownFields(__unused const void *key, const
}
}
- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData {
[[self mutableFieldForNumber:number create:YES] addLengthDelimited:messageData];
}
- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES];
[field addLengthDelimited:data];
}
- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input {
while (YES) {
int32_t tag = GPBCodedInputStreamReadTag(&input->state_);

@ -14,8 +14,6 @@
@interface GPBUnknownFieldSet ()
+ (BOOL)isFieldTag:(int32_t)tag;
- (NSData *)data;
- (size_t)serializedSize;
@ -29,9 +27,7 @@
- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input;
- (void)mergeVarintField:(int32_t)number value:(int32_t)value;
- (void)mergeLengthDelimited:(int32_t)number value:(NSData *)value;
- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input;
- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData;
- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data;
@end

@ -12,7 +12,9 @@
#import "GPBCodedInputStream_PackagePrivate.h"
#import "GPBCodedOutputStream.h"
#import "GPBCodedOutputStream_PackagePrivate.h"
#import "GPBDescriptor.h"
#import "GPBMessage.h"
#import "GPBMessage_PackagePrivate.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownField_PackagePrivate.h"
@ -195,12 +197,9 @@ static BOOL MergeFromInputStream(GPBUnknownFields *self, GPBCodedInputStream *in
self = [super init];
if (self) {
fields_ = [[NSMutableArray alloc] init];
// TODO: b/349146447 - Move off the legacy class and directly to the data once Message is
// updated.
GPBUnknownFieldSet *legacyUnknownFields = [message unknownFields];
if (legacyUnknownFields) {
GPBCodedInputStream *input =
[[GPBCodedInputStream alloc] initWithData:[legacyUnknownFields data]];
NSData *data = GPBMessageUnknownFieldsData(message);
if (data) {
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
// Parse until the end of the data (tag will be zero).
if (!MergeFromInputStream(self, input, 0)) {
[input release];

@ -40,7 +40,9 @@ NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *__nullable line
* @return An NSString with the TextFormat of the unknown field set.
**/
NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *__nullable unknownSet,
NSString *__nullable lineIndent);
NSString *__nullable lineIndent)
__attribute__((deprecated("Use GPBTextFormatForMessage will include the unknown fields, and "
"GPBUnknownFieldSet it going away.")));
/**
* Checks if the given field number is set on a message.

@ -5,7 +5,7 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#import "GPBUtilities_PackagePrivate.h"
#import "GPBUtilities.h"
#import <objc/runtime.h>
@ -15,6 +15,9 @@
#import "GPBMessage_PackagePrivate.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFieldSet.h"
#import "GPBUnknownField_PackagePrivate.h"
#import "GPBUnknownFields.h"
#import "GPBUtilities_PackagePrivate.h"
// 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
@ -1929,6 +1932,78 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, NSArra
} // for..in(activeExtensions)
}
static void AppendTextFormatForUnknownFields(GPBUnknownFields *ufs, NSMutableString *toStr,
NSString *lineIndent) {
#if defined(DEBUG) && DEBUG
NSCAssert(!ufs.empty, @"Internal Error: No unknown fields to format.");
#endif
// Extract the fields and sort them by field number. Use a stable sort and sort just by the field
// numbers, that way the output will still show the order the different types were added as well
// as maintaining the order within a give number/type pair (i.e. - repeated fields say in order).
NSMutableArray *sortedFields = [[NSMutableArray alloc] initWithCapacity:ufs.count];
for (GPBUnknownField *field in ufs) {
[sortedFields addObject:field];
}
[sortedFields
sortWithOptions:NSSortStable
usingComparator:^NSComparisonResult(GPBUnknownField *field1, GPBUnknownField *field2) {
int32_t fieldNumber1 = field1->number_;
int32_t fieldNumber2 = field2->number_;
if (fieldNumber1 < fieldNumber2) {
return NSOrderedAscending;
} else if (fieldNumber1 > fieldNumber2) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
NSString *subIndent = nil;
for (GPBUnknownField *field in sortedFields) {
int32_t fieldNumber = field->number_;
switch (field->type_) {
case GPBUnknownFieldTypeVarint:
[toStr appendFormat:@"%@%d: %llu\n", lineIndent, fieldNumber, field->storage_.intValue];
break;
case GPBUnknownFieldTypeFixed32:
[toStr appendFormat:@"%@%d: 0x%X\n", lineIndent, fieldNumber,
(uint32_t)field->storage_.intValue];
break;
case GPBUnknownFieldTypeFixed64:
[toStr appendFormat:@"%@%d: 0x%llX\n", lineIndent, fieldNumber, field->storage_.intValue];
break;
case GPBUnknownFieldTypeLengthDelimited:
[toStr appendFormat:@"%@%d: ", lineIndent, fieldNumber];
AppendBufferAsString(field->storage_.lengthDelimited, toStr);
[toStr appendString:@"\n"];
break;
case GPBUnknownFieldTypeGroup: {
GPBUnknownFields *group = field->storage_.group;
if (group.empty) {
[toStr appendFormat:@"%@%d: {}\n", lineIndent, fieldNumber];
} else {
[toStr appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
if (subIndent == nil) {
subIndent = [lineIndent stringByAppendingString:@" "];
}
AppendTextFormatForUnknownFields(group, toStr, subIndent);
[toStr appendFormat:@"%@}\n", lineIndent];
}
} break;
case GPBUnknownFieldTypeLegacy:
#if defined(DEBUG) && DEBUG
NSCAssert(
NO,
@"Internal error: Shouldn't have gotten a legacy field type in the unknown fields.");
#endif
break;
}
}
[subIndent release];
[sortedFields release];
}
static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr,
NSString *lineIndent) {
GPBDescriptor *descriptor = [message descriptor];
@ -1951,11 +2026,12 @@ static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toS
}
}
NSString *unknownFieldsStr = GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
if ([unknownFieldsStr length] > 0) {
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:message];
if (ufs.count > 0) {
[toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
[toStr appendString:unknownFieldsStr];
AppendTextFormatForUnknownFields(ufs, toStr, lineIndent);
}
[ufs release];
}
NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) {

@ -6,12 +6,16 @@
// https://developers.google.com/open-source/licenses/bsd
#import <Foundation/Foundation.h>
#import "GPBTestUtilities.h"
#import "GPBCodedInputStream.h"
#import "GPBCodedInputStream_PackagePrivate.h"
#import "GPBCodedOutputStream.h"
#import "GPBTestUtilities.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownFields.h"
#import "GPBUtilities_PackagePrivate.h"
#import "GPBWireFormat.h"
#import "objectivec/Tests/Unittest.pbobjc.h"
@interface CodedInputStreamTests : GPBTestCase
@ -266,20 +270,55 @@
TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
NSData* rawBytes = message.data;
// Create two parallel inputs. Parse one as unknown fields while using
// skipField() to skip each field on the other. Expect the same tags.
TestEmptyMessage* empty = [TestEmptyMessage parseFromData:rawBytes error:NULL];
XCTAssertNotNil(empty);
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:empty] autorelease];
NSMutableArray<NSNumber*>* fieldNumbers = [NSMutableArray arrayWithCapacity:ufs.count];
for (GPBUnknownField* field in ufs) {
GPBWireFormat wireFormat;
switch (field.type) {
case GPBUnknownFieldTypeFixed32:
wireFormat = GPBWireFormatFixed32;
break;
case GPBUnknownFieldTypeFixed64:
wireFormat = GPBWireFormatFixed64;
break;
case GPBUnknownFieldTypeVarint:
wireFormat = GPBWireFormatVarint;
break;
case GPBUnknownFieldTypeLengthDelimited:
wireFormat = GPBWireFormatLengthDelimited;
break;
case GPBUnknownFieldTypeGroup:
wireFormat = GPBWireFormatStartGroup;
break;
case GPBUnknownFieldTypeLegacy:
XCTFail(@"Legacy field type not expected");
wireFormat = GPBWireFormatVarint;
break;
}
uint32_t tag = GPBWireFormatMakeTag(field.number, wireFormat);
[fieldNumbers addObject:@(tag)];
}
// Check the tags compared to what's in the UnknownFields to confirm the stream is
// skipping as expected (this covers the tags within a group also).
GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes];
GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes];
GPBUnknownFieldSet* unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease];
NSUInteger idx = 0;
while (YES) {
int32_t tag = [input1 readTag];
XCTAssertEqual(tag, [input2 readTag]);
if (tag == 0) {
XCTAssertEqual(idx, fieldNumbers.count);
break;
}
XCTAssertEqual(tag, [fieldNumbers[idx] intValue]);
[unknownFields mergeFieldFrom:tag input:input1];
[input2 skipField:tag];
++idx;
}
}
@ -444,4 +483,102 @@
}
}
- (void)assertReadByteToEndGroupFails:(NSData*)data {
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
uint32_t tag = [input readTag];
XCTAssertThrows(GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(
&input->state_, GPBWireFormatGetTagFieldNumber(tag)));
}
- (void)assertReadByteToEndGroup:(NSData*)data value:(NSData*)value {
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
uint32_t tag = [input readTag];
NSData* readValue = GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(
&input->state_, GPBWireFormatGetTagFieldNumber(tag));
XCTAssertNotNil(readValue);
XCTAssertEqualObjects(readValue, value);
[readValue release];
}
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testBytesToEndGroup {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
[self assertReadByteToEndGroup:bytes(35, 36) value:bytes(36)]; // empty group
[self assertReadByteToEndGroup:bytes(35, 8, 1, 36) value:bytes(8, 1, 36)]; // varint
[self assertReadByteToEndGroup:bytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36) // fixed32
value:bytes(21, 0x78, 0x56, 0x34, 0x12, 36)];
[self assertReadByteToEndGroup:bytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36) // fixed64
value:bytes(25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, 36)];
[self assertReadByteToEndGroup:bytes(35, 50, 0, 36)
value:bytes(50, 0, 36)]; // length delimited, length 0
[self assertReadByteToEndGroup:bytes(35, 50, 1, 42, 36)
value:bytes(50, 1, 42, 36)]; // length delimited, length 1, byte 42
[self assertReadByteToEndGroup:bytes(35, 43, 44, 36) value:bytes(43, 44, 36)]; // Sub group
[self assertReadByteToEndGroup:bytes(35, 8, 1, 43, 8, 1, 44,
36) // varint and sub group with varint
value:bytes(8, 1, 43, 8, 1, 44, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 0, 36)]; // Invalid field number
[self assertReadByteToEndGroupFails:bytes(35, 15, 36)]; // Invalid wire type
[self assertReadByteToEndGroupFails:bytes(35, 21, 0x78, 0x56, 0x34)]; // truncated fixed32
[self assertReadByteToEndGroupFails:bytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)]; // truncated fixed64
// Mising end group
[self assertReadByteToEndGroupFails:bytes(35)];
[self assertReadByteToEndGroupFails:bytes(35, 8, 1)];
[self assertReadByteToEndGroupFails:bytes(35, 43)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1)];
// Wrong end group
[self assertReadByteToEndGroupFails:bytes(35, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 8, 1, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 44, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1, 44, 44)];
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
[self assertReadByteToEndGroup:testData
value:[testData subdataWithRange:NSMakeRange(1, testData.length - 1)]];
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
[self assertReadByteToEndGroupFails:testData];
}
@end

@ -419,6 +419,17 @@
// All the values should be in unknown fields.
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:msg];
XCTAssertEqual(ufs.count, 3U);
uint64_t varint;
XCTAssertTrue([ufs getFirst:Message2_FieldNumber_OptionalEnum varint:&varint]);
XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3);
XCTAssertTrue([ufs getFirst:Message2_FieldNumber_RepeatedEnumArray varint:&varint]);
XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3);
XCTAssertTrue([ufs getFirst:Message2_FieldNumber_OneofEnum varint:&varint]);
XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3);
[ufs release];
GPBUnknownFieldSet *unknownFields = msg.unknownFields;
XCTAssertEqual([unknownFields countOfFields], 3U);
@ -1398,6 +1409,9 @@
int32_t val = -1;
XCTAssertTrue([msg1.knownMapField getEnum:&val forKey:0]);
XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo);
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:msg1];
XCTAssertEqual(ufs.count, 1U);
[ufs release];
XCTAssertEqual(msg1.unknownFields.countOfFields, 1U);
data = [msg1 data];
@ -1410,6 +1424,9 @@
XCTAssertEqual(msg2.unknownMapField.count, 1U);
XCTAssertTrue([msg2.unknownMapField getEnum:&val forKey:0]);
XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumExtra);
ufs = [[GPBUnknownFields alloc] initFromMessage:msg2];
XCTAssertTrue(ufs.empty);
[ufs release];
XCTAssertEqual(msg2.unknownFields.countOfFields, 0U);
XCTAssertEqualObjects(orig, msg2);

@ -5,16 +5,18 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#import "GPBTestUtilities.h"
#import <objc/runtime.h>
#import "GPBArray.h"
#import "GPBArray_PackagePrivate.h"
#import "GPBDescriptor.h"
#import "GPBDictionary_PackagePrivate.h"
#import "GPBMessage_PackagePrivate.h"
#import "GPBTestUtilities.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownField_PackagePrivate.h"
#import "GPBUnknownFields.h"
#import "objectivec/Tests/Unittest.pbobjc.h"
#import "objectivec/Tests/UnittestImport.pbobjc.h"
#import "objectivec/Tests/UnittestObjc.pbobjc.h"
@ -501,6 +503,11 @@
[message setUnknownFields:unknownFields];
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1234 fixed32:1234];
[ufs addFieldNumber:2345 varint:54321];
[message mergeUnknownFields:ufs extensionRegistry:nil];
NSString *description = [message description];
XCTAssertGreaterThan([description length], 0U);
@ -985,6 +992,19 @@
XCTAssertFalse([message hasOptionalNestedMessage]);
[message.optionalNestedMessage setUnknownFields:unknownFields];
XCTAssertTrue([message hasOptionalNestedMessage]);
message.optionalNestedMessage = nil;
XCTAssertFalse([message hasOptionalNestedMessage]);
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1 varint:1];
[message.optionalNestedMessage mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message hasOptionalNestedMessage]);
message.optionalNestedMessage = nil;
XCTAssertFalse([message hasOptionalNestedMessage]);
[ufs clear]; // Also make sure merging zero length forces it to become visible.
[message.optionalNestedMessage mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message hasOptionalNestedMessage]);
}
- (void)testSetAutocreatedSubmessageToSelf {
@ -1481,6 +1501,19 @@
XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedNestedEnumExtension]]);
XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedForeignEnumExtension]]);
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease];
XCTAssertEqual(ufs.count, 3);
uint64_t varint;
XCTAssertTrue([ufs getFirst:[UnittestRoot optionalNestedEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 10);
XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedNestedEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 11);
XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedForeignEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 12);
GPBUnknownFieldSet *unknownFields = msg.unknownFields;
GPBUnknownField *field =
[unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber];
@ -1523,6 +1556,18 @@
expected = @[ @4, @6 ];
XCTAssertEqualObjects([msg getExtension:[UnittestRoot repeatedForeignEnumExtension]], expected);
ufs = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease];
XCTAssertEqual(ufs.count, 3);
XCTAssertTrue([ufs getFirst:[UnittestRoot optionalNestedEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 10);
XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedNestedEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 11);
XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedForeignEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 12);
unknownFields = msg.unknownFields;
field = [unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber];
XCTAssertNotNil(field);
@ -1840,6 +1885,9 @@
[unknowns mergeVarintField:123 value:456];
GPBMessage *message = [GPBMessage message];
[message setUnknownFields:unknowns];
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1234 varint:5678];
[message mergeUnknownFields:ufs extensionRegistry:nil];
NSData *data = [message data];
GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil error:NULL];
XCTAssertEqualObjects(message, message2);
@ -1850,12 +1898,19 @@
[unknowns1 mergeVarintField:123 value:456];
GPBMessage *message1 = [GPBMessage message];
[message1 setUnknownFields:unknowns1];
GPBUnknownFields *ufs1 = [[[GPBUnknownFields alloc] init] autorelease];
[ufs1 addFieldNumber:1234 varint:5678];
[message1 mergeUnknownFields:ufs1 extensionRegistry:nil];
GPBUnknownFieldSet *unknowns2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
[unknowns2 mergeVarintField:789 value:987];
[unknowns2 mergeVarintField:654 value:321];
GPBMessage *message2 = [GPBMessage message];
[message2 setUnknownFields:unknowns2];
GPBUnknownFields *ufs2 = [[[GPBUnknownFields alloc] init] autorelease];
[ufs2 addFieldNumber:2345 fixed32:6789];
[ufs2 addFieldNumber:3456 fixed32:7890];
[message2 mergeUnknownFields:ufs2 extensionRegistry:nil];
NSMutableData *delimitedData = [NSMutableData data];
[delimitedData appendData:[message1 delimitedData]];
@ -2022,6 +2077,54 @@
XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo);
}
- (void)testCloseEnumsValuesOutOfRange {
// The unknown values should all make it into the unknown fields.
EnumTestMsg *msg1 = [EnumTestMsg message];
msg1.bar = EnumTestMsg_MyEnum_NegTwo;
msg1.baz = EnumTestMsg_MyEnum_Two;
[msg1.mumbleArray addValue:EnumTestMsg_MyEnum_Two];
[msg1.mumbleArray addValue:EnumTestMsg_MyEnum_NegTwo];
NSData *data = [msg1 data];
XCTAssertNotNil(data);
EnumTestMsgPrime *msg2 = [EnumTestMsgPrime parseFromData:data error:NULL];
XCTAssertNotNil(msg2);
XCTAssertEqualObjects(data, [msg2 data]);
XCTAssertFalse(msg2.hasBar);
XCTAssertFalse(msg2.hasBaz);
XCTAssertEqual(msg2.mumbleArray_Count, 0U);
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] initFromMessage:msg2] autorelease];
XCTAssertEqual(ufs.count, 4U);
uint64_t varint;
XCTAssertTrue([ufs getFirst:EnumTestMsg_FieldNumber_Bar varint:&varint]);
XCTAssertEqual(varint, (uint64_t)EnumTestMsg_MyEnum_NegTwo);
XCTAssertTrue([ufs getFirst:EnumTestMsg_FieldNumber_Baz varint:&varint]);
XCTAssertEqual(varint, (uint64_t)EnumTestMsg_MyEnum_Two);
NSArray<GPBUnknownField *> *fields = [ufs fields:EnumTestMsg_FieldNumber_MumbleArray];
XCTAssertEqual(fields.count, 2U);
XCTAssertEqual(fields[0].varint, (uint64_t)EnumTestMsg_MyEnum_Two);
XCTAssertEqual(fields[1].varint, (uint64_t)EnumTestMsg_MyEnum_NegTwo);
GPBUnknownFieldSet *unknownFields = msg2.unknownFields;
XCTAssertNotNil(unknownFields);
XCTAssertEqual(unknownFields.countOfFields, 3U);
XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_Bar]);
XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_Baz]);
XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_MumbleArray]);
GPBUnknownField *field = [unknownFields getField:EnumTestMsg_FieldNumber_Bar];
XCTAssertEqual(field.varintList.count, 1U);
XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_NegTwo);
field = [unknownFields getField:EnumTestMsg_FieldNumber_Baz];
XCTAssertEqual(field.varintList.count, 1U);
XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_Two);
field = [unknownFields getField:EnumTestMsg_FieldNumber_MumbleArray];
XCTAssertEqual(field.varintList.count, 2U);
XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_Two);
XCTAssertEqual([field.varintList valueAtIndex:1], (uint64_t)EnumTestMsg_MyEnum_NegTwo);
}
- (void)testReservedWordNaming {
// names.cc has some special handing to make sure that some "reserved" objc
// names get renamed in a way so they don't conflict.

@ -6,6 +6,7 @@
// https://developers.google.com/open-source/licenses/bsd
#import "GPBTestUtilities.h"
#import "GPBUnknownFieldSet.h"
#import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownField_PackagePrivate.h"
@ -281,6 +282,10 @@
TestEmptyMessage* destination2 = [TestEmptyMessage message];
[destination2 mergeFrom:source3];
XCTAssertEqualObjects(destination1.unknownFields, destination2.unknownFields);
XCTAssertEqualObjects(destination1.unknownFields, source3.unknownFields);
XCTAssertEqualObjects(destination2.unknownFields, source3.unknownFields);
XCTAssertEqualObjects(destination1.data, destination2.data);
XCTAssertEqualObjects(destination1.data, source3.data);
XCTAssertEqualObjects(destination2.data, source3.data);
@ -376,6 +381,180 @@
XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]);
}
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testParsingNestingGroupData {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
TestEmptyMessage* m = [TestEmptyMessage parseFromData:DataFromBytes(35, 36)
error:NULL]; // empty group
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
GPBUnknownField* field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
GPBUnknownFieldSet* group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)0);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 36) error:NULL]; // varint
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 1);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36)
error:NULL]; // fixed32
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:2];
XCTAssertEqual(field.fixed32List.count, (NSUInteger)1);
XCTAssertEqual([field.fixed32List valueAtIndex:0], 0x12345678);
m = [TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36)
error:NULL]; // fixed64
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:3];
XCTAssertEqual(field.fixed64List.count, (NSUInteger)1);
XCTAssertEqual([field.fixed64List valueAtIndex:0], 0x123456789abcdef0LL);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 0, 36)
error:NULL]; // length delimited, length 0
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:6];
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)1);
XCTAssertEqualObjects(field.lengthDelimitedList[0], [NSData data]);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 1, 42, 36)
error:NULL]; // length delimited, length 1, byte 42
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:6];
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)1);
XCTAssertEqualObjects(field.lengthDelimitedList[0], DataFromBytes(42));
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 36) error:NULL]; // Sub group
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)1);
field = [group getField:5];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)0);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 43, 8, 2, 44, 36)
error:NULL]; // varint and sub group with varint
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)2);
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 1);
field = [group getField:5];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 2);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 0, 36)
error:NULL]); // Invalid field number
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 15, 36)
error:NULL]); // Invalid wire type
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34)
error:NULL]); // truncated fixed32
XCTAssertNil([TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)
error:NULL]); // truncated fixed64
// Mising end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1) error:NULL]);
// Wrong end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 44, 44) error:NULL]);
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
m = [TestEmptyMessage parseFromData:testData error:NULL];
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
for (NSUInteger i = 0; i < kDefaultRecursionLimit; ++i) {
XCTAssertEqual(field.varintList.count, (NSUInteger)0);
XCTAssertEqual(field.fixed32List.count, (NSUInteger)0);
XCTAssertEqual(field.fixed64List.count, (NSUInteger)0);
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)0);
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)1);
field = [group getField:(i < (kDefaultRecursionLimit - 1) ? 4 : 1)];
}
// field is of the inner most group
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], (NSUInteger)1);
XCTAssertEqual(field.fixed32List.count, (NSUInteger)0);
XCTAssertEqual(field.fixed64List.count, (NSUInteger)0);
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)0);
XCTAssertEqual(field.groupList.count, (NSUInteger)0);
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
XCTAssertNil([TestEmptyMessage parseFromData:testData error:NULL]);
}
#pragma mark - Field tests
// Some tests directly on fields since the dictionary in FieldSet can gate
// testing some of these.

@ -847,4 +847,163 @@
XCTAssertEqual(varint, 0x7FFFFFFFFFFFFFFFL);
}
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testParsingNestingGroupData {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
TestEmptyMessage* m = [TestEmptyMessage parseFromData:DataFromBytes(35, 36)
error:NULL]; // empty group
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
GPBUnknownFields* group = [ufs firstGroup:4];
XCTAssertTrue(group.empty);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 36) error:NULL]; // varint
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint64_t varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36)
error:NULL]; // fixed32
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint32_t fixed32 = 0;
XCTAssertTrue([group getFirst:2 fixed32:&fixed32]);
XCTAssertEqual(fixed32, 0x12345678);
m = [TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36)
error:NULL]; // fixed64
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint64_t fixed64 = 0;
XCTAssertTrue([group getFirst:3 fixed64:&fixed64]);
XCTAssertEqual(fixed64, 0x123456789abcdef0LL);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 0, 36)
error:NULL]; // length delimited, length 0
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
NSData* lengthDelimited = [group firstLengthDelimited:6];
XCTAssertEqualObjects(lengthDelimited, [NSData data]);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 1, 42, 36)
error:NULL]; // length delimited, length 1, byte 42
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
lengthDelimited = [group firstLengthDelimited:6];
XCTAssertEqualObjects(lengthDelimited, DataFromBytes(42));
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 36) error:NULL]; // Sub group
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
group = [group firstGroup:5];
XCTAssertTrue(group.empty);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 43, 8, 2, 44, 36)
error:NULL]; // varint and sub group with varint
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)2);
varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
group = [group firstGroup:5];
XCTAssertEqual(group.count, (NSUInteger)1);
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 2);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 0, 36)
error:NULL]); // Invalid field number
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 15, 36)
error:NULL]); // Invalid wire type
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34)
error:NULL]); // truncated fixed32
XCTAssertNil([TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)
error:NULL]); // truncated fixed64
// Mising end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1) error:NULL]);
// Wrong end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 44, 44) error:NULL]);
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
m = [TestEmptyMessage parseFromData:testData error:NULL];
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
for (NSUInteger i = 1; i < kDefaultRecursionLimit; ++i) {
XCTAssertEqual(group.count, (NSUInteger)1);
group = [group firstGroup:4];
}
// group is now the inner most group.
XCTAssertEqual(group.count, (NSUInteger)1);
varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
XCTAssertNil([TestEmptyMessage parseFromData:testData error:NULL]);
}
@end

@ -6,17 +6,16 @@
// https://developers.google.com/open-source/licenses/bsd
#import <XCTest/XCTest.h>
#import "GPBUtilities_PackagePrivate.h"
#import <objc/runtime.h>
#import "GPBTestUtilities.h"
#import "GPBDescriptor.h"
#import "GPBDescriptor_PackagePrivate.h"
#import "GPBMessage.h"
#import "GPBTestUtilities.h"
#import "GPBUnknownField.h"
#import "GPBUnknownField_PackagePrivate.h"
#import "GPBUtilities.h"
#import "GPBUtilities_PackagePrivate.h"
#import "objectivec/Tests/MapUnittest.pbobjc.h"
#import "objectivec/Tests/Unittest.pbobjc.h"
@ -168,6 +167,54 @@
[expected release];
}
- (void)testTextFormatUnknownFields {
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:100 varint:5];
[ufs addFieldNumber:100 varint:4];
[ufs addFieldNumber:10 varint:1];
[ufs addFieldNumber:300 fixed32:0x50];
[ufs addFieldNumber:300 fixed32:0x40];
[ufs addFieldNumber:10 fixed32:0x10];
[ufs addFieldNumber:200 fixed64:0x5000];
[ufs addFieldNumber:200 fixed64:0x4000];
[ufs addFieldNumber:10 fixed64:0x1000];
[ufs addFieldNumber:10 lengthDelimited:DataFromCStr("foo")];
[ufs addFieldNumber:10 lengthDelimited:DataFromCStr("bar")];
GPBUnknownFields *group = [ufs addGroupWithFieldNumber:150];
[group addFieldNumber:2 varint:2];
[group addFieldNumber:1 varint:1];
group = [ufs addGroupWithFieldNumber:150];
[group addFieldNumber:1 varint:1];
[group addFieldNumber:3 fixed32:0x3];
[group addFieldNumber:2 fixed64:0x2];
TestEmptyMessage *message = [TestEmptyMessage message];
[message mergeUnknownFields:ufs extensionRegistry:nil];
NSString *expected = @"# --- Unknown fields ---\n"
@"10: 1\n"
@"10: 0x10\n"
@"10: 0x1000\n"
@"10: \"foo\"\n"
@"10: \"bar\"\n"
@"100: 5\n"
@"100: 4\n"
@"150: {\n"
@" 1: 1\n"
@" 2: 2\n"
@"}\n"
@"150: {\n"
@" 1: 1\n"
@" 2: 0x2\n"
@" 3: 0x3\n"
@"}\n"
@"200: 0x5000\n"
@"200: 0x4000\n"
@"300: 0x50\n"
@"300: 0x40\n";
NSString *result = GPBTextFormatForMessage(message, nil);
XCTAssertEqualObjects(expected, result);
}
- (void)testSetRepeatedFields {
TestAllTypes *message = [TestAllTypes message];
@ -204,11 +251,27 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
return result;
}
// Helper to add an unknown field data to messages.
static void AddUnknownFields(GPBMessage *message, int num) {
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] init];
[ufs addFieldNumber:num varint:num];
[message mergeUnknownFields:ufs extensionRegistry:nil];
[ufs release];
}
static BOOL HasUnknownFields(GPBMessage *message) {
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:message];
BOOL result = !ufs.empty;
[ufs release];
return result;
}
- (void)testDropMessageUnknownFieldsRecursively {
TestAllExtensions *message = [TestAllExtensions message];
// Give it unknownFields.
message.unknownFields = UnknownFieldsSetHelper(777);
AddUnknownFields(message, 1777);
// Given it extensions that include a message with unknown fields of its own.
{
@ -219,18 +282,21 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message];
optionalGroup.a = 123;
optionalGroup.unknownFields = UnknownFieldsSetHelper(779);
AddUnknownFields(optionalGroup, 1779);
[message setExtension:[UnittestRoot optionalGroupExtension] value:optionalGroup];
// Message
TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
nestedMessage.bb = 456;
nestedMessage.unknownFields = UnknownFieldsSetHelper(778);
AddUnknownFields(nestedMessage, 1778);
[message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage];
// Repeated Group
RepeatedGroup_extension *repeatedGroup = [[RepeatedGroup_extension alloc] init];
repeatedGroup.a = 567;
repeatedGroup.unknownFields = UnknownFieldsSetHelper(780);
AddUnknownFields(repeatedGroup, 1780);
[message addExtension:[UnittestRoot repeatedGroupExtension] value:repeatedGroup];
[repeatedGroup release];
@ -238,6 +304,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
nestedMessage.bb = 678;
nestedMessage.unknownFields = UnknownFieldsSetHelper(781);
AddUnknownFields(nestedMessage, 1781);
[message addExtension:[UnittestRoot repeatedNestedMessageExtension] value:nestedMessage];
[nestedMessage release];
}
@ -245,6 +312,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
// Confirm everything is there.
XCTAssertNotNil(message);
XCTAssertTrue(HasUnknownFields(message));
XCTAssertNotNil(message.unknownFields);
XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
@ -254,6 +322,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
[message getExtension:[UnittestRoot optionalGroupExtension]];
XCTAssertNotNil(optionalGroup);
XCTAssertEqual(optionalGroup.a, 123);
XCTAssertTrue(HasUnknownFields(optionalGroup));
XCTAssertNotNil(optionalGroup.unknownFields);
}
@ -263,6 +332,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
[message getExtension:[UnittestRoot optionalNestedMessageExtension]];
XCTAssertNotNil(nestedMessage);
XCTAssertEqual(nestedMessage.bb, 456);
XCTAssertTrue(HasUnknownFields(nestedMessage));
XCTAssertNotNil(nestedMessage.unknownFields);
}
@ -273,6 +343,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject;
XCTAssertNotNil(repeatedGroup);
XCTAssertEqual(repeatedGroup.a, 567);
XCTAssertTrue(HasUnknownFields(repeatedGroup));
XCTAssertNotNil(repeatedGroup.unknownFields);
}
@ -284,6 +355,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject;
XCTAssertNotNil(repeatedNestedMessage);
XCTAssertEqual(repeatedNestedMessage.bb, 678);
XCTAssertTrue(HasUnknownFields(repeatedNestedMessage));
XCTAssertNotNil(repeatedNestedMessage.unknownFields);
}
@ -293,6 +365,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
// Confirm unknowns are gone from within the messages.
XCTAssertNotNil(message);
XCTAssertFalse(HasUnknownFields(message));
XCTAssertNil(message.unknownFields);
XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
@ -302,6 +375,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
[message getExtension:[UnittestRoot optionalGroupExtension]];
XCTAssertNotNil(optionalGroup);
XCTAssertEqual(optionalGroup.a, 123);
XCTAssertFalse(HasUnknownFields(optionalGroup));
XCTAssertNil(optionalGroup.unknownFields);
}
@ -311,6 +385,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
[message getExtension:[UnittestRoot optionalNestedMessageExtension]];
XCTAssertNotNil(nestedMessage);
XCTAssertEqual(nestedMessage.bb, 456);
XCTAssertFalse(HasUnknownFields(nestedMessage));
XCTAssertNil(nestedMessage.unknownFields);
}
@ -321,6 +396,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject;
XCTAssertNotNil(repeatedGroup);
XCTAssertEqual(repeatedGroup.a, 567);
XCTAssertFalse(HasUnknownFields(repeatedGroup));
XCTAssertNil(repeatedGroup.unknownFields);
}
@ -332,6 +408,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject;
XCTAssertNotNil(repeatedNestedMessage);
XCTAssertEqual(repeatedNestedMessage.bb, 678);
XCTAssertFalse(HasUnknownFields(repeatedNestedMessage));
XCTAssertNil(repeatedNestedMessage.unknownFields);
}
}
@ -342,10 +419,12 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
{
ForeignMessage *foreignMessage = [ForeignMessage message];
foreignMessage.unknownFields = UnknownFieldsSetHelper(100);
AddUnknownFields(foreignMessage, 1000);
[message.mapInt32ForeignMessage setObject:foreignMessage forKey:100];
foreignMessage = [ForeignMessage message];
foreignMessage.unknownFields = UnknownFieldsSetHelper(101);
AddUnknownFields(foreignMessage, 1001);
[message.mapStringForeignMessage setObject:foreignMessage forKey:@"101"];
}
@ -356,12 +435,14 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
{
ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100];
XCTAssertNotNil(foreignMessage);
XCTAssertTrue(HasUnknownFields(foreignMessage));
XCTAssertNotNil(foreignMessage.unknownFields);
}
{
ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"];
XCTAssertNotNil(foreignMessage);
XCTAssertTrue(HasUnknownFields(foreignMessage));
XCTAssertNotNil(foreignMessage.unknownFields);
}
@ -374,12 +455,14 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
{
ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100];
XCTAssertNotNil(foreignMessage);
XCTAssertFalse(HasUnknownFields(foreignMessage));
XCTAssertNil(foreignMessage.unknownFields);
}
{
ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"];
XCTAssertNotNil(foreignMessage);
XCTAssertFalse(HasUnknownFields(foreignMessage));
XCTAssertNil(foreignMessage.unknownFields);
}
}

@ -5,11 +5,13 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#import "GPBTestUtilities.h"
#import "GPBCodedInputStream.h"
#import "GPBMessage_PackagePrivate.h"
#import "GPBTestUtilities.h"
#import "GPBUnknownField.h"
#import "GPBUnknownField_PackagePrivate.h"
#import "GPBUnknownFields.h"
#import "GPBWireFormat.h"
#import "objectivec/Tests/Unittest.pbobjc.h"
#import "objectivec/Tests/UnittestMset.pbobjc.h"
@ -110,32 +112,43 @@
}
const int kUnknownTypeId = 1550055;
const int kUnknownTypeId2 = 1550056;
- (void)testSerializeMessageSet {
// Set up a MSetMessage with two known messages and an unknown one.
MSetMessage* message_set = [MSetMessage message];
[[message_set getExtension:[MSetMessageExtension1 messageSetExtension]] setI:123];
[[message_set getExtension:[MSetMessageExtension2 messageSetExtension]] setStr:@"foo"];
GPBUnknownField* unknownField =
[[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease];
[unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]];
[unknownField addLengthDelimited:DataFromCStr("bar")];
GPBUnknownFieldSet* unknownFieldSet = [[[GPBUnknownFieldSet alloc] init] autorelease];
[unknownFieldSet addField:unknownField];
[message_set setUnknownFields:unknownFieldSet];
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
GPBUnknownFields* group = [ufs addGroupWithFieldNumber:GPBWireFormatMessageSetItem];
[group addFieldNumber:GPBWireFormatMessageSetTypeId varint:kUnknownTypeId2];
[group addFieldNumber:GPBWireFormatMessageSetMessage lengthDelimited:DataFromCStr("baz")];
[message_set mergeUnknownFields:ufs extensionRegistry:[MSetUnittestMsetRoot extensionRegistry]];
NSData* data = [message_set data];
// Parse back using MSetRawMessageSet and check the contents.
MSetRawMessageSet* raw = [MSetRawMessageSet parseFromData:data error:NULL];
GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:raw] autorelease];
XCTAssertTrue(ufs2.empty);
XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0);
XCTAssertEqual(raw.itemArray.count, (NSUInteger)3);
XCTAssertEqual(raw.itemArray.count, (NSUInteger)4);
XCTAssertEqual((uint32_t)[raw.itemArray[0] typeId],
[MSetMessageExtension1 messageSetExtension].fieldNumber);
XCTAssertEqual((uint32_t)[raw.itemArray[1] typeId],
[MSetMessageExtension2 messageSetExtension].fieldNumber);
XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId);
XCTAssertEqual([raw.itemArray[3] typeId], kUnknownTypeId2);
MSetMessageExtension1* message1 =
[MSetMessageExtension1 parseFromData:[((MSetRawMessageSet_Item*)raw.itemArray[0]) message]
@ -147,7 +160,8 @@ const int kUnknownTypeId = 1550055;
error:NULL];
XCTAssertEqualObjects(message2.str, @"foo");
XCTAssertEqualObjects([raw.itemArray[2] message], [NSData dataWithBytes:"bar" length:3]);
XCTAssertEqualObjects([raw.itemArray[2] message], DataFromCStr("bar"));
XCTAssertEqualObjects([raw.itemArray[3] message], DataFromCStr("baz"));
}
- (void)testParseMessageSet {
@ -175,7 +189,7 @@ const int kUnknownTypeId = 1550055;
{
MSetRawMessageSet_Item* item = [MSetRawMessageSet_Item message];
item.typeId = kUnknownTypeId;
item.message = [NSData dataWithBytes:"bar" length:3];
item.message = DataFromCStr("bar");
[raw.itemArray addObject:item];
}
@ -190,11 +204,100 @@ const int kUnknownTypeId = 1550055;
XCTAssertEqualObjects([[messageSet getExtension:[MSetMessageExtension2 messageSetExtension]] str],
@"foo");
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:messageSet] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
GPBUnknownFields* group = [ufs firstGroup:GPBWireFormatMessageSetItem];
XCTAssertNotNil(group);
XCTAssertEqual(group.count, (NSUInteger)2);
uint64_t varint = 0;
XCTAssertTrue([group getFirst:GPBWireFormatMessageSetTypeId varint:&varint]);
XCTAssertEqual(varint, kUnknownTypeId);
XCTAssertEqualObjects([group firstLengthDelimited:GPBWireFormatMessageSetMessage],
DataFromCStr("bar"));
XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1);
GPBUnknownField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId];
XCTAssertNotNil(unknownField);
XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1);
XCTAssertEqualObjects(unknownField.lengthDelimitedList[0], [NSData dataWithBytes:"bar" length:3]);
XCTAssertEqualObjects(unknownField.lengthDelimitedList[0], DataFromCStr("bar"));
}
- (void)testParseMessageSet_FirstValueSticks {
MSetRawBreakableMessageSet* raw = [MSetRawBreakableMessageSet message];
{
MSetRawBreakableMessageSet_Item* item = [MSetRawBreakableMessageSet_Item message];
[item.typeIdArray addValue:[MSetMessageExtension1 messageSetExtension].fieldNumber];
MSetMessageExtension1* message1 = [MSetMessageExtension1 message];
message1.i = 123;
NSData* itemData = [message1 data];
[item.messageArray addObject:itemData];
[item.typeIdArray addValue:[MSetMessageExtension2 messageSetExtension].fieldNumber];
MSetMessageExtension2* message2 = [MSetMessageExtension2 message];
message2.str = @"foo";
itemData = [message2 data];
[item.messageArray addObject:itemData];
[raw.itemArray addObject:item];
}
NSData* data = [raw data];
// Parse as a MSetMessage and check the contents.
NSError* err = nil;
MSetMessage* messageSet = [MSetMessage parseFromData:data
extensionRegistry:[MSetUnittestMsetRoot extensionRegistry]
error:&err];
XCTAssertNotNil(messageSet);
XCTAssertNil(err);
XCTAssertTrue([messageSet hasExtension:[MSetMessageExtension1 messageSetExtension]]);
XCTAssertEqual([[messageSet getExtension:[MSetMessageExtension1 messageSetExtension]] i], 123);
XCTAssertFalse([messageSet hasExtension:[MSetMessageExtension2 messageSetExtension]]);
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:messageSet] autorelease];
XCTAssertTrue(ufs.empty);
}
- (void)testParseMessageSet_PartialValuesDropped {
MSetRawBreakableMessageSet* raw = [MSetRawBreakableMessageSet message];
{
MSetRawBreakableMessageSet_Item* item = [MSetRawBreakableMessageSet_Item message];
[item.typeIdArray addValue:[MSetMessageExtension1 messageSetExtension].fieldNumber];
// No payload.
[raw.itemArray addObject:item];
}
{
MSetRawBreakableMessageSet_Item* item = [MSetRawBreakableMessageSet_Item message];
// No type ID.
MSetMessageExtension2* message = [MSetMessageExtension2 message];
message.str = @"foo";
NSData* itemData = [message data];
[item.messageArray addObject:itemData];
[raw.itemArray addObject:item];
}
{
MSetRawBreakableMessageSet_Item* item = [MSetRawBreakableMessageSet_Item message];
// Neither type ID nor payload.
[raw.itemArray addObject:item];
}
NSData* data = [raw data];
// Parse as a MSetMessage and check the contents.
NSError* err = nil;
MSetMessage* messageSet = [MSetMessage parseFromData:data
extensionRegistry:[MSetUnittestMsetRoot extensionRegistry]
error:&err];
XCTAssertNotNil(messageSet);
XCTAssertNil(err);
XCTAssertEqual([messageSet extensionsCurrentlySet].count,
(NSUInteger)0); // None because they were all partial and dropped.
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:messageSet] autorelease];
XCTAssertTrue(ufs.empty);
}
- (void)assertFieldsInOrder:(NSData*)data {

@ -14,6 +14,7 @@ option objc_class_prefix = "MSet";
// A message with message_set_wire_format.
message Message {
option message_set_wire_format = true;
extensions 4 to max;
}
@ -40,3 +41,12 @@ message RawMessageSet {
required bytes message = 3;
}
}
// MessageSet wire format is equivalent to this but since the fields
// are repeated they can be left off or over present to testing.
message RawBreakableMessageSet {
repeated group Item = 1 {
repeated int32 type_id = 2;
repeated bytes message = 3;
}
}

@ -7,11 +7,11 @@
syntax = "proto2";
package objc.protobuf.tests;
import "google/protobuf/any.proto";
import "objectivec/Tests/unittest.proto";
package objc.protobuf.tests;
// Explicit empty prefix, tests some validations code paths also.
option objc_class_prefix = "";
@ -167,7 +167,6 @@ message self {
}
extensions 3000 to 3999;
}
enum retain {
@ -700,13 +699,17 @@ message JustToScopeExtensions {
repeated string mutableCopy_val_lower_complex_repeated = 2711;
repeated string mutableCopy_Val_upper_complex_repeated = 2712;
repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 2713;
repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 2714;
repeated string mutableCopyvalue_lower_no_underscore_complex_repeated =
2713;
repeated string mutableCopyValue_upper_no_underscore_complex_repeated =
2714;
repeated int32 mutableCopy_val_lower_primitive_repeated = 2715;
repeated int32 mutableCopy_Val_upper_primitive_repeated = 2716;
repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 2717;
repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 2718;
repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated =
2717;
repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated =
2718;
repeated self mutableCopy_val_lower_message_repeated = 2719;
repeated self mutableCopy_Val_upper_message_repeated = 2720;
@ -794,6 +797,20 @@ message EnumTestMsg {
repeated MyEnum mumble = 4;
}
message EnumTestMsgPrime {
enum MyEnumPrime {
ZERO = 0;
ONE = 1;
NEG_ONE = -1;
// Lacks 2, -2.
}
optional MyEnumPrime foo = 1;
optional MyEnumPrime bar = 2 [default = ONE];
optional MyEnumPrime baz = 3 [default = NEG_ONE];
repeated MyEnumPrime mumble = 4;
}
// Test case for https://github.com/protocolbuffers/protobuf/issues/1453
// Message with no explicit defaults, but a non zero default for an enum.
message MessageWithOneBasedEnum {

@ -39,6 +39,14 @@ ExtensionGenerator::ExtensionGenerator(
ABSL_CHECK(!descriptor->is_map())
<< "error: Extension is a map<>!"
<< " That used to be blocked by the compiler.";
if (descriptor->containing_type()->options().message_set_wire_format()) {
ABSL_CHECK(descriptor->type() == FieldDescriptor::TYPE_MESSAGE)
<< "error: Extension to a message_set_wire_format message and the type "
"wasn't a message!";
ABSL_CHECK(!descriptor->is_repeated())
<< "error: Extension to a message_set_wire_format message should not "
"be repeated!";
}
}
void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) const {

@ -202,8 +202,12 @@ MessageGenerator::MessageGenerator(const std::string& file_description_name,
class_name_(ClassName(descriptor_)),
deprecated_attribute_(
GetOptionalDeprecatedAttribute(descriptor, descriptor->file())) {
ABSL_DCHECK(!descriptor->options().map_entry())
ABSL_CHECK(!descriptor->options().map_entry())
<< "error: MessageGenerator create of a map<>!";
ABSL_CHECK(!descriptor->options().message_set_wire_format() ||
descriptor->field_count() == 0)
<< "error: MessageGenerator message_set_wire_format should never have "
"fields!";
for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
oneof_generators_.push_back(std::make_unique<OneofGenerator>(
descriptor_->real_oneof_decl(i), generation_options));

Loading…
Cancel
Save