in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/text_format.cc [412:652]
bool ConsumeField(Message* message) {
const Reflection* reflection = message->GetReflection();
const Descriptor* descriptor = message->GetDescriptor();
std::string field_name;
bool reserved_field = false;
const FieldDescriptor* field = nullptr;
int start_line = tokenizer_.current().line;
int start_column = tokenizer_.current().column;
const FieldDescriptor* any_type_url_field;
const FieldDescriptor* any_value_field;
if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field,
&any_value_field) &&
TryConsume("[")) {
std::string full_type_name, prefix;
DO(ConsumeAnyTypeUrl(&full_type_name, &prefix));
std::string prefix_and_full_type_name =
StrCat(prefix, full_type_name);
DO(ConsumeBeforeWhitespace("]"));
TryConsumeWhitespace(prefix_and_full_type_name, "Any");
// ':' is optional between message labels and values.
TryConsumeBeforeWhitespace(":");
TryConsumeWhitespace(prefix_and_full_type_name, "Any");
std::string serialized_value;
const Descriptor* value_descriptor =
finder_ ? finder_->FindAnyType(*message, prefix, full_type_name)
: DefaultFinderFindAnyType(*message, prefix, full_type_name);
if (value_descriptor == nullptr) {
ReportError("Could not find type \"" + prefix_and_full_type_name +
"\" stored in google.protobuf.Any.");
return false;
}
DO(ConsumeAnyValue(value_descriptor, &serialized_value));
if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) {
// Fail if any_type_url_field has already been specified.
if ((!any_type_url_field->is_repeated() &&
reflection->HasField(*message, any_type_url_field)) ||
(!any_value_field->is_repeated() &&
reflection->HasField(*message, any_value_field))) {
ReportError("Non-repeated Any specified multiple times.");
return false;
}
}
reflection->SetString(message, any_type_url_field,
prefix_and_full_type_name);
reflection->SetString(message, any_value_field, serialized_value);
return true;
}
if (TryConsume("[")) {
// Extension.
DO(ConsumeFullTypeName(&field_name));
DO(ConsumeBeforeWhitespace("]"));
TryConsumeWhitespace(message->GetTypeName(), "Extension");
field = finder_ ? finder_->FindExtension(message, field_name)
: DefaultFinderFindExtension(message, field_name);
if (field == nullptr) {
if (!allow_unknown_field_ && !allow_unknown_extension_) {
ReportError("Extension \"" + field_name +
"\" is not defined or "
"is not an extension of \"" +
descriptor->full_name() + "\".");
return false;
} else {
ReportWarning("Ignoring extension \"" + field_name +
"\" which is not defined or is not an extension of \"" +
descriptor->full_name() + "\".");
}
}
} else {
DO(ConsumeIdentifierBeforeWhitespace(&field_name));
TryConsumeWhitespace(message->GetTypeName(), "Normal");
int32_t field_number;
if (allow_field_number_ && safe_strto32(field_name, &field_number)) {
if (descriptor->IsExtensionNumber(field_number)) {
field = finder_
? finder_->FindExtensionByNumber(descriptor, field_number)
: DefaultFinderFindExtensionByNumber(descriptor,
field_number);
} else if (descriptor->IsReservedNumber(field_number)) {
reserved_field = true;
} else {
field = descriptor->FindFieldByNumber(field_number);
}
} else {
field = descriptor->FindFieldByName(field_name);
// Group names are expected to be capitalized as they appear in the
// .proto file, which actually matches their type names, not their
// field names.
if (field == nullptr) {
std::string lower_field_name = field_name;
LowerString(&lower_field_name);
field = descriptor->FindFieldByName(lower_field_name);
// If the case-insensitive match worked but the field is NOT a group,
if (field != nullptr &&
field->type() != FieldDescriptor::TYPE_GROUP) {
field = nullptr;
}
}
// Again, special-case group names as described above.
if (field != nullptr && field->type() == FieldDescriptor::TYPE_GROUP &&
field->message_type()->name() != field_name) {
field = nullptr;
}
if (field == nullptr && allow_case_insensitive_field_) {
std::string lower_field_name = field_name;
LowerString(&lower_field_name);
field = descriptor->FindFieldByLowercaseName(lower_field_name);
}
if (field == nullptr) {
reserved_field = descriptor->IsReservedName(field_name);
}
}
if (field == nullptr && !reserved_field) {
if (!allow_unknown_field_) {
ReportError("Message type \"" + descriptor->full_name() +
"\" has no field named \"" + field_name + "\".");
return false;
} else {
ReportWarning("Message type \"" + descriptor->full_name() +
"\" has no field named \"" + field_name + "\".");
}
}
}
// Skips unknown or reserved fields.
if (field == nullptr) {
GOOGLE_CHECK(allow_unknown_field_ || allow_unknown_extension_ || reserved_field);
// Try to guess the type of this field.
// If this field is not a message, there should be a ":" between the
// field name and the field value and also the field value should not
// start with "{" or "<" which indicates the beginning of a message body.
// If there is no ":" or there is a "{" or "<" after ":", this field has
// to be a message or the input is ill-formed.
if (TryConsumeBeforeWhitespace(":")) {
TryConsumeWhitespace(message->GetTypeName(), "Unknown/Reserved");
if (!LookingAt("{") && !LookingAt("<")) {
return SkipFieldValue();
}
}
return SkipFieldMessage();
}
if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) {
// Fail if the field is not repeated and it has already been specified.
if (!field->is_repeated() && reflection->HasField(*message, field)) {
ReportError("Non-repeated field \"" + field_name +
"\" is specified multiple times.");
return false;
}
// Fail if the field is a member of a oneof and another member has already
// been specified.
const OneofDescriptor* oneof = field->containing_oneof();
if (oneof != nullptr && reflection->HasOneof(*message, oneof)) {
const FieldDescriptor* other_field =
reflection->GetOneofFieldDescriptor(*message, oneof);
ReportError("Field \"" + field_name +
"\" is specified along with "
"field \"" +
other_field->name() +
"\", another member "
"of oneof \"" +
oneof->name() + "\".");
return false;
}
}
// Perform special handling for embedded message types.
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
// ':' is optional here.
bool consumed_semicolon = TryConsumeBeforeWhitespace(":");
TryConsumeWhitespace(message->GetTypeName(), "Normal");
if (consumed_semicolon && field->options().weak() &&
LookingAtType(io::Tokenizer::TYPE_STRING)) {
// we are getting a bytes string for a weak field.
std::string tmp;
DO(ConsumeString(&tmp));
MessageFactory* factory =
finder_ ? finder_->FindExtensionFactory(field) : nullptr;
reflection->MutableMessage(message, field, factory)
->ParseFromString(tmp);
goto label_skip_parsing;
}
} else {
// ':' is required here.
DO(ConsumeBeforeWhitespace(":"));
TryConsumeWhitespace(message->GetTypeName(), "Normal");
}
if (field->is_repeated() && TryConsume("[")) {
// Short repeated format, e.g. "foo: [1, 2, 3]".
if (!TryConsume("]")) {
// "foo: []" is treated as empty.
while (true) {
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
// Perform special handling for embedded message types.
DO(ConsumeFieldMessage(message, reflection, field));
} else {
DO(ConsumeFieldValue(message, reflection, field));
}
if (TryConsume("]")) {
break;
}
DO(Consume(","));
}
}
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
DO(ConsumeFieldMessage(message, reflection, field));
} else {
DO(ConsumeFieldValue(message, reflection, field));
}
label_skip_parsing:
// For historical reasons, fields may optionally be separated by commas or
// semicolons.
TryConsume(";") || TryConsume(",");
if (field->options().deprecated()) {
ReportWarning("text format contains deprecated field \"" + field_name +
"\"");
}
// If a parse info tree exists, add the location for the parsed
// field.
if (parse_info_tree_ != nullptr) {
int end_line = tokenizer_.previous().line;
int end_column = tokenizer_.previous().end_column;
RecordLocation(parse_info_tree_, field,
ParseLocationRange(ParseLocation(start_line, start_column),
ParseLocation(end_line, end_column)));
}
return true;
}