Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc

Issue 2495533002: third_party/protobuf: Update to HEAD (83d681ee2c) (Closed)
Patch Set: Make chrome settings proto generated file a component Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Protocol Buffers - Google's data interchange format 1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved. 2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/ 3 // https://developers.google.com/protocol-buffers/
4 // 4 //
5 // Redistribution and use in source and binary forms, with or without 5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are 6 // modification, are permitted provided that the following conditions are
7 // met: 7 // met:
8 // 8 //
9 // * Redistributions of source code must retain the above copyright 9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer. 10 // notice, this list of conditions and the following disclaimer.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 using util::StatusOr; 56 using util::StatusOr;
57 57
58 58
59 ProtoStreamObjectWriter::ProtoStreamObjectWriter( 59 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
60 TypeResolver* type_resolver, const google::protobuf::Type& type, 60 TypeResolver* type_resolver, const google::protobuf::Type& type,
61 strings::ByteSink* output, ErrorListener* listener, 61 strings::ByteSink* output, ErrorListener* listener,
62 const ProtoStreamObjectWriter::Options& options) 62 const ProtoStreamObjectWriter::Options& options)
63 : ProtoWriter(type_resolver, type, output, listener), 63 : ProtoWriter(type_resolver, type, output, listener),
64 master_type_(type), 64 master_type_(type),
65 current_(NULL), 65 current_(NULL),
66 options_(options) {} 66 options_(options) {
67 set_ignore_unknown_fields(options_.ignore_unknown_fields);
68 set_use_lower_camel_for_enums(options_.use_lower_camel_for_enums);
69 }
67 70
68 ProtoStreamObjectWriter::ProtoStreamObjectWriter( 71 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
69 const TypeInfo* typeinfo, const google::protobuf::Type& type, 72 const TypeInfo* typeinfo, const google::protobuf::Type& type,
70 strings::ByteSink* output, ErrorListener* listener) 73 strings::ByteSink* output, ErrorListener* listener)
71 : ProtoWriter(typeinfo, type, output, listener), 74 : ProtoWriter(typeinfo, type, output, listener),
72 master_type_(type), 75 master_type_(type),
73 current_(NULL), 76 current_(NULL),
74 options_(ProtoStreamObjectWriter::Options::Defaults()) {} 77 options_(ProtoStreamObjectWriter::Options::Defaults()) {}
75 78
76 ProtoStreamObjectWriter::~ProtoStreamObjectWriter() { 79 ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 output_(&data_), 186 output_(&data_),
184 depth_(0), 187 depth_(0),
185 is_well_known_type_(false), 188 is_well_known_type_(false),
186 well_known_type_render_(NULL) {} 189 well_known_type_render_(NULL) {}
187 190
188 ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {} 191 ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {}
189 192
190 void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { 193 void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) {
191 ++depth_; 194 ++depth_;
192 // If an object writer is absent, that means we have not called StartAny() 195 // If an object writer is absent, that means we have not called StartAny()
193 // before reaching here. This is an invalid state. StartAny() gets called 196 // before reaching here, which happens when we have data before the "@type"
194 // whenever we see an "@type" being rendered (see AnyWriter::RenderDataPiece). 197 // field.
195 if (ow_ == NULL) { 198 if (ow_ == NULL) {
196 // Make sure we are not already in an invalid state. This avoids making 199 // Save data before the "@type" field for later replay.
197 // multiple unnecessary InvalidValue calls. 200 uninterpreted_events_.push_back(Event(Event::START_OBJECT, name));
198 if (!invalid_) {
199 parent_->InvalidValue("Any",
200 StrCat("Missing or invalid @type for any field in ",
201 parent_->master_type_.name()));
202 invalid_ = true;
203 }
204 } else if (is_well_known_type_ && depth_ == 1) { 201 } else if (is_well_known_type_ && depth_ == 1) {
205 // For well-known types, the only other field besides "@type" should be a 202 // For well-known types, the only other field besides "@type" should be a
206 // "value" field. 203 // "value" field.
207 if (name != "value" && !invalid_) { 204 if (name != "value" && !invalid_) {
208 parent_->InvalidValue("Any", 205 parent_->InvalidValue("Any",
209 "Expect a \"value\" field for well-known types."); 206 "Expect a \"value\" field for well-known types.");
210 invalid_ = true; 207 invalid_ = true;
211 } 208 }
212 ow_->StartObject(""); 209 ow_->StartObject("");
213 } else { 210 } else {
214 // Forward the call to the child writer if: 211 // Forward the call to the child writer if:
215 // 1. the type is not a well-known type. 212 // 1. the type is not a well-known type.
216 // 2. or, we are in a nested Any, Struct, or Value object. 213 // 2. or, we are in a nested Any, Struct, or Value object.
217 ow_->StartObject(name); 214 ow_->StartObject(name);
218 } 215 }
219 } 216 }
220 217
221 bool ProtoStreamObjectWriter::AnyWriter::EndObject() { 218 bool ProtoStreamObjectWriter::AnyWriter::EndObject() {
222 --depth_; 219 --depth_;
223 // As long as depth_ >= 0, we know we haven't reached the end of Any. 220 if (ow_ == NULL) {
224 // Propagate these EndObject() calls to the contained ow_. For regular 221 if (depth_ >= 0) {
225 // message types, we propagate the end of Any as well. 222 // Save data before the "@type" field for later replay.
226 if (ow_ != NULL && (depth_ >= 0 || !is_well_known_type_)) { 223 uninterpreted_events_.push_back(Event(Event::END_OBJECT));
224 }
225 } else if (depth_ >= 0 || !is_well_known_type_) {
226 // As long as depth_ >= 0, we know we haven't reached the end of Any.
227 // Propagate these EndObject() calls to the contained ow_. For regular
228 // message types, we propagate the end of Any as well.
227 ow_->EndObject(); 229 ow_->EndObject();
228 } 230 }
229 // A negative depth_ implies that we have reached the end of Any 231 // A negative depth_ implies that we have reached the end of Any
230 // object. Now we write out its contents. 232 // object. Now we write out its contents.
231 if (depth_ < 0) { 233 if (depth_ < 0) {
232 WriteAny(); 234 WriteAny();
233 return false; 235 return false;
234 } 236 }
235 return true; 237 return true;
236 } 238 }
237 239
238 void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) { 240 void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) {
239 ++depth_; 241 ++depth_;
240 // We expect ow_ to be present as this call only makes sense inside an Any.
241 if (ow_ == NULL) { 242 if (ow_ == NULL) {
242 if (!invalid_) { 243 // Save data before the "@type" field for later replay.
243 parent_->InvalidValue("Any", 244 uninterpreted_events_.push_back(Event(Event::START_LIST, name));
244 StrCat("Missing or invalid @type for any field in ",
245 parent_->master_type_.name()));
246 invalid_ = true;
247 }
248 } else if (is_well_known_type_ && depth_ == 1) { 245 } else if (is_well_known_type_ && depth_ == 1) {
249 if (name != "value" && !invalid_) { 246 if (name != "value" && !invalid_) {
250 parent_->InvalidValue("Any", 247 parent_->InvalidValue("Any",
251 "Expect a \"value\" field for well-known types."); 248 "Expect a \"value\" field for well-known types.");
252 invalid_ = true; 249 invalid_ = true;
253 } 250 }
254 ow_->StartList(""); 251 ow_->StartList("");
255 } else { 252 } else {
256 ow_->StartList(name); 253 ow_->StartList(name);
257 } 254 }
258 } 255 }
259 256
260 void ProtoStreamObjectWriter::AnyWriter::EndList() { 257 void ProtoStreamObjectWriter::AnyWriter::EndList() {
261 --depth_; 258 --depth_;
262 if (depth_ < 0) { 259 if (depth_ < 0) {
263 GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible"; 260 GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible";
264 depth_ = 0; 261 depth_ = 0;
265 } 262 }
266 // We don't write an error on the close, only on the open 263 if (ow_ == NULL) {
267 if (ow_ != NULL) { 264 // Save data before the "@type" field for later replay.
265 uninterpreted_events_.push_back(Event(Event::END_LIST));
266 } else {
268 ow_->EndList(); 267 ow_->EndList();
269 } 268 }
270 } 269 }
271 270
272 void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( 271 void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece(
273 StringPiece name, const DataPiece& value) { 272 StringPiece name, const DataPiece& value) {
274 // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type" 273 // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type"
275 // should go to the contained ow_ as they indicate nested Anys. 274 // should go to the contained ow_ as they indicate nested Anys.
276 if (depth_ == 0 && ow_ == NULL && name == "@type") { 275 if (depth_ == 0 && ow_ == NULL && name == "@type") {
277 StartAny(value); 276 StartAny(value);
278 } else if (ow_ == NULL) { 277 } else if (ow_ == NULL) {
279 if (!invalid_) { 278 // Save data before the "@type" field.
280 parent_->InvalidValue("Any", 279 uninterpreted_events_.push_back(Event(name, value));
281 StrCat("Missing or invalid @type for any field in ",
282 parent_->master_type_.name()));
283 invalid_ = true;
284 }
285 } else if (depth_ == 0 && is_well_known_type_) { 280 } else if (depth_ == 0 && is_well_known_type_) {
286 if (name != "value" && !invalid_) { 281 if (name != "value" && !invalid_) {
287 parent_->InvalidValue("Any", 282 parent_->InvalidValue("Any",
288 "Expect a \"value\" field for well-known types."); 283 "Expect a \"value\" field for well-known types.");
289 invalid_ = true; 284 invalid_ = true;
290 } 285 }
291 if (well_known_type_render_ == NULL) { 286 if (well_known_type_render_ == NULL) {
292 // Only Any and Struct don't have a special type render but both of 287 // Only Any and Struct don't have a special type render but both of
293 // them expect a JSON object (i.e., a StartObject() call). 288 // them expect a JSON object (i.e., a StartObject() call).
294 if (!invalid_) { 289 if (value.type() != DataPiece::TYPE_NULL && !invalid_) {
295 parent_->InvalidValue("Any", "Expect a JSON object."); 290 parent_->InvalidValue("Any", "Expect a JSON object.");
296 invalid_ = true; 291 invalid_ = true;
297 } 292 }
298 } else { 293 } else {
299 ow_->ProtoWriter::StartObject(""); 294 ow_->ProtoWriter::StartObject("");
300 Status status = (*well_known_type_render_)(ow_.get(), value); 295 Status status = (*well_known_type_render_)(ow_.get(), value);
301 if (!status.ok()) ow_->InvalidValue("Any", status.error_message()); 296 if (!status.ok()) ow_->InvalidValue("Any", status.error_message());
302 ow_->ProtoWriter::EndObject(); 297 ow_->ProtoWriter::EndObject();
303 } 298 }
304 } else { 299 } else {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 // example: 344 // example:
350 // { 345 // {
351 // "@type": "type.googleapis.com/google.protobuf.Value", 346 // "@type": "type.googleapis.com/google.protobuf.Value",
352 // "value": [1, 2, 3], 347 // "value": [1, 2, 3],
353 // } 348 // }
354 // With the above JSON representation, we will only call StartList() on the 349 // With the above JSON representation, we will only call StartList() on the
355 // contained ow_. 350 // contained ow_.
356 if (!is_well_known_type_) { 351 if (!is_well_known_type_) {
357 ow_->StartObject(""); 352 ow_->StartObject("");
358 } 353 }
354
355 // Now we know the proto type and can interpret all data fields we gathered
356 // before the "@type" field.
357 for (int i = 0; i < uninterpreted_events_.size(); ++i) {
358 uninterpreted_events_[i].Replay(this);
359 }
359 } 360 }
360 361
361 void ProtoStreamObjectWriter::AnyWriter::WriteAny() { 362 void ProtoStreamObjectWriter::AnyWriter::WriteAny() {
362 if (ow_ == NULL) { 363 if (ow_ == NULL) {
363 // If we had no object writer, we never got any content, so just return 364 if (uninterpreted_events_.empty()) {
364 // immediately, which is equivalent to writing an empty Any. 365 // We never got any content, so just return immediately, which is
365 return; 366 // equivalent to writing an empty Any.
367 return;
368 } else {
369 // There are uninterpreted data, but we never got a "@type" field.
370 if (!invalid_) {
371 parent_->InvalidValue("Any", StrCat("Missing @type for any field in ",
372 parent_->master_type_.name()));
373 invalid_ = true;
374 }
375 return;
376 }
366 } 377 }
367 // Render the type_url and value fields directly to the stream. 378 // Render the type_url and value fields directly to the stream.
368 // type_url has tag 1 and value has tag 2. 379 // type_url has tag 1 and value has tag 2.
369 WireFormatLite::WriteString(1, type_url_, parent_->stream()); 380 WireFormatLite::WriteString(1, type_url_, parent_->stream());
370 if (!data_.empty()) { 381 if (!data_.empty()) {
371 WireFormatLite::WriteBytes(2, data_, parent_->stream()); 382 WireFormatLite::WriteBytes(2, data_, parent_->stream());
372 } 383 }
373 } 384 }
374 385
386 void ProtoStreamObjectWriter::AnyWriter::Event::Replay(
387 AnyWriter* writer) const {
388 switch (type_) {
389 case START_OBJECT:
390 writer->StartObject(name_);
391 break;
392 case END_OBJECT:
393 writer->EndObject();
394 break;
395 case START_LIST:
396 writer->StartList(name_);
397 break;
398 case END_LIST:
399 writer->EndList();
400 break;
401 case RENDER_DATA_PIECE:
402 writer->RenderDataPiece(name_, value_);
403 break;
404 }
405 }
406
407 void ProtoStreamObjectWriter::AnyWriter::Event::DeepCopy() {
408 // DataPiece only contains a string reference. To make sure the referenced
409 // string value stays valid, we make a copy of the string value and update
410 // DataPiece to reference our own copy.
411 if (value_.type() == DataPiece::TYPE_STRING) {
412 value_.str().AppendToString(&value_storage_);
413 value_ = DataPiece(value_storage_, value_.use_strict_base64_decoding());
414 } else if (value_.type() == DataPiece::TYPE_BYTES) {
415 value_storage_ = value_.ToBytes().ValueOrDie();
416 value_ =
417 DataPiece(value_storage_, true, value_.use_strict_base64_decoding());
418 }
419 }
420
375 ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing, 421 ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing,
376 ItemType item_type, bool is_placeholder, 422 ItemType item_type, bool is_placeholder,
377 bool is_list) 423 bool is_list)
378 : BaseElement(NULL), 424 : BaseElement(NULL),
379 ow_(enclosing), 425 ow_(enclosing),
380 any_(), 426 any_(),
381 item_type_(item_type), 427 item_type_(item_type),
382 is_placeholder_(is_placeholder), 428 is_placeholder_(is_placeholder),
383 is_list_(is_list) { 429 is_list_(is_list) {
384 if (item_type_ == ANY) { 430 if (item_type_ == ANY) {
385 any_.reset(new AnyWriter(ow_)); 431 any_.reset(new AnyWriter(ow_));
386 } 432 }
433 if (item_type == MAP) {
434 map_keys_.reset(new hash_set<string>);
435 }
387 } 436 }
388 437
389 ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent, 438 ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent,
390 ItemType item_type, bool is_placeholder, 439 ItemType item_type, bool is_placeholder,
391 bool is_list) 440 bool is_list)
392 : BaseElement(parent), 441 : BaseElement(parent),
393 ow_(this->parent()->ow_), 442 ow_(this->parent()->ow_),
394 any_(), 443 any_(),
395 item_type_(item_type), 444 item_type_(item_type),
396 is_placeholder_(is_placeholder), 445 is_placeholder_(is_placeholder),
397 is_list_(is_list) { 446 is_list_(is_list) {
398 if (item_type == ANY) { 447 if (item_type == ANY) {
399 any_.reset(new AnyWriter(ow_)); 448 any_.reset(new AnyWriter(ow_));
400 } 449 }
450 if (item_type == MAP) {
451 map_keys_.reset(new hash_set<string>);
452 }
401 } 453 }
402 454
403 bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent( 455 bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent(
404 StringPiece map_key) { 456 StringPiece map_key) {
405 return InsertIfNotPresent(&map_keys_, map_key.ToString()); 457 return InsertIfNotPresent(map_keys_.get(), map_key.ToString());
406 } 458 }
407 459
408 ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( 460 ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
409 StringPiece name) { 461 StringPiece name) {
410 if (invalid_depth() > 0) { 462 if (invalid_depth() > 0) {
411 IncrementInvalidDepth(); 463 IncrementInvalidDepth();
412 return this; 464 return this;
413 } 465 }
414 466
415 // Starting the root message. Create the root Item and return. 467 // Starting the root message. Create the root Item and return.
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 "Invalid struct data type. Only number, string, boolean or " 904 "Invalid struct data type. Only number, string, boolean or "
853 "null values are supported."); 905 "null values are supported.");
854 } 906 }
855 } 907 }
856 ow->ProtoWriter::RenderDataPiece(struct_field_name, data); 908 ow->ProtoWriter::RenderDataPiece(struct_field_name, data);
857 return Status::OK; 909 return Status::OK;
858 } 910 }
859 911
860 Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow, 912 Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow,
861 const DataPiece& data) { 913 const DataPiece& data) {
914 if (data.type() == DataPiece::TYPE_NULL) return Status::OK;
862 if (data.type() != DataPiece::TYPE_STRING) { 915 if (data.type() != DataPiece::TYPE_STRING) {
863 return Status(INVALID_ARGUMENT, 916 return Status(INVALID_ARGUMENT,
864 StrCat("Invalid data type for timestamp, value is ", 917 StrCat("Invalid data type for timestamp, value is ",
865 data.ValueAsStringOrDefault(""))); 918 data.ValueAsStringOrDefault("")));
866 } 919 }
867 920
868 StringPiece value(data.str()); 921 StringPiece value(data.str());
869 922
870 int64 seconds; 923 int64 seconds;
871 int32 nanos; 924 int32 nanos;
(...skipping 10 matching lines...) Expand all
882 935
883 static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow, 936 static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
884 StringPiece path) { 937 StringPiece path) {
885 ow->ProtoWriter::RenderDataPiece( 938 ow->ProtoWriter::RenderDataPiece(
886 "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true)); 939 "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true));
887 return Status::OK; 940 return Status::OK;
888 } 941 }
889 942
890 Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, 943 Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
891 const DataPiece& data) { 944 const DataPiece& data) {
945 if (data.type() == DataPiece::TYPE_NULL) return Status::OK;
892 if (data.type() != DataPiece::TYPE_STRING) { 946 if (data.type() != DataPiece::TYPE_STRING) {
893 return Status(INVALID_ARGUMENT, 947 return Status(INVALID_ARGUMENT,
894 StrCat("Invalid data type for field mask, value is ", 948 StrCat("Invalid data type for field mask, value is ",
895 data.ValueAsStringOrDefault(""))); 949 data.ValueAsStringOrDefault("")));
896 } 950 }
897 951
898 // TODO(tsun): figure out how to do proto descriptor based snake case 952 // TODO(tsun): figure out how to do proto descriptor based snake case
899 // conversions as much as possible. Because ToSnakeCase sometimes returns the 953 // conversions as much as possible. Because ToSnakeCase sometimes returns the
900 // wrong value. 954 // wrong value.
901 google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > call back( 955 google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > call back(
902 ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow )); 956 NewPermanentCallback(&RenderOneFieldPath, ow));
903 return DecodeCompactFieldMaskPaths(data.str(), callback.get()); 957 return DecodeCompactFieldMaskPaths(data.str(), callback.get());
904 } 958 }
905 959
906 Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow, 960 Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow,
907 const DataPiece& data) { 961 const DataPiece& data) {
962 if (data.type() == DataPiece::TYPE_NULL) return Status::OK;
908 if (data.type() != DataPiece::TYPE_STRING) { 963 if (data.type() != DataPiece::TYPE_STRING) {
909 return Status(INVALID_ARGUMENT, 964 return Status(INVALID_ARGUMENT,
910 StrCat("Invalid data type for duration, value is ", 965 StrCat("Invalid data type for duration, value is ",
911 data.ValueAsStringOrDefault(""))); 966 data.ValueAsStringOrDefault("")));
912 } 967 }
913 968
914 StringPiece value(data.str()); 969 StringPiece value(data.str());
915 970
916 if (!value.ends_with("s")) { 971 if (!value.ends_with("s")) {
917 return Status(INVALID_ARGUMENT, 972 return Status(INVALID_ARGUMENT,
(...skipping 29 matching lines...) Expand all
947 return Status(INVALID_ARGUMENT, "Duration value exceeds limits"); 1002 return Status(INVALID_ARGUMENT, "Duration value exceeds limits");
948 } 1003 }
949 1004
950 ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds)); 1005 ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
951 ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos)); 1006 ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos));
952 return Status::OK; 1007 return Status::OK;
953 } 1008 }
954 1009
955 Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow, 1010 Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow,
956 const DataPiece& data) { 1011 const DataPiece& data) {
1012 if (data.type() == DataPiece::TYPE_NULL) return Status::OK;
957 ow->ProtoWriter::RenderDataPiece("value", data); 1013 ow->ProtoWriter::RenderDataPiece("value", data);
958 return Status::OK; 1014 return Status::OK;
959 } 1015 }
960 1016
961 ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( 1017 ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
962 StringPiece name, const DataPiece& data) { 1018 StringPiece name, const DataPiece& data) {
963 Status status; 1019 Status status;
964 if (invalid_depth() > 0) return this; 1020 if (invalid_depth() > 0) return this;
965 1021
966 if (current_ == NULL) { 1022 if (current_ == NULL) {
(...skipping 26 matching lines...) Expand all
993 if (current_->IsMap()) { 1049 if (current_->IsMap()) {
994 if (!ValidMapKey(name)) return this; 1050 if (!ValidMapKey(name)) return this;
995 1051
996 // Render an item in repeated map list. 1052 // Render an item in repeated map list.
997 // { "key": "<name>", "value": 1053 // { "key": "<name>", "value":
998 Push("", Item::MESSAGE, false, false); 1054 Push("", Item::MESSAGE, false, false);
999 ProtoWriter::RenderDataPiece("key", 1055 ProtoWriter::RenderDataPiece("key",
1000 DataPiece(name, use_strict_base64_decoding())); 1056 DataPiece(name, use_strict_base64_decoding()));
1001 field = Lookup("value"); 1057 field = Lookup("value");
1002 if (field == NULL) { 1058 if (field == NULL) {
1059 Pop();
1003 GOOGLE_LOG(DFATAL) << "Map does not have a value field."; 1060 GOOGLE_LOG(DFATAL) << "Map does not have a value field.";
1004 return this; 1061 return this;
1005 } 1062 }
1006 1063
1007 const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url()); 1064 const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url());
1008 if (type_renderer != NULL) { 1065 if (type_renderer != NULL) {
1009 // Map's value type is a special type. Render it like a message: 1066 // Map's value type is a special type. Render it like a message:
1010 // "value": { 1067 // "value": {
1011 // ... Render special type ... 1068 // ... Render special type ...
1012 // } 1069 // }
(...skipping 20 matching lines...) Expand all
1033 Pop(); 1090 Pop();
1034 return this; 1091 return this;
1035 } 1092 }
1036 1093
1037 field = Lookup(name); 1094 field = Lookup(name);
1038 if (field == NULL) return this; 1095 if (field == NULL) return this;
1039 1096
1040 // Check if the field is of special type. Render it accordingly if so. 1097 // Check if the field is of special type. Render it accordingly if so.
1041 const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url()); 1098 const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url());
1042 if (type_renderer != NULL) { 1099 if (type_renderer != NULL) {
1043 Push(name, Item::MESSAGE, false, false); 1100 // Pass through null value only for google.protobuf.Value. For other
1044 status = (*type_renderer)(this, data); 1101 // types we ignore null value just like for regular field types.
1045 if (!status.ok()) { 1102 if (data.type() != DataPiece::TYPE_NULL ||
1046 InvalidValue(field->type_url(), 1103 field->type_url() == kStructValueTypeUrl) {
1047 StrCat("Field '", name, "', ", status.error_message())); 1104 Push(name, Item::MESSAGE, false, false);
1105 status = (*type_renderer)(this, data);
1106 if (!status.ok()) {
1107 InvalidValue(field->type_url(),
1108 StrCat("Field '", name, "', ", status.error_message()));
1109 }
1110 Pop();
1048 } 1111 }
1049 Pop();
1050 return this; 1112 return this;
1051 } 1113 }
1052 1114
1053 // If we are rendering explicit null values and the backend proto field is 1115 // If we are rendering explicit null values and the backend proto field is
1054 // not of the google.protobuf.NullType type, we do nothing. 1116 // not of the google.protobuf.NullType type, we do nothing.
1055 if (data.type() == DataPiece::TYPE_NULL && 1117 if (data.type() == DataPiece::TYPE_NULL &&
1056 field->type_url() != kStructNullValueTypeUrl) { 1118 field->type_url() != kStructNullValueTypeUrl) {
1057 return this; 1119 return this;
1058 } 1120 }
1059 1121
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE || 1233 field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE ||
1172 field.cardinality() != 1234 field.cardinality() !=
1173 google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { 1235 google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
1174 return false; 1236 return false;
1175 } 1237 }
1176 const google::protobuf::Type* field_type = 1238 const google::protobuf::Type* field_type =
1177 typeinfo()->GetTypeByTypeUrl(field.type_url()); 1239 typeinfo()->GetTypeByTypeUrl(field.type_url());
1178 1240
1179 // TODO(xiaofeng): Unify option names. 1241 // TODO(xiaofeng): Unify option names.
1180 return GetBoolOptionOrDefault(field_type->options(), 1242 return GetBoolOptionOrDefault(field_type->options(),
1181 "google.protobuf.MessageOptions.map_entry", fals e) || 1243 "google.protobuf.MessageOptions.map_entry",
1182 GetBoolOptionOrDefault(field_type->options(), "map_entry", false); 1244 false) ||
1245 GetBoolOptionOrDefault(field_type->options(), "map_entry", false) ||
1246 GetBoolOptionOrDefault(field_type->options(),
1247 "proto2.MessageOptions.map_entry", false);
1183 } 1248 }
1184 1249
1185 bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) { 1250 bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) {
1186 return GetTypeWithoutUrl(field.type_url()) == kAnyType; 1251 return GetTypeWithoutUrl(field.type_url()) == kAnyType;
1187 } 1252 }
1188 1253
1189 bool ProtoStreamObjectWriter::IsStruct(const google::protobuf::Field& field) { 1254 bool ProtoStreamObjectWriter::IsStruct(const google::protobuf::Field& field) {
1190 return GetTypeWithoutUrl(field.type_url()) == kStructType; 1255 return GetTypeWithoutUrl(field.type_url()) == kStructType;
1191 } 1256 }
1192 1257
1193 bool ProtoStreamObjectWriter::IsStructValue( 1258 bool ProtoStreamObjectWriter::IsStructValue(
1194 const google::protobuf::Field& field) { 1259 const google::protobuf::Field& field) {
1195 return GetTypeWithoutUrl(field.type_url()) == kStructValueType; 1260 return GetTypeWithoutUrl(field.type_url()) == kStructValueType;
1196 } 1261 }
1197 1262
1198 bool ProtoStreamObjectWriter::IsStructListValue( 1263 bool ProtoStreamObjectWriter::IsStructListValue(
1199 const google::protobuf::Field& field) { 1264 const google::protobuf::Field& field) {
1200 return GetTypeWithoutUrl(field.type_url()) == kStructListValueType; 1265 return GetTypeWithoutUrl(field.type_url()) == kStructListValueType;
1201 } 1266 }
1202 1267
1203 } // namespace converter 1268 } // namespace converter
1204 } // namespace util 1269 } // namespace util
1205 } // namespace protobuf 1270 } // namespace protobuf
1206 } // namespace google 1271 } // namespace google
1272
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698