Index: third_party/protobuf/src/google/protobuf/util/internal/proto_writer.cc |
diff --git a/third_party/protobuf/src/google/protobuf/util/internal/proto_writer.cc b/third_party/protobuf/src/google/protobuf/util/internal/proto_writer.cc |
index 36b7941095e695a26d9af410d43b58b86ccbb212..8bebf2ab1f7a6e83ed7dd6e3b093011338dfe50a 100644 |
--- a/third_party/protobuf/src/google/protobuf/util/internal/proto_writer.cc |
+++ b/third_party/protobuf/src/google/protobuf/util/internal/proto_writer.cc |
@@ -64,6 +64,8 @@ ProtoWriter::ProtoWriter(TypeResolver* type_resolver, |
typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), |
own_typeinfo_(true), |
done_(false), |
+ ignore_unknown_fields_(false), |
+ use_lower_camel_for_enums_(false), |
element_(NULL), |
size_insert_(), |
output_(output), |
@@ -81,6 +83,8 @@ ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, |
typeinfo_(typeinfo), |
own_typeinfo_(false), |
done_(false), |
+ ignore_unknown_fields_(false), |
+ use_lower_camel_for_enums_(false), |
element_(NULL), |
size_insert_(), |
output_(output), |
@@ -262,8 +266,9 @@ inline Status WriteString(int field_number, const DataPiece& data, |
// Writes an ENUM field, including tag, to the stream. |
inline Status WriteEnum(int field_number, const DataPiece& data, |
const google::protobuf::Enum* enum_type, |
- CodedOutputStream* stream) { |
- StatusOr<int> e = data.ToEnum(enum_type); |
+ CodedOutputStream* stream, |
+ bool use_lower_camel_for_enums) { |
+ StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums); |
if (e.ok()) { |
WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); |
} |
@@ -293,10 +298,16 @@ ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo, |
ow_(enclosing), |
parent_field_(NULL), |
typeinfo_(typeinfo), |
+ proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), |
type_(type), |
- required_fields_(GetRequiredFields(type)), |
size_index_(-1), |
- array_index_(-1) {} |
+ array_index_(-1), |
+ // oneof_indices_ values are 1-indexed (0 means not present). |
+ oneof_indices_(type.oneofs_size() + 1) { |
+ if (!proto3_) { |
+ required_fields_ = GetRequiredFields(type_); |
+ } |
+} |
ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, |
const google::protobuf::Field* field, |
@@ -306,22 +317,28 @@ ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, |
ow_(this->parent()->ow_), |
parent_field_(field), |
typeinfo_(this->parent()->typeinfo_), |
+ proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), |
type_(type), |
size_index_( |
!is_list && field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE |
? ow_->size_insert_.size() |
: -1), |
- array_index_(is_list ? 0 : -1) { |
+ array_index_(is_list ? 0 : -1), |
+ // oneof_indices_ values are 1-indexed (0 means not present). |
+ oneof_indices_(type_.oneofs_size() + 1) { |
if (!is_list) { |
if (ow_->IsRepeated(*field)) { |
// Update array_index_ if it is an explicit list. |
if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; |
- } else { |
+ } else if (!proto3_) { |
+ // For required fields tracking. |
this->parent()->RegisterField(field); |
} |
if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { |
- required_fields_ = GetRequiredFields(type_); |
+ if (!proto3_) { |
+ required_fields_ = GetRequiredFields(type_); |
+ } |
int start_pos = ow_->stream_->ByteCount(); |
// length of serialized message is the final buffer position minus |
// starting buffer position, plus length adjustments for size fields |
@@ -334,12 +351,14 @@ ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, |
} |
ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() { |
- // Calls the registered error listener for any required field(s) not yet |
- // seen. |
- for (set<const google::protobuf::Field*>::iterator it = |
- required_fields_.begin(); |
- it != required_fields_.end(); ++it) { |
- ow_->MissingField((*it)->name()); |
+ if (!proto3_) { |
+ // Calls the registered error listener for any required field(s) not yet |
+ // seen. |
+ for (std::set<const google::protobuf::Field*>::iterator it = |
+ required_fields_.begin(); |
+ it != required_fields_.end(); ++it) { |
+ ow_->MissingField((*it)->name()); |
+ } |
} |
// Computes the total number of proto bytes used by a message, also adjusts |
// the size of all parent messages by the length of this size field. |
@@ -399,11 +418,11 @@ string ProtoWriter::ProtoElement::ToString() const { |
} |
bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) { |
- return ContainsKey(oneof_indices_, index); |
+ return oneof_indices_[index]; |
} |
void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) { |
- InsertIfNotPresent(&oneof_indices_, index); |
+ oneof_indices_[index] = true; |
} |
void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) { |
@@ -561,10 +580,19 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField( |
// Pushing a ProtoElement and then pop it off at the end for 2 purposes: |
// error location reporting and required field accounting. |
- element_.reset(new ProtoElement(element_.release(), &field, type, false)); |
+ // |
+ // For proto3, since there is no required field tracking, we only need to push |
+ // ProtoElement for error cases. |
+ if (!element_->proto3()) { |
+ element_.reset(new ProtoElement(element_.release(), &field, type, false)); |
+ } |
if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN || |
field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { |
+ // Push a ProtoElement for location reporting purposes. |
+ if (element_->proto3()) { |
+ element_.reset(new ProtoElement(element_.release(), &field, type, false)); |
+ } |
InvalidValue(field.type_url().empty() |
? google::protobuf::Field_Kind_Name(field.kind()) |
: field.type_url(), |
@@ -637,7 +665,7 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField( |
case google::protobuf::Field_Kind_TYPE_ENUM: { |
status = WriteEnum(field.number(), data, |
typeinfo_->GetEnumByTypeUrl(field.type_url()), |
- stream_.get()); |
+ stream_.get(), use_lower_camel_for_enums_); |
break; |
} |
default: // TYPE_GROUP or TYPE_MESSAGE |
@@ -645,11 +673,18 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField( |
} |
if (!status.ok()) { |
+ // Push a ProtoElement for location reporting purposes. |
+ if (element_->proto3()) { |
+ element_.reset(new ProtoElement(element_.release(), &field, type, false)); |
+ } |
InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), |
status.error_message()); |
+ element_.reset(element()->pop()); |
+ return this; |
} |
- element_.reset(element()->pop()); |
+ if (!element_->proto3()) element_.reset(element()->pop()); |
+ |
return this; |
} |
@@ -692,7 +727,9 @@ const google::protobuf::Field* ProtoWriter::Lookup( |
} |
const google::protobuf::Field* field = |
typeinfo_->FindField(&e->type(), unnormalized_name); |
- if (field == NULL) InvalidName(unnormalized_name, "Cannot find field."); |
+ if (field == NULL && !ignore_unknown_fields_) { |
+ InvalidName(unnormalized_name, "Cannot find field."); |
+ } |
return field; |
} |