in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/wire_format.cc [417:633]
bool WireFormat::ParseAndMergeField(
uint32_t tag,
const FieldDescriptor* field, // May be nullptr for unknown
Message* message, io::CodedInputStream* input) {
const Reflection* message_reflection = message->GetReflection();
enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format;
if (field == nullptr) {
value_format = UNKNOWN;
} else if (WireFormatLite::GetTagWireType(tag) ==
WireTypeForFieldType(field->type())) {
value_format = NORMAL_FORMAT;
} else if (field->is_packable() &&
WireFormatLite::GetTagWireType(tag) ==
WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
value_format = PACKED_FORMAT;
} else {
// We don't recognize this field. Either the field number is unknown
// or the wire type doesn't match. Put it in our unknown field set.
value_format = UNKNOWN;
}
if (value_format == UNKNOWN) {
return SkipField(input, tag,
message_reflection->MutableUnknownFields(message));
} else if (value_format == PACKED_FORMAT) {
uint32_t length;
if (!input->ReadVarint32(&length)) return false;
io::CodedInputStream::Limit limit = input->PushLimit(length);
switch (field->type()) {
#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
while (input->BytesUntilLimit() > 0) { \
CPPTYPE value; \
if (!WireFormatLite::ReadPrimitive<CPPTYPE, \
WireFormatLite::TYPE_##TYPE>(input, \
&value)) \
return false; \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} \
break; \
}
HANDLE_PACKED_TYPE(INT32, int32_t, Int32)
HANDLE_PACKED_TYPE(INT64, int64_t, Int64)
HANDLE_PACKED_TYPE(SINT32, int32_t, Int32)
HANDLE_PACKED_TYPE(SINT64, int64_t, Int64)
HANDLE_PACKED_TYPE(UINT32, uint32_t, UInt32)
HANDLE_PACKED_TYPE(UINT64, uint64_t, UInt64)
HANDLE_PACKED_TYPE(FIXED32, uint32_t, UInt32)
HANDLE_PACKED_TYPE(FIXED64, uint64_t, UInt64)
HANDLE_PACKED_TYPE(SFIXED32, int32_t, Int32)
HANDLE_PACKED_TYPE(SFIXED64, int64_t, Int64)
HANDLE_PACKED_TYPE(FLOAT, float, Float)
HANDLE_PACKED_TYPE(DOUBLE, double, Double)
HANDLE_PACKED_TYPE(BOOL, bool, Bool)
#undef HANDLE_PACKED_TYPE
case FieldDescriptor::TYPE_ENUM: {
while (input->BytesUntilLimit() > 0) {
int value;
if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
input, &value))
return false;
if (message->GetDescriptor()->file()->syntax() ==
FileDescriptor::SYNTAX_PROTO3) {
message_reflection->AddEnumValue(message, field, value);
} else {
const EnumValueDescriptor* enum_value =
field->enum_type()->FindValueByNumber(value);
if (enum_value != nullptr) {
message_reflection->AddEnum(message, field, enum_value);
} else {
// The enum value is not one of the known values. Add it to the
// UnknownFieldSet.
int64_t sign_extended_value = static_cast<int64_t>(value);
message_reflection->MutableUnknownFields(message)->AddVarint(
WireFormatLite::GetTagFieldNumber(tag), sign_extended_value);
}
}
}
break;
}
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_BYTES:
// Can't have packed fields of these types: these should be caught by
// the protocol compiler.
return false;
break;
}
input->PopLimit(limit);
} else {
// Non-packed value (value_format == NORMAL_FORMAT)
switch (field->type()) {
#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
CPPTYPE value; \
if (!WireFormatLite::ReadPrimitive<CPPTYPE, WireFormatLite::TYPE_##TYPE>( \
input, &value)) \
return false; \
if (field->is_repeated()) { \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} else { \
message_reflection->Set##CPPTYPE_METHOD(message, field, value); \
} \
break; \
}
HANDLE_TYPE(INT32, int32_t, Int32)
HANDLE_TYPE(INT64, int64_t, Int64)
HANDLE_TYPE(SINT32, int32_t, Int32)
HANDLE_TYPE(SINT64, int64_t, Int64)
HANDLE_TYPE(UINT32, uint32_t, UInt32)
HANDLE_TYPE(UINT64, uint64_t, UInt64)
HANDLE_TYPE(FIXED32, uint32_t, UInt32)
HANDLE_TYPE(FIXED64, uint64_t, UInt64)
HANDLE_TYPE(SFIXED32, int32_t, Int32)
HANDLE_TYPE(SFIXED64, int64_t, Int64)
HANDLE_TYPE(FLOAT, float, Float)
HANDLE_TYPE(DOUBLE, double, Double)
HANDLE_TYPE(BOOL, bool, Bool)
#undef HANDLE_TYPE
case FieldDescriptor::TYPE_ENUM: {
int value;
if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
input, &value))
return false;
if (field->is_repeated()) {
message_reflection->AddEnumValue(message, field, value);
} else {
message_reflection->SetEnumValue(message, field, value);
}
break;
}
// Handle strings separately so that we can optimize the ctype=CORD case.
case FieldDescriptor::TYPE_STRING: {
bool strict_utf8_check = StrictUtf8Check(field);
std::string value;
if (!WireFormatLite::ReadString(input, &value)) return false;
if (strict_utf8_check) {
if (!WireFormatLite::VerifyUtf8String(value.data(), value.length(),
WireFormatLite::PARSE,
field->full_name().c_str())) {
return false;
}
} else {
VerifyUTF8StringNamedField(value.data(), value.length(), PARSE,
field->full_name().c_str());
}
if (field->is_repeated()) {
message_reflection->AddString(message, field, value);
} else {
message_reflection->SetString(message, field, value);
}
break;
}
case FieldDescriptor::TYPE_BYTES: {
std::string value;
if (!WireFormatLite::ReadBytes(input, &value)) return false;
if (field->is_repeated()) {
message_reflection->AddString(message, field, value);
} else {
message_reflection->SetString(message, field, value);
}
break;
}
case FieldDescriptor::TYPE_GROUP: {
Message* sub_message;
if (field->is_repeated()) {
sub_message = message_reflection->AddMessage(
message, field, input->GetExtensionFactory());
} else {
sub_message = message_reflection->MutableMessage(
message, field, input->GetExtensionFactory());
}
if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag),
input, sub_message))
return false;
break;
}
case FieldDescriptor::TYPE_MESSAGE: {
Message* sub_message;
if (field->is_repeated()) {
sub_message = message_reflection->AddMessage(
message, field, input->GetExtensionFactory());
} else {
sub_message = message_reflection->MutableMessage(
message, field, input->GetExtensionFactory());
}
if (!WireFormatLite::ReadMessage(input, sub_message)) return false;
break;
}
}
}
return true;
}