aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/util/internal/protostream_objectwriter.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/util/internal/protostream_objectwriter.h')
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.h122
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);
};