diff options
Diffstat (limited to 'src/google/protobuf/util/internal/protostream_objectwriter.h')
-rw-r--r-- | src/google/protobuf/util/internal/protostream_objectwriter.h | 122 |
1 files changed, 109 insertions, 13 deletions
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h index 08ac6e33..c33a4639 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.h +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -74,10 +74,44 @@ class ObjectLocationTracker; // It also supports streaming. class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { public: + // Options that control ProtoStreamObjectWriter class's behavior. + struct Options { + // Treats numeric inputs in google.protobuf.Struct as strings. Normally, + // numeric values are returned in double field "number_value" of + // google.protobuf.Struct. However, this can cause precision loss for + // int64/uint64/double inputs. This option is provided for cases that want + // to preserve number precision. + // + // TODO(skarvaje): Rename to struct_numbers_as_strings as it covers double + // as well. + bool struct_integers_as_strings; + + // Not treat unknown fields as an error. If there is an unknown fields, + // just ignore it and continue to process the rest. + bool ignore_unknown_fields; + + // If true, check if enum name in camel case or without underscore matches + // the field name. + bool use_lower_camel_for_enums; + + Options() + : struct_integers_as_strings(false), + ignore_unknown_fields(false), + use_lower_camel_for_enums(false) {} + + // Default instance of Options with all options set to defaults. + static const Options& Defaults() { + static Options defaults; + return defaults; + } + }; + // Constructor. Does not take ownership of any parameter passed in. ProtoStreamObjectWriter(TypeResolver* type_resolver, const google::protobuf::Type& type, - strings::ByteSink* output, ErrorListener* listener); + strings::ByteSink* output, ErrorListener* listener, + const ProtoStreamObjectWriter::Options& options = + ProtoStreamObjectWriter::Options::Defaults()); virtual ~ProtoStreamObjectWriter(); // ObjectWriter methods. @@ -120,6 +154,57 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { void RenderDataPiece(StringPiece name, const DataPiece& value); private: + // Before the "@type" field is encountered, we store all incoming data + // into this Event struct and replay them after we get the "@type" field. + class LIBPROTOBUF_EXPORT Event { + public: + enum Type { + START_OBJECT = 0, + END_OBJECT = 1, + START_LIST = 2, + END_LIST = 3, + RENDER_DATA_PIECE = 4, + }; + + // Constructor for END_OBJECT and END_LIST events. + explicit Event(Type type) : type_(type), value_(DataPiece::NullData()) {} + + // Constructor for START_OBJECT and START_LIST events. + explicit Event(Type type, StringPiece name) + : type_(type), + name_(name.ToString()), + value_(DataPiece::NullData()) {} + + // Constructor for RENDER_DATA_PIECE events. + explicit Event(StringPiece name, const DataPiece& value) + : type_(RENDER_DATA_PIECE), name_(name.ToString()), value_(value) { + DeepCopy(); + } + + Event(const Event& other) + : type_(other.type_), name_(other.name_), value_(other.value_) { + DeepCopy(); + } + + Event& operator=(const Event& other) { + type_ = other.type_; + name_ = other.name_; + value_ = other.value_; + DeepCopy(); + return *this; + } + + void Replay(AnyWriter* writer) const; + + private: + void DeepCopy(); + + Type type_; + string name_; + DataPiece value_; + string value_storage_; + }; + // Handles starting up the any once we have a type. void StartAny(const DataPiece& value); @@ -131,7 +216,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { ProtoStreamObjectWriter* parent_; // The nested object writer, used to write events. - google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_; + std::unique_ptr<ProtoStreamObjectWriter> ow_; // The type_url_ that this Any represents. string type_url_; @@ -147,9 +232,17 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // The depth within the Any, so we can track when we're done. int depth_; - // True if the message type contained in Any has a special "value" message - // injected. This is true for well-known message types like Any or Struct. - bool has_injected_value_message_; + // True if the type is a well-known type. Well-known types in Any + // has a special formating: + // { + // "@type": "type.googleapis.com/google.protobuf.XXX", + // "value": <JSON representation of the type>, + // } + bool is_well_known_type_; + TypeRenderer* well_known_type_render_; + + // Store data before the "@type" field. + std::vector<Event> uninterpreted_events_; }; // Represents an item in a stack of items used to keep state between @@ -199,14 +292,14 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { ProtoStreamObjectWriter* ow_; // A writer for Any objects, handles all Any-related nonsense. - google::protobuf::scoped_ptr<AnyWriter> any_; + std::unique_ptr<AnyWriter> any_; // The type of this element, see enum for permissible types. ItemType item_type_; // Set of map keys already seen for the type_. Used to validate incoming // messages so no map key appears more than once. - hash_set<string> map_keys_; + std::unique_ptr<hash_set<string> > map_keys_; // Conveys whether this Item is a placeholder or not. Placeholder items are // pushed to stack to account for special types. @@ -224,19 +317,19 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { strings::ByteSink* output, ErrorListener* listener); // Returns true if the field is a map. - bool IsMap(const google::protobuf::Field& field); + inline bool IsMap(const google::protobuf::Field& field); // Returns true if the field is an any. - bool IsAny(const google::protobuf::Field& field); + inline bool IsAny(const google::protobuf::Field& field); // Returns true if the field is google.protobuf.Struct. - bool IsStruct(const google::protobuf::Field& field); + inline bool IsStruct(const google::protobuf::Field& field); // Returns true if the field is google.protobuf.Value. - bool IsStructValue(const google::protobuf::Field& field); + inline bool IsStructValue(const google::protobuf::Field& field); // Returns true if the field is google.protobuf.ListValue. - bool IsStructListValue(const google::protobuf::Field& field); + inline bool IsStructListValue(const google::protobuf::Field& field); // Renders google.protobuf.Value in struct.proto. It picks the right oneof // type based on value's type. @@ -299,7 +392,10 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { const google::protobuf::Type& master_type_; // The current element, variable for internal state processing. - google::protobuf::scoped_ptr<Item> current_; + std::unique_ptr<Item> current_; + + // Reference to the options that control this class's behavior. + const ProtoStreamObjectWriter::Options options_; GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter); }; |