Index: third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc |
diff --git a/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc b/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc |
index c37e671cc22a3ae6124533fe1864aa9350b557f8..97a7909a185df2f61ac721b50109b57b21ef12c8 100644 |
--- a/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc |
+++ b/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc |
@@ -63,10 +63,7 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter( |
: ProtoWriter(type_resolver, type, output, listener), |
master_type_(type), |
current_(NULL), |
- options_(options) { |
- set_ignore_unknown_fields(options_.ignore_unknown_fields); |
- set_use_lower_camel_for_enums(options_.use_lower_camel_for_enums); |
-} |
+ options_(options) {} |
ProtoStreamObjectWriter::ProtoStreamObjectWriter( |
const TypeInfo* typeinfo, const google::protobuf::Type& type, |
@@ -193,11 +190,17 @@ ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {} |
void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { |
++depth_; |
// If an object writer is absent, that means we have not called StartAny() |
- // before reaching here, which happens when we have data before the "@type" |
- // field. |
+ // before reaching here. This is an invalid state. StartAny() gets called |
+ // whenever we see an "@type" being rendered (see AnyWriter::RenderDataPiece). |
if (ow_ == NULL) { |
- // Save data before the "@type" field for later replay. |
- uninterpreted_events_.push_back(Event(Event::START_OBJECT, name)); |
+ // Make sure we are not already in an invalid state. This avoids making |
+ // multiple unnecessary InvalidValue calls. |
+ if (!invalid_) { |
+ parent_->InvalidValue("Any", |
+ StrCat("Missing or invalid @type for any field in ", |
+ parent_->master_type_.name())); |
+ invalid_ = true; |
+ } |
} else if (is_well_known_type_ && depth_ == 1) { |
// For well-known types, the only other field besides "@type" should be a |
// "value" field. |
@@ -217,15 +220,10 @@ void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { |
bool ProtoStreamObjectWriter::AnyWriter::EndObject() { |
--depth_; |
- if (ow_ == NULL) { |
- if (depth_ >= 0) { |
- // Save data before the "@type" field for later replay. |
- uninterpreted_events_.push_back(Event(Event::END_OBJECT)); |
- } |
- } else if (depth_ >= 0 || !is_well_known_type_) { |
- // As long as depth_ >= 0, we know we haven't reached the end of Any. |
- // Propagate these EndObject() calls to the contained ow_. For regular |
- // message types, we propagate the end of Any as well. |
+ // As long as depth_ >= 0, we know we haven't reached the end of Any. |
+ // Propagate these EndObject() calls to the contained ow_. For regular |
+ // message types, we propagate the end of Any as well. |
+ if (ow_ != NULL && (depth_ >= 0 || !is_well_known_type_)) { |
ow_->EndObject(); |
} |
// A negative depth_ implies that we have reached the end of Any |
@@ -239,9 +237,14 @@ bool ProtoStreamObjectWriter::AnyWriter::EndObject() { |
void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) { |
++depth_; |
+ // We expect ow_ to be present as this call only makes sense inside an Any. |
if (ow_ == NULL) { |
- // Save data before the "@type" field for later replay. |
- uninterpreted_events_.push_back(Event(Event::START_LIST, name)); |
+ if (!invalid_) { |
+ parent_->InvalidValue("Any", |
+ StrCat("Missing or invalid @type for any field in ", |
+ parent_->master_type_.name())); |
+ invalid_ = true; |
+ } |
} else if (is_well_known_type_ && depth_ == 1) { |
if (name != "value" && !invalid_) { |
parent_->InvalidValue("Any", |
@@ -260,10 +263,8 @@ void ProtoStreamObjectWriter::AnyWriter::EndList() { |
GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible"; |
depth_ = 0; |
} |
- if (ow_ == NULL) { |
- // Save data before the "@type" field for later replay. |
- uninterpreted_events_.push_back(Event(Event::END_LIST)); |
- } else { |
+ // We don't write an error on the close, only on the open |
+ if (ow_ != NULL) { |
ow_->EndList(); |
} |
} |
@@ -275,8 +276,12 @@ void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( |
if (depth_ == 0 && ow_ == NULL && name == "@type") { |
StartAny(value); |
} else if (ow_ == NULL) { |
- // Save data before the "@type" field. |
- uninterpreted_events_.push_back(Event(name, value)); |
+ if (!invalid_) { |
+ parent_->InvalidValue("Any", |
+ StrCat("Missing or invalid @type for any field in ", |
+ parent_->master_type_.name())); |
+ invalid_ = true; |
+ } |
} else if (depth_ == 0 && is_well_known_type_) { |
if (name != "value" && !invalid_) { |
parent_->InvalidValue("Any", |
@@ -286,7 +291,7 @@ void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( |
if (well_known_type_render_ == NULL) { |
// Only Any and Struct don't have a special type render but both of |
// them expect a JSON object (i.e., a StartObject() call). |
- if (value.type() != DataPiece::TYPE_NULL && !invalid_) { |
+ if (!invalid_) { |
parent_->InvalidValue("Any", "Expect a JSON object."); |
invalid_ = true; |
} |
@@ -351,29 +356,13 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { |
if (!is_well_known_type_) { |
ow_->StartObject(""); |
} |
- |
- // Now we know the proto type and can interpret all data fields we gathered |
- // before the "@type" field. |
- for (int i = 0; i < uninterpreted_events_.size(); ++i) { |
- uninterpreted_events_[i].Replay(this); |
- } |
} |
void ProtoStreamObjectWriter::AnyWriter::WriteAny() { |
if (ow_ == NULL) { |
- if (uninterpreted_events_.empty()) { |
- // We never got any content, so just return immediately, which is |
- // equivalent to writing an empty Any. |
- return; |
- } else { |
- // There are uninterpreted data, but we never got a "@type" field. |
- if (!invalid_) { |
- parent_->InvalidValue("Any", StrCat("Missing @type for any field in ", |
- parent_->master_type_.name())); |
- invalid_ = true; |
- } |
- return; |
- } |
+ // If we had no object writer, we never got any content, so just return |
+ // immediately, which is equivalent to writing an empty Any. |
+ return; |
} |
// Render the type_url and value fields directly to the stream. |
// type_url has tag 1 and value has tag 2. |
@@ -383,41 +372,6 @@ void ProtoStreamObjectWriter::AnyWriter::WriteAny() { |
} |
} |
-void ProtoStreamObjectWriter::AnyWriter::Event::Replay( |
- AnyWriter* writer) const { |
- switch (type_) { |
- case START_OBJECT: |
- writer->StartObject(name_); |
- break; |
- case END_OBJECT: |
- writer->EndObject(); |
- break; |
- case START_LIST: |
- writer->StartList(name_); |
- break; |
- case END_LIST: |
- writer->EndList(); |
- break; |
- case RENDER_DATA_PIECE: |
- writer->RenderDataPiece(name_, value_); |
- break; |
- } |
-} |
- |
-void ProtoStreamObjectWriter::AnyWriter::Event::DeepCopy() { |
- // DataPiece only contains a string reference. To make sure the referenced |
- // string value stays valid, we make a copy of the string value and update |
- // DataPiece to reference our own copy. |
- if (value_.type() == DataPiece::TYPE_STRING) { |
- value_.str().AppendToString(&value_storage_); |
- value_ = DataPiece(value_storage_, value_.use_strict_base64_decoding()); |
- } else if (value_.type() == DataPiece::TYPE_BYTES) { |
- value_storage_ = value_.ToBytes().ValueOrDie(); |
- value_ = |
- DataPiece(value_storage_, true, value_.use_strict_base64_decoding()); |
- } |
-} |
- |
ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing, |
ItemType item_type, bool is_placeholder, |
bool is_list) |
@@ -430,9 +384,6 @@ ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing, |
if (item_type_ == ANY) { |
any_.reset(new AnyWriter(ow_)); |
} |
- if (item_type == MAP) { |
- map_keys_.reset(new hash_set<string>); |
- } |
} |
ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent, |
@@ -447,14 +398,11 @@ ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent, |
if (item_type == ANY) { |
any_.reset(new AnyWriter(ow_)); |
} |
- if (item_type == MAP) { |
- map_keys_.reset(new hash_set<string>); |
- } |
} |
bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent( |
StringPiece map_key) { |
- return InsertIfNotPresent(map_keys_.get(), map_key.ToString()); |
+ return InsertIfNotPresent(&map_keys_, map_key.ToString()); |
} |
ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( |
@@ -911,7 +859,6 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, |
Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow, |
const DataPiece& data) { |
- if (data.type() == DataPiece::TYPE_NULL) return Status::OK; |
if (data.type() != DataPiece::TYPE_STRING) { |
return Status(INVALID_ARGUMENT, |
StrCat("Invalid data type for timestamp, value is ", |
@@ -942,7 +889,6 @@ static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow, |
Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, |
const DataPiece& data) { |
- if (data.type() == DataPiece::TYPE_NULL) return Status::OK; |
if (data.type() != DataPiece::TYPE_STRING) { |
return Status(INVALID_ARGUMENT, |
StrCat("Invalid data type for field mask, value is ", |
@@ -953,13 +899,12 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, |
// conversions as much as possible. Because ToSnakeCase sometimes returns the |
// wrong value. |
google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback( |
- NewPermanentCallback(&RenderOneFieldPath, ow)); |
+ ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow)); |
return DecodeCompactFieldMaskPaths(data.str(), callback.get()); |
} |
Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow, |
const DataPiece& data) { |
- if (data.type() == DataPiece::TYPE_NULL) return Status::OK; |
if (data.type() != DataPiece::TYPE_STRING) { |
return Status(INVALID_ARGUMENT, |
StrCat("Invalid data type for duration, value is ", |
@@ -1009,7 +954,6 @@ Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow, |
Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow, |
const DataPiece& data) { |
- if (data.type() == DataPiece::TYPE_NULL) return Status::OK; |
ow->ProtoWriter::RenderDataPiece("value", data); |
return Status::OK; |
} |
@@ -1056,7 +1000,6 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( |
DataPiece(name, use_strict_base64_decoding())); |
field = Lookup("value"); |
if (field == NULL) { |
- Pop(); |
GOOGLE_LOG(DFATAL) << "Map does not have a value field."; |
return this; |
} |
@@ -1097,18 +1040,13 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( |
// Check if the field is of special type. Render it accordingly if so. |
const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url()); |
if (type_renderer != NULL) { |
- // Pass through null value only for google.protobuf.Value. For other |
- // types we ignore null value just like for regular field types. |
- if (data.type() != DataPiece::TYPE_NULL || |
- field->type_url() == kStructValueTypeUrl) { |
- Push(name, Item::MESSAGE, false, false); |
- status = (*type_renderer)(this, data); |
- if (!status.ok()) { |
- InvalidValue(field->type_url(), |
- StrCat("Field '", name, "', ", status.error_message())); |
- } |
- Pop(); |
+ Push(name, Item::MESSAGE, false, false); |
+ status = (*type_renderer)(this, data); |
+ if (!status.ok()) { |
+ InvalidValue(field->type_url(), |
+ StrCat("Field '", name, "', ", status.error_message())); |
} |
+ Pop(); |
return this; |
} |
@@ -1240,11 +1178,8 @@ bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) { |
// TODO(xiaofeng): Unify option names. |
return GetBoolOptionOrDefault(field_type->options(), |
- "google.protobuf.MessageOptions.map_entry", |
- false) || |
- GetBoolOptionOrDefault(field_type->options(), "map_entry", false) || |
- GetBoolOptionOrDefault(field_type->options(), |
- "proto2.MessageOptions.map_entry", false); |
+ "google.protobuf.MessageOptions.map_entry", false) || |
+ GetBoolOptionOrDefault(field_type->options(), "map_entry", false); |
} |
bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) { |
@@ -1269,4 +1204,3 @@ bool ProtoStreamObjectWriter::IsStructListValue( |
} // namespace util |
} // namespace protobuf |
} // namespace google |
- |