Go to the documentation of this file.
31 #include <google/protobuf/util/internal/protostream_objectwriter.h>
36 #include <unordered_map>
37 #include <unordered_set>
39 #include <google/protobuf/stubs/once.h>
40 #include <google/protobuf/wire_format_lite.h>
41 #include <google/protobuf/util/internal/field_mask_utility.h>
42 #include <google/protobuf/util/internal/object_location_tracker.h>
43 #include <google/protobuf/util/internal/constants.h>
44 #include <google/protobuf/util/internal/utility.h>
45 #include <google/protobuf/stubs/strutil.h>
46 #include <google/protobuf/stubs/status.h>
47 #include <google/protobuf/stubs/statusor.h>
48 #include <google/protobuf/stubs/time.h>
49 #include <google/protobuf/stubs/map_util.h>
52 #include <google/protobuf/port_def.inc>
59 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
60 using std::placeholders::_1;
66 strings::ByteSink*
output, ErrorListener* listener,
67 const ProtoStreamObjectWriter::Options&
options)
81 strings::ByteSink*
output, ErrorListener* listener,
82 const ProtoStreamObjectWriter::Options&
options)
83 : ProtoWriter(typeinfo,
type,
output, listener),
95 strings::ByteSink*
output, ErrorListener* listener)
96 : ProtoWriter(typeinfo,
type,
output, listener),
99 options_(ProtoStreamObjectWriter::Options::Defaults()) {}
107 std::unique_ptr<BaseElement>
element(
108 static_cast<BaseElement*
>(
current_.get())->pop<BaseElement>());
117 void SplitSecondsAndNanos(StringPiece
input, StringPiece*
seconds,
118 StringPiece* nanos) {
120 if (
idx != std::string::npos) {
125 *nanos = StringPiece();
129 Status GetNanosFromStringPiece(StringPiece s_nanos,
130 const char* parse_failure_message,
131 const char* exceeded_limit_message,
136 int num_leading_zeros = 0;
137 while (s_nanos.Consume(
"0")) {
145 if (!s_nanos.empty() && !
safe_strto32(s_nanos, &i_nanos)) {
166 conversion = 100000000;
169 conversion = 10000000;
172 conversion = 1000000;
195 *nanos = i_nanos * conversion;
210 is_well_known_type_(
false),
211 well_known_type_render_(nullptr) {}
220 if (ow_ ==
nullptr) {
222 uninterpreted_events_.push_back(Event(Event::START_OBJECT,
name));
223 }
else if (is_well_known_type_ &&
depth_ == 1) {
226 if (
name !=
"value" && !invalid_) {
228 "Expect a \"value\" field for well-known types.");
231 ow_->StartObject(
"");
236 ow_->StartObject(
name);
242 if (ow_ ==
nullptr) {
245 uninterpreted_events_.push_back(Event(Event::END_OBJECT));
247 }
else if (
depth_ >= 0 || !is_well_known_type_) {
264 if (ow_ ==
nullptr) {
266 uninterpreted_events_.push_back(Event(Event::START_LIST,
name));
267 }
else if (is_well_known_type_ &&
depth_ == 1) {
268 if (
name !=
"value" && !invalid_) {
270 "Expect a \"value\" field for well-known types.");
275 ow_->StartList(
name);
282 GOOGLE_LOG(DFATAL) <<
"Mismatched EndList found, should not be possible";
285 if (ow_ ==
nullptr) {
287 uninterpreted_events_.push_back(Event(Event::END_LIST));
294 StringPiece
name,
const DataPiece&
value) {
297 if (
depth_ == 0 && ow_ ==
nullptr &&
name ==
"@type") {
299 }
else if (ow_ ==
nullptr) {
301 uninterpreted_events_.push_back(Event(
name,
value));
302 }
else if (
depth_ == 0 && is_well_known_type_) {
303 if (
name !=
"value" && !invalid_) {
305 "Expect a \"value\" field for well-known types.");
308 if (well_known_type_render_ ==
nullptr) {
312 parent_->InvalidValue(
"Any",
"Expect a JSON object.");
316 ow_->ProtoWriter::StartObject(
"");
319 ow_->ProtoWriter::EndObject();
332 util::StatusOr<std::string>
s =
value.ToString();
334 parent_->InvalidValue(
"String",
s.status().message());
338 type_url_ =
s.value();
341 util::StatusOr<const google::protobuf::Type*> resolved_type =
342 parent_->typeinfo()->ResolveTypeUrl(type_url_);
343 if (!resolved_type.ok()) {
344 parent_->InvalidValue(
"Any", resolved_type.status().message());
352 if (well_known_type_render_ !=
nullptr ||
356 is_well_known_type_ =
true;
374 if (!is_well_known_type_) {
375 ow_->StartObject(
"");
380 for (
int i = 0;
i < uninterpreted_events_.size(); ++
i) {
381 uninterpreted_events_[
i].Replay(
this);
386 if (ow_ ==
nullptr) {
387 if (uninterpreted_events_.empty()) {
395 StrCat(
"Missing @type for any field in ",
396 parent_->master_type_.name()));
405 if (!
data_.empty()) {
411 AnyWriter*
writer)
const {
425 case RENDER_DATA_PIECE:
437 value_ = DataPiece(value_storage_,
value_.use_strict_base64_decoding());
439 value_storage_ =
value_.ToBytes().value();
441 DataPiece(value_storage_,
true,
value_.use_strict_base64_decoding());
446 ItemType item_type,
bool is_placeholder,
448 : BaseElement(nullptr),
451 item_type_(item_type),
452 is_placeholder_(is_placeholder),
454 if (item_type_ == ANY) {
455 any_.reset(
new AnyWriter(ow_));
457 if (item_type == MAP) {
458 map_keys_.reset(
new std::unordered_set<std::string>);
463 ItemType item_type,
bool is_placeholder,
465 : BaseElement(parent),
466 ow_(this->parent()->ow_),
468 item_type_(item_type),
469 is_placeholder_(is_placeholder),
471 if (item_type == ANY) {
472 any_.reset(
new AnyWriter(ow_));
474 if (item_type == MAP) {
475 map_keys_.reset(
new std::unordered_set<std::string>);
480 StringPiece map_key) {
527 "Cannot start root message with ListValue.");
589 if (
field ==
nullptr)
return this;
616 "Starting an object in a repeated field but the parent object "
646 if (
field->kind() != google::protobuf::Field::TYPE_GROUP &&
647 field->kind() != google::protobuf::Field::TYPE_MESSAGE) {
669 if (
current_ ==
nullptr)
return this;
672 if (
current_->any()->EndObject())
return this;
770 if (
element() !=
nullptr &&
element()->parent_field() !=
nullptr) {
791 "') within a map."));
798 if (
element() !=
nullptr &&
element()->parent_field() !=
nullptr) {
830 if (
field ==
nullptr) {
906 if (
current_ ==
nullptr)
return this;
918 const DataPiece&
data) {
920 switch (
data.type()) {
922 if (ow->options_.struct_integers_as_strings) {
923 util::StatusOr<int32_t> int_value =
data.ToInt32();
924 if (int_value.ok()) {
925 ow->ProtoWriter::RenderDataPiece(
927 DataPiece(
SimpleDtoa(int_value.value()),
true));
931 struct_field_name =
"number_value";
935 if (ow->options_.struct_integers_as_strings) {
936 util::StatusOr<uint32_t> int_value =
data.ToUint32();
937 if (int_value.ok()) {
938 ow->ProtoWriter::RenderDataPiece(
940 DataPiece(
SimpleDtoa(int_value.value()),
true));
944 struct_field_name =
"number_value";
950 if (ow->options_.struct_integers_as_strings) {
951 util::StatusOr<int64_t> int_value =
data.ToInt64();
952 if (int_value.ok()) {
953 ow->ProtoWriter::RenderDataPiece(
954 "string_value", DataPiece(
StrCat(int_value.value()),
true));
958 struct_field_name =
"number_value";
964 if (ow->options_.struct_integers_as_strings) {
965 util::StatusOr<uint64_t> int_value =
data.ToUint64();
966 if (int_value.ok()) {
967 ow->ProtoWriter::RenderDataPiece(
968 "string_value", DataPiece(
StrCat(int_value.value()),
true));
972 struct_field_name =
"number_value";
976 if (ow->options_.struct_integers_as_strings) {
977 util::StatusOr<float> float_value =
data.ToFloat();
978 if (float_value.ok()) {
979 ow->ProtoWriter::RenderDataPiece(
981 DataPiece(
SimpleDtoa(float_value.value()),
true));
985 struct_field_name =
"number_value";
989 if (ow->options_.struct_integers_as_strings) {
990 util::StatusOr<double> double_value =
data.ToDouble();
991 if (double_value.ok()) {
992 ow->ProtoWriter::RenderDataPiece(
994 DataPiece(
SimpleDtoa(double_value.value()),
true));
998 struct_field_name =
"number_value";
1002 struct_field_name =
"string_value";
1006 struct_field_name =
"bool_value";
1010 struct_field_name =
"null_value";
1015 "Invalid struct data type. Only number, string, boolean or null "
1016 "values are supported.");
1019 ow->ProtoWriter::RenderDataPiece(struct_field_name,
data);
1024 const DataPiece&
data) {
1028 StrCat(
"Invalid data type for timestamp, value is ",
1029 data.ValueAsStringOrDefault(
"")));
1042 ow->ProtoWriter::RenderDataPiece(
"seconds", DataPiece(
seconds));
1043 ow->ProtoWriter::RenderDataPiece(
"nanos", DataPiece(nanos));
1049 ow->ProtoWriter::RenderDataPiece(
1055 const DataPiece&
data) {
1059 StrCat(
"Invalid data type for field mask, value is ",
1060 data.ValueAsStringOrDefault(
"")));
1071 const DataPiece&
data) {
1075 StrCat(
"Invalid data type for duration, value is ",
1076 data.ValueAsStringOrDefault(
"")));
1083 "Illegal duration format; duration must end with 's'");
1092 StringPiece s_secs, s_nanos;
1093 SplitSecondsAndNanos(
value, &s_secs, &s_nanos);
1097 "Invalid duration format, failed to parse seconds");
1101 Status nanos_status = GetNanosFromStringPiece(
1102 s_nanos,
"Invalid duration format, failed to parse nano seconds",
1103 "Duration value exceeds limits", &nanos);
1104 if (!nanos_status.ok()) {
1105 return nanos_status;
1107 nanos = sign * nanos;
1115 ow->ProtoWriter::RenderDataPiece(
"seconds", DataPiece(
seconds));
1116 ow->ProtoWriter::RenderDataPiece(
"nanos", DataPiece(nanos));
1121 const DataPiece&
data) {
1123 ow->ProtoWriter::RenderDataPiece(
"value",
data);
1128 StringPiece
name,
const DataPiece&
data) {
1135 if (type_renderer ==
nullptr) {
1163 if (
field ==
nullptr) {
1164 GOOGLE_LOG(DFATAL) <<
"Map does not have a value field.";
1184 if (type_renderer !=
nullptr) {
1214 if (
field ==
nullptr)
return this;
1218 if (type_renderer !=
nullptr) {
1246 "Starting an primitive in a repeated field but the parent field "
1260 std::unordered_map<std::string, ProtoStreamObjectWriter::TypeRenderer>*
1267 (*renderers_)[
"type.googleapis.com/google.protobuf.Timestamp"] =
1269 (*renderers_)[
"type.googleapis.com/google.protobuf.Duration"] =
1271 (*renderers_)[
"type.googleapis.com/google.protobuf.FieldMask"] =
1273 (*renderers_)[
"type.googleapis.com/google.protobuf.Double"] =
1275 (*renderers_)[
"type.googleapis.com/google.protobuf.Float"] =
1277 (*renderers_)[
"type.googleapis.com/google.protobuf.Int64"] =
1279 (*renderers_)[
"type.googleapis.com/google.protobuf.UInt64"] =
1281 (*renderers_)[
"type.googleapis.com/google.protobuf.Int32"] =
1283 (*renderers_)[
"type.googleapis.com/google.protobuf.UInt32"] =
1285 (*renderers_)[
"type.googleapis.com/google.protobuf.Bool"] =
1287 (*renderers_)[
"type.googleapis.com/google.protobuf.String"] =
1289 (*renderers_)[
"type.googleapis.com/google.protobuf.Bytes"] =
1291 (*renderers_)[
"type.googleapis.com/google.protobuf.DoubleValue"] =
1293 (*renderers_)[
"type.googleapis.com/google.protobuf.FloatValue"] =
1295 (*renderers_)[
"type.googleapis.com/google.protobuf.Int64Value"] =
1297 (*renderers_)[
"type.googleapis.com/google.protobuf.UInt64Value"] =
1299 (*renderers_)[
"type.googleapis.com/google.protobuf.Int32Value"] =
1301 (*renderers_)[
"type.googleapis.com/google.protobuf.UInt32Value"] =
1303 (*renderers_)[
"type.googleapis.com/google.protobuf.BoolValue"] =
1305 (*renderers_)[
"type.googleapis.com/google.protobuf.StringValue"] =
1307 (*renderers_)[
"type.googleapis.com/google.protobuf.BytesValue"] =
1309 (*renderers_)[
"type.googleapis.com/google.protobuf.Value"] =
1327 if (
current_ ==
nullptr)
return true;
1329 if (!
current_->InsertMapKeyIfNotPresent(unnormalized_name)) {
1332 StrCat(
"Repeated map key: '", unnormalized_name,
1333 "' is already set."));
1348 new Item(
current_.release(), item_type, is_placeholder, is_list));
1368 if (
field.type_url().empty() ||
1369 field.kind() != google::protobuf::Field::TYPE_MESSAGE ||
1370 field.cardinality() != google::protobuf::Field::CARDINALITY_REPEATED) {
ProtoWriter * EndList() override
const char kStructValueType[]
Status InvalidArgumentError(absl::string_view message)
const char kStructValueTypeUrl[]
strings::ByteSink * output_
std::chrono::duration< std::int_fast64_t > seconds
ErrorListener * listener()
ProtoStreamObjectWriter(TypeResolver *type_resolver, const google::protobuf::Type &type, strings::ByteSink *output, ErrorListener *listener, const ProtoStreamObjectWriter::Options &options=ProtoStreamObjectWriter::Options::Defaults())
virtual void InvalidName(const LocationTrackerInterface &loc, StringPiece invalid_name, StringPiece message)=0
bool ignore_null_value_map_entry
const char kStructListValueType[]
ProtoWriter * StartList(StringPiece name) override
const Descriptor::ReservedRange value
ProtoWriter * EndObject() override
ProtoStreamObjectWriter * EndList() override
const LocationTrackerInterface & location()
ProtoElement * element() override
bool ValidMapKey(StringPiece unnormalized_name)
const StringPiece GetTypeWithoutUrl(StringPiece type_url)
util::Status DecodeCompactFieldMaskPaths(StringPiece paths, PathSinkCallback path_sink)
bool safe_strto32(const string &str, int32 *value)
void InvalidName(StringPiece unknown_name, StringPiece message)
void set_ignore_unknown_fields(bool ignore_unknown_fields)
bool InsertMapKeyIfNotPresent(StringPiece map_key)
ProtoStreamObjectWriter * EndObject() override
bool disable_implicit_scalar_list
std::string ToSnakeCase(StringPiece input)
ProtoWriter(TypeResolver *type_resolver, const google::protobuf::Type &type, strings::ByteSink *output, ErrorListener *listener)
string StrCat(const AlphaNum &a, const AlphaNum &b)
virtual const google::protobuf::Type * GetTypeByTypeUrl(StringPiece type_url) const =0
static TypeRenderer * FindTypeRenderer(const std::string &type_url)
void OnShutdown(void(*func)())
static util::Status RenderDuration(ProtoStreamObjectWriter *ow, const DataPiece &value)
void call_once(absl::once_flag &flag, Callable &&fn, Args &&... args)
void set_use_lower_camel_for_enums(bool use_lower_camel_for_enums)
ProtoStreamObjectWriter * StartObject(StringPiece name) override
static const size_type npos
bool use_lower_camel_for_enums
static util::Status RenderTimestamp(ProtoStreamObjectWriter *ow, const DataPiece &value)
const std::string GetFullTypeWithUrl(StringPiece simple_type)
void set_case_insensitive_enum_parsing(bool case_insensitive_enum_parsing)
void set_ignore_unknown_enum_values(bool ignore_unknown_enum_values)
void Replay(AnyWriter *writer) const
std::unique_ptr< Item > current_
static PyObject * Item(PyObject *pself, Py_ssize_t index)
void DecrementInvalidDepth()
bool IsMap(const google::protobuf::Field &field)
absl::string_view message() const
static void DeleteRendererMap()
unsigned __int64 uint64_t
bool IsMap(const google::protobuf::Field &field, const google::protobuf::Type &type)
AnyWriter(ProtoStreamObjectWriter *parent)
void IncrementInvalidDepth()
bool IsAny(const google::protobuf::Field &field)
bool ParseTime(const string &value, int64 *seconds, int32 *nanos)
util::Status(* TypeRenderer)(ProtoStreamObjectWriter *, const DataPiece &)
const int64 kDurationMinSeconds
bool HasPrefixString(const string &str, const string &prefix)
bool suppress_object_to_scalar_error
ProtoStreamObjectWriter * StartList(StringPiece name) override
const google::protobuf::Field * BeginNamed(StringPiece name, bool is_list)
static util::Status RenderFieldMask(ProtoStreamObjectWriter *ow, const DataPiece &value)
virtual ProtoWriter * RenderDataPiece(StringPiece name, const DataPiece &value)
bool IsStruct(const google::protobuf::Field &field)
void RenderDataPiece(StringPiece name, const DataPiece &value)
bool ignore_unknown_fields
string SimpleDtoa(double value)
ProtoStreamObjectWriter * RenderDataPiece(StringPiece name, const DataPiece &data) override
static util::Status RenderWrapperType(ProtoStreamObjectWriter *ow, const DataPiece &value)
const FieldDescriptor * field
bool use_strict_base64_decoding() const
const TypeInfo * typeinfo()
bool IsStructListValue(const google::protobuf::Field &field)
DebugStringOptions options_
void Push(StringPiece name, Item::ItemType item_type, bool is_placeholder, bool is_list)
PROTOBUF_NAMESPACE_ID::internal::once_flag writer_renderers_init_
bool ignore_unknown_enum_values
void StartList(StringPiece name)
static std::unordered_map< std::string, TypeRenderer > * renderers_
void set_use_json_name_in_missing_fields(bool use_json_name_in_missing_fields)
zend_class_entry * field_type
GRPC_CUSTOM_UTIL_STATUS Status
std::string ConvertFieldMaskPath(const StringPiece path, ConverterCallback converter)
bool suppress_implicit_scalar_list_error
ProtoWriter * StartObject(StringPiece name) override
ABSL_MUST_USE_RESULT bool ok() const
static util::Status RenderStructValue(ProtoStreamObjectWriter *ow, const DataPiece &value)
bool IsRepeated(const google::protobuf::Field &field)
bool use_legacy_json_map_format
static void InitRendererMap()
void StartAny(const DataPiece &value)
const google::protobuf::Type & master_type_
void InvalidValue(StringPiece type_name, StringPiece value)
Item(ProtoStreamObjectWriter *enclosing, ItemType item_type, bool is_placeholder, bool is_list)
bool HasSuffixString(const string &str, const string &suffix)
bool suppress_implicit_message_list_error
static util::Status RenderOneFieldPath(ProtoStreamObjectWriter *ow, StringPiece path)
bool IsStructValue(const google::protobuf::Field &field)
bool case_insensitive_enum_parsing
RefCountedPtr< GrpcLb > parent_
bool safe_strtou64(const string &str, uint64 *value)
std::unique_ptr< std::unordered_set< std::string > > map_keys_
#define GOOGLE_LOG(LEVEL)
void StartObject(StringPiece name)
~ProtoStreamObjectWriter() override
const Collection::value_type::second_type * FindOrNull(const Collection &collection, const typename Collection::value_type::first_type &key)
const ProtoStreamObjectWriter::Options options_
const int64 kDurationMaxSeconds
bool InsertIfNotPresent(Collection *const collection, const typename Collection::value_type &vt)
const int32 kNanosPerSecond
const google::protobuf::Field * Lookup(StringPiece name)
bool disable_implicit_message_list
const char kStructNullValueTypeUrl[]
void StrAppend(string *result, const AlphaNum &a)
grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:49