|
|
|
@ -766,6 +766,44 @@ struct WireFormat::MessageSetParser { |
|
|
|
|
const Reflection* reflection; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const char* HandleMessage(Message* msg, const char* ptr, |
|
|
|
|
internal::ParseContext* ctx, uint64_t tag, |
|
|
|
|
const Reflection* reflection, |
|
|
|
|
const FieldDescriptor* field) { |
|
|
|
|
Message* sub_message; |
|
|
|
|
if (field->is_repeated()) { |
|
|
|
|
sub_message = reflection->AddMessage(msg, field, ctx->data().factory); |
|
|
|
|
} else { |
|
|
|
|
sub_message = reflection->MutableMessage(msg, field, ctx->data().factory); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (WireFormatLite::GetTagWireType(tag) == |
|
|
|
|
WireFormatLite::WIRETYPE_START_GROUP) { |
|
|
|
|
return ctx->ParseGroup(sub_message, ptr, tag); |
|
|
|
|
} else { |
|
|
|
|
ABSL_DCHECK(WireFormatLite::GetTagWireType(tag) == |
|
|
|
|
WireFormatLite::WIRETYPE_LENGTH_DELIMITED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ptr = ctx->ParseMessage(sub_message, ptr); |
|
|
|
|
|
|
|
|
|
// For map entries, if the value is an unknown enum we have to push it
|
|
|
|
|
// into the unknown field set and remove it from the list.
|
|
|
|
|
if (ptr != nullptr && field->is_map()) { |
|
|
|
|
auto* value_field = field->message_type()->map_value(); |
|
|
|
|
auto* enum_type = value_field->enum_type(); |
|
|
|
|
if (enum_type != nullptr && |
|
|
|
|
!internal::cpp::HasPreservingUnknownEnumSemantics(value_field) && |
|
|
|
|
enum_type->FindValueByNumber(sub_message->GetReflection()->GetEnumValue( |
|
|
|
|
*sub_message, value_field)) == nullptr) { |
|
|
|
|
reflection->MutableUnknownFields(msg)->AddLengthDelimited( |
|
|
|
|
field->number(), sub_message->SerializeAsString()); |
|
|
|
|
reflection->RemoveLast(msg, field); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return ptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char* WireFormat::_InternalParse(Message* msg, const char* ptr, |
|
|
|
|
internal::ParseContext* ctx) { |
|
|
|
|
const Descriptor* descriptor = msg->GetDescriptor(); |
|
|
|
@ -995,46 +1033,9 @@ const char* WireFormat::_InternalParseAndMergeField( |
|
|
|
|
return ptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case FieldDescriptor::TYPE_GROUP: { |
|
|
|
|
Message* sub_message; |
|
|
|
|
if (field->is_repeated()) { |
|
|
|
|
sub_message = reflection->AddMessage(msg, field, ctx->data().factory); |
|
|
|
|
} else { |
|
|
|
|
sub_message = |
|
|
|
|
reflection->MutableMessage(msg, field, ctx->data().factory); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ctx->ParseGroup(sub_message, ptr, tag); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case FieldDescriptor::TYPE_MESSAGE: { |
|
|
|
|
Message* sub_message; |
|
|
|
|
if (field->is_repeated()) { |
|
|
|
|
sub_message = reflection->AddMessage(msg, field, ctx->data().factory); |
|
|
|
|
} else { |
|
|
|
|
sub_message = |
|
|
|
|
reflection->MutableMessage(msg, field, ctx->data().factory); |
|
|
|
|
} |
|
|
|
|
ptr = ctx->ParseMessage(sub_message, ptr); |
|
|
|
|
|
|
|
|
|
// For map entries, if the value is an unknown enum we have to push it
|
|
|
|
|
// into the unknown field set and remove it from the list.
|
|
|
|
|
if (ptr != nullptr && field->is_map()) { |
|
|
|
|
auto* value_field = field->message_type()->map_value(); |
|
|
|
|
auto* enum_type = value_field->enum_type(); |
|
|
|
|
if (enum_type != nullptr && |
|
|
|
|
!internal::cpp::HasPreservingUnknownEnumSemantics(value_field) && |
|
|
|
|
enum_type->FindValueByNumber( |
|
|
|
|
sub_message->GetReflection()->GetEnumValue( |
|
|
|
|
*sub_message, value_field)) == nullptr) { |
|
|
|
|
reflection->MutableUnknownFields(msg)->AddLengthDelimited( |
|
|
|
|
field->number(), sub_message->SerializeAsString()); |
|
|
|
|
reflection->RemoveLast(msg, field); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ptr; |
|
|
|
|
} |
|
|
|
|
case FieldDescriptor::TYPE_MESSAGE: |
|
|
|
|
case FieldDescriptor::TYPE_GROUP: |
|
|
|
|
return HandleMessage(msg, ptr, ctx, tag, reflection, field); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GCC 8 complains about control reaching end of non-void function here.
|
|
|
|
|