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