diff options
author | Jisi Liu <jisi.liu@gmail.com> | 2015-10-05 11:59:43 -0700 |
---|---|---|
committer | Jisi Liu <jisi.liu@gmail.com> | 2015-10-05 11:59:43 -0700 |
commit | 46e8ff63cb67a6520711da5317aaaef04d0414d0 (patch) | |
tree | 64370726fe469f8dfca7b14f8b8cb80b6cc856f6 /src/google/protobuf/util/internal | |
parent | 0087da9d4775f79c67362cc89c653f3a33a9bae2 (diff) |
Down-integrate from google internal.
Diffstat (limited to 'src/google/protobuf/util/internal')
9 files changed, 207 insertions, 46 deletions
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h index d4547601..bcb526e8 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.h +++ b/src/google/protobuf/util/internal/default_value_objectwriter.h @@ -110,7 +110,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // "Node" represents a node in the tree that holds the input of // DefaultValueObjectWriter. - class Node { + class LIBPROTOBUF_EXPORT Node { public: Node(const string& name, const google::protobuf::Type* type, NodeKind kind, const DataPiece& data, bool is_placeholder); diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc index f81e3306..94d2ab7a 100644 --- a/src/google/protobuf/util/internal/json_objectwriter.cc +++ b/src/google/protobuf/util/internal/json_objectwriter.cc @@ -37,8 +37,8 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/util/internal/utility.h> #include <google/protobuf/util/internal/json_escaping.h> -#include <google/protobuf/stubs/mathlimits.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/mathlimits.h> namespace google { namespace protobuf { @@ -116,7 +116,7 @@ JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name, JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name, double value) { - if (google::protobuf::MathLimits<double>::IsFinite(value)) { + if (MathLimits<double>::IsFinite(value)) { return RenderSimple(name, SimpleDtoa(value)); } @@ -126,7 +126,7 @@ JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name, JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, float value) { - if (google::protobuf::MathLimits<float>::IsFinite(value)) { + if (MathLimits<float>::IsFinite(value)) { return RenderSimple(name, SimpleFtoa(value)); } diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 996e1f8c..aebf19a1 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -47,7 +47,6 @@ #include <google/protobuf/util/internal/utility.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/once.h> #include <google/protobuf/stubs/status_macros.h> @@ -140,6 +139,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, const uint32 end_tag, bool include_start_and_end, ObjectWriter* ow) const { + const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); if (type_renderer != NULL) { return (*type_renderer)(this, type, name, ow); @@ -332,10 +332,9 @@ Status ProtoStreamObjectSource::RenderDuration( if (seconds < 0) { if (nanos > 0) { return Status(util::error::INTERNAL, - StrCat( - "Duration nanos is non-negative, but seconds is " - "negative for field: ", - field_name)); + StrCat("Duration nanos is non-negative, but seconds is " + "negative for field: ", + field_name)); } sign = "-"; seconds = -seconds; @@ -648,6 +647,7 @@ Status ProtoStreamObjectSource::RenderFieldMask( return Status::OK; } + hash_map<string, ProtoStreamObjectSource::TypeRenderer>* ProtoStreamObjectSource::renderers_ = NULL; GOOGLE_PROTOBUF_DECLARE_ONCE(source_renderers_init_); @@ -670,13 +670,16 @@ void ProtoStreamObjectSource::InitRendererMap() { &ProtoStreamObjectSource::RenderInt32; (*renderers_)["google.protobuf.UInt32Value"] = &ProtoStreamObjectSource::RenderUInt32; - (*renderers_)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool; + (*renderers_)["google.protobuf.BoolValue"] = + &ProtoStreamObjectSource::RenderBool; (*renderers_)["google.protobuf.StringValue"] = &ProtoStreamObjectSource::RenderString; (*renderers_)["google.protobuf.BytesValue"] = &ProtoStreamObjectSource::RenderBytes; - (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny; - (*renderers_)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct; + (*renderers_)["google.protobuf.Any"] = + &ProtoStreamObjectSource::RenderAny; + (*renderers_)["google.protobuf.Struct"] = + &ProtoStreamObjectSource::RenderStruct; (*renderers_)["google.protobuf.Value"] = &ProtoStreamObjectSource::RenderStructValue; (*renderers_)["google.protobuf.ListValue"] = @@ -835,6 +838,7 @@ Status ProtoStreamObjectSource::RenderField( StrCat("Invalid configuration. Could not find the type: ", field->type_url())); } + RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow)); if (!stream_->ConsumedEntireMessage()) { return Status(util::error::INVALID_ARGUMENT, @@ -988,7 +992,7 @@ std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( uint32 nanos = 0; uint32 tag = 0; int64 signed_seconds = 0; - int64 signed_nanos = 0; + int32 signed_nanos = 0; for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { const google::protobuf::Field* field = FindAndVerifyField(type, tag); diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h index f52383a1..3cd37aa1 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.h +++ b/src/google/protobuf/util/internal/protostream_objectsource.h @@ -188,8 +188,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter. static util::Status RenderStructListValue( - const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece name, ObjectWriter* ow); // Render the "Any" type. @@ -211,6 +210,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { util::Status RenderField(const google::protobuf::Field* field, StringPiece field_name, ObjectWriter* ow) const; + // Reads field value according to Field spec in 'field' and returns the read // value as string. This only works for primitive datatypes (no message // types). diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index a935ac39..bd245999 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -33,13 +33,13 @@ #include <functional> #include <stack> +#include <google/protobuf/stubs/once.h> #include <google/protobuf/stubs/time.h> #include <google/protobuf/wire_format_lite.h> #include <google/protobuf/util/internal/field_mask_utility.h> #include <google/protobuf/util/internal/object_location_tracker.h> #include <google/protobuf/util/internal/constants.h> #include <google/protobuf/util/internal/utility.h> -#include <google/protobuf/stubs/once.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/map_util.h> #include <google/protobuf/stubs/statusor.h> @@ -397,8 +397,8 @@ void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( const TypeRenderer* type_renderer = FindTypeRenderer(GetFullTypeWithUrl(ow_->master_type_.name())); if (type_renderer) { - // TODO(rikka): Don't just ignore the util::Status object! - (*type_renderer)(ow_.get(), value); + Status status = (*type_renderer)(ow_.get(), value); + if (!status.ok()) ow_->InvalidValue("Any", status.error_message()); } else { ow_->RenderDataPiece(name, value); } @@ -600,6 +600,11 @@ void ProtoStreamObjectWriter::ProtoElement::TakeOneofIndex(int32 index) { InsertIfNotPresent(&oneof_indices_, index); } +bool ProtoStreamObjectWriter::ProtoElement::InsertMapKeyIfNotPresent( + StringPiece map_key) { + return InsertIfNotPresent(&map_keys_, map_key); +} + inline void ProtoStreamObjectWriter::InvalidName(StringPiece unknown_name, StringPiece message) { listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); @@ -643,6 +648,11 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( return this; } else if (element_ != NULL && (element_->IsMap() || element_->IsStructMap())) { + if (!ValidMapKey(name)) { + ++invalid_depth_; + return this; + } + field = StartMapEntry(name); if (element_->IsStructMapEntry()) { // If the top element is a map entry, this means we are starting another @@ -698,7 +708,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( element_.reset( new ProtoElement(element_.release(), field, *type, ProtoElement::MAP)); } else { - WriteTag(*field); + WriteTag(*field); element_.reset(new ProtoElement(element_.release(), field, *type, ProtoElement::MESSAGE)); } @@ -863,6 +873,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() { // struct. SkipElements(); + // If ending the root element, // then serialize the full message with calculated sizes. if (element_ == NULL) { @@ -914,6 +925,11 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { // Check if we need to start a map. This can heppen when there is either a map // or a struct type within a list. if (element_->IsMap() || element_->IsStructMap()) { + if (!ValidMapKey(name)) { + ++invalid_depth_; + return this; + } + field = StartMapEntry(name); if (field == NULL) return this; @@ -969,7 +985,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { ProtoElement::MESSAGE)); InvalidValue("Map", "Cannot bind a list to map."); ++invalid_depth_; - element_->pop(); + element_.reset(element_->pop()); return this; } @@ -1188,6 +1204,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( type_url = GetFullTypeWithUrl(master_type_.name()); } else { if (element_->IsMap() || element_->IsStructMap()) { + if (!ValidMapKey(name)) return this; is_map_entry = true; field = StartMapEntry(name); } else { @@ -1462,6 +1479,19 @@ bool ProtoStreamObjectWriter::ValidOneof(const google::protobuf::Field& field, return true; } +bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) { + if (element_ == NULL) return true; + + if (!element_->InsertMapKeyIfNotPresent(unnormalized_name)) { + InvalidName( + unnormalized_name, + StrCat("Repeated map key: '", unnormalized_name, "' is already set.")); + return false; + } + + return true; +} + const google::protobuf::Field* ProtoStreamObjectWriter::BeginNamed( StringPiece name, bool is_list) { if (invalid_depth_ > 0) { @@ -1614,6 +1644,7 @@ void ProtoStreamObjectWriter::WriteTag(const google::protobuf::Field& field) { stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); } + } // namespace converter } // namespace util } // namespace protobuf diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h index 8f49120b..19f747fe 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.h +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -259,6 +259,13 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter // generate an error. void TakeOneofIndex(int32 index); + // Inserts map key into hash set if and only if the key did NOT already + // exist in hash set. + // The hash set (map_keys_) is ONLY used to keep track of map keys. + // Return true if insert successfully; returns false if the map key was + // already present. + bool InsertMapKeyIfNotPresent(StringPiece map_key); + private: // Used for access to variables of the enclosing instance of // ProtoStreamObjectWriter. @@ -296,6 +303,10 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter // incoming messages so no more than one oneof is set. hash_set<int32> oneof_indices_; + // Set of map keys already seen for the type_. Used to validate incoming + // messages so no map key appears more than once. + hash_set<StringPiece> map_keys_; + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement); }; @@ -378,6 +389,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter // Helper method to write proto tags based on the given field. void WriteTag(const google::protobuf::Field& field); + // Helper function to render primitive data types in DataPiece. void RenderSimpleDataPiece(const google::protobuf::Field& field, const google::protobuf::Type& type, @@ -424,6 +436,14 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter bool ValidOneof(const google::protobuf::Field& field, StringPiece unnormalized_name); + // Returns true if the map key for type_ is not duplicated key. + // If map key is duplicated key, this function returns false. + // Note that caller should make sure that the current proto element (element_) + // is of element type MAP or STRUCT_MAP. + // It also calls the appropriate error callback and unnormalzied_name is used + // for error string. + bool ValidMapKey(StringPiece unnormalized_name); + // Variables for describing the structure of the input tree: // master_type_: descriptor for the whole protobuf message. // typeinfo_ : the TypeInfo object to lookup types. diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc index 96e5ccfb..941fa71a 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -45,6 +45,7 @@ #include <google/protobuf/util/internal/testdata/field_mask.pb.h> #include <google/protobuf/util/internal/type_info_test_helper.h> #include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/util/message_differencer.h> #include <google/protobuf/stubs/bytestream.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/util/internal/testdata/anys.pb.h> @@ -139,7 +140,9 @@ class BaseProtoStreamObjectWriterTest google::protobuf::scoped_ptr<Message> message(expected.New()); message->ParsePartialFromIstream(&istream); - EXPECT_EQ(expected.DebugString(), message->DebugString()); + if (!MessageDifferencer::Equivalent(expected, *message)) { + EXPECT_EQ(expected.DebugString(), message->DebugString()); + } } void CheckOutput(const Message& expected) { CheckOutput(expected, -1); } @@ -851,15 +854,19 @@ class ProtoStreamObjectWriterTimestampDurationTest } }; +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtoStreamObjectWriterTimestampDurationTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) { TimestampDuration timestamp; EXPECT_CALL( listener_, - InvalidValue( - _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Illegal timestamp format; timestamps " - "must end with 'Z'"))); + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: "))); ow_->StartObject("")->RenderString("ts", "")->EndObject(); CheckOutput(timestamp); @@ -870,10 +877,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) { EXPECT_CALL( listener_, - InvalidValue( - _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece( - "Field 'ts', Invalid time format: Failed to parse input"))); + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: Z"))); ow_->StartObject("")->RenderString("ts", "Z")->EndObject(); CheckOutput(timestamp); @@ -884,10 +890,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) { EXPECT_CALL( listener_, - InvalidValue( - _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Invalid time format, failed to parse nano " - "seconds"))); + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Invalid time format: " + "1970-01-01T00:00:00.ABZ"))); ow_->StartObject("") ->RenderString("ts", "1970-01-01T00:00:00.ABZ") @@ -902,7 +908,8 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) { listener_, InvalidValue(_, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), - StringPiece("Field 'ts', Timestamp value exceeds limits"))); + StringPiece("Field 'ts', Invalid time format: " + "-8032-10-18T00:00:00.000Z"))); ow_->StartObject("") ->RenderString("ts", "-8032-10-18T00:00:00.000Z") @@ -1008,6 +1015,11 @@ class ProtoStreamObjectWriterStructTest } }; +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtoStreamObjectWriterStructTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + // TODO(skarvaje): Write tests for failure cases. TEST_P(ProtoStreamObjectWriterStructTest, StructRenderSuccess) { StructType struct_type; @@ -1046,12 +1058,62 @@ TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) { CheckOutput(struct_type); } +TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) { + EXPECT_CALL( + listener_, + InvalidName(_, StringPiece("k1"), + StringPiece("Repeated map key: 'k1' is already set."))); + ow_->StartObject("") + ->StartObject("object") + ->RenderString("k1", "v1") + ->RenderString("k1", "v2") + ->EndObject() + ->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapListKeyTest) { + EXPECT_CALL( + listener_, + InvalidName(_, StringPiece("k1"), + StringPiece("Repeated map key: 'k1' is already set."))); + ow_->StartObject("") + ->StartObject("object") + ->RenderString("k1", "v1") + ->StartList("k1") + ->RenderString("", "v2") + ->EndList() + ->EndObject() + ->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapObjectKeyTest) { + EXPECT_CALL( + listener_, + InvalidName(_, StringPiece("k1"), + StringPiece("Repeated map key: 'k1' is already set."))); + ow_->StartObject("") + ->StartObject("object") + ->StartObject("k1") + ->RenderString("sub_k1", "v1") + ->EndObject() + ->StartObject("k1") + ->RenderString("sub_k2", "v2") + ->EndObject() + ->EndObject() + ->EndObject(); +} + class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest { protected: ProtoStreamObjectWriterMapTest() : BaseProtoStreamObjectWriterTest(MapIn::descriptor()) {} }; +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtoStreamObjectWriterMapTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) { MapIn mm; EXPECT_CALL(listener_, @@ -1066,17 +1128,37 @@ TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) { CheckOutput(mm); } +TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) { + EXPECT_CALL( + listener_, + InvalidName(_, StringPiece("k1"), + StringPiece("Repeated map key: 'k1' is already set."))); + ow_->StartObject("") + ->RenderString("other", "test") + ->StartObject("map_input") + ->RenderString("k1", "v1") + ->RenderString("k1", "v2") + ->EndObject() + ->EndObject(); +} + class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest { protected: ProtoStreamObjectWriterAnyTest() { vector<const Descriptor*> descriptors; descriptors.push_back(AnyOut::descriptor()); descriptors.push_back(google::protobuf::DoubleValue::descriptor()); + descriptors.push_back(google::protobuf::Timestamp::descriptor()); descriptors.push_back(google::protobuf::Any::descriptor()); ResetTypeInfo(descriptors); } }; +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtoStreamObjectWriterAnyTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) { AnyOut any; google::protobuf::Any* any_type = any.mutable_any(); @@ -1119,8 +1201,6 @@ TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) { ->EndObject() ->EndObject() ->EndObject(); - - CheckOutput(out, 115); } TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) { @@ -1155,8 +1235,6 @@ TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) { ->EndObject() ->EndObject() ->EndObject(); - - CheckOutput(out, 159); } TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) { @@ -1263,6 +1341,23 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyNullInputFails) { CheckOutput(any); } +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) { + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"), + StringPiece("Invalid time format: "))); + + AnyOut any; + google::protobuf::Any* any_type = any.mutable_any(); + any_type->set_type_url("type.googleapis.com/google.protobuf.Timestamp"); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp") + ->RenderString("value", "") + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + class ProtoStreamObjectWriterFieldMaskTest : public BaseProtoStreamObjectWriterTest { protected: @@ -1274,6 +1369,11 @@ class ProtoStreamObjectWriterFieldMaskTest } }; +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtoStreamObjectWriterFieldMaskTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) { FieldMaskTest expected; expected.set_id("1"); @@ -1683,6 +1783,7 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, ow_->RenderString("strData", "blah"); ow_->RenderInt32("intData", 123); ow_->EndObject(); + ow_->EndObject(); } } // namespace converter diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc index 5d7dcc87..61899c24 100644 --- a/src/google/protobuf/util/internal/utility.cc +++ b/src/google/protobuf/util/internal/utility.cc @@ -298,16 +298,21 @@ bool IsMap(const google::protobuf::Field& field, "google.protobuf.MessageOptions.map_entry", false)); } +bool IsMessageSetWireFormat(const google::protobuf::Type& type) { + return GetBoolOptionOrDefault( + type.options(), "google.protobuf.MessageOptions.message_set_wire_format", false); +} + string DoubleAsString(double value) { - if (google::protobuf::MathLimits<double>::IsPosInf(value)) return "Infinity"; - if (google::protobuf::MathLimits<double>::IsNegInf(value)) return "-Infinity"; - if (google::protobuf::MathLimits<double>::IsNaN(value)) return "NaN"; + if (MathLimits<double>::IsPosInf(value)) return "Infinity"; + if (MathLimits<double>::IsNegInf(value)) return "-Infinity"; + if (MathLimits<double>::IsNaN(value)) return "NaN"; return SimpleDtoa(value); } string FloatAsString(float value) { - if (google::protobuf::MathLimits<float>::IsFinite(value)) return SimpleFtoa(value); + if (MathLimits<float>::IsFinite(value)) return SimpleFtoa(value); return DoubleAsString(value); } @@ -318,7 +323,7 @@ bool SafeStrToFloat(StringPiece str, float *value) { } *value = static_cast<float>(double_value); - if (google::protobuf::MathLimits<float>::IsInf(*value)) { + if (MathLimits<float>::IsInf(*value)) { return false; } return true; diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h index 87f7602a..5ba97bd2 100644 --- a/src/google/protobuf/util/internal/utility.h +++ b/src/google/protobuf/util/internal/utility.h @@ -138,9 +138,6 @@ const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( const google::protobuf::Enum* enum_type, int32 value); // Converts input to camel-case and returns it. -// Tests are in wrappers/translator/snake2camel_objectwriter_test.cc -// TODO(skarvaje): Isolate tests for this function and put them in -// utility_test.cc LIBPROTOBUF_EXPORT string ToCamelCase(const StringPiece input); // Converts input to snake_case and returns it. @@ -157,6 +154,9 @@ LIBPROTOBUF_EXPORT bool IsValidBoolString(const string& bool_string); LIBPROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field, const google::protobuf::Type& type); +// Returns true if the given type has special MessageSet wire format. +bool IsMessageSetWireFormat(const google::protobuf::Type& type); + // Infinity/NaN-aware conversion to string. LIBPROTOBUF_EXPORT string DoubleAsString(double value); LIBPROTOBUF_EXPORT string FloatAsString(float value); |