| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 using util::StatusOr; | 57 using util::StatusOr; |
| 58 | 58 |
| 59 | 59 |
| 60 ProtoWriter::ProtoWriter(TypeResolver* type_resolver, | 60 ProtoWriter::ProtoWriter(TypeResolver* type_resolver, |
| 61 const google::protobuf::Type& type, | 61 const google::protobuf::Type& type, |
| 62 strings::ByteSink* output, ErrorListener* listener) | 62 strings::ByteSink* output, ErrorListener* listener) |
| 63 : master_type_(type), | 63 : master_type_(type), |
| 64 typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), | 64 typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), |
| 65 own_typeinfo_(true), | 65 own_typeinfo_(true), |
| 66 done_(false), | 66 done_(false), |
| 67 ignore_unknown_fields_(false), |
| 68 use_lower_camel_for_enums_(false), |
| 67 element_(NULL), | 69 element_(NULL), |
| 68 size_insert_(), | 70 size_insert_(), |
| 69 output_(output), | 71 output_(output), |
| 70 buffer_(), | 72 buffer_(), |
| 71 adapter_(&buffer_), | 73 adapter_(&buffer_), |
| 72 stream_(new CodedOutputStream(&adapter_)), | 74 stream_(new CodedOutputStream(&adapter_)), |
| 73 listener_(listener), | 75 listener_(listener), |
| 74 invalid_depth_(0), | 76 invalid_depth_(0), |
| 75 tracker_(new ObjectLocationTracker()) {} | 77 tracker_(new ObjectLocationTracker()) {} |
| 76 | 78 |
| 77 ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, | 79 ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, |
| 78 const google::protobuf::Type& type, | 80 const google::protobuf::Type& type, |
| 79 strings::ByteSink* output, ErrorListener* listener) | 81 strings::ByteSink* output, ErrorListener* listener) |
| 80 : master_type_(type), | 82 : master_type_(type), |
| 81 typeinfo_(typeinfo), | 83 typeinfo_(typeinfo), |
| 82 own_typeinfo_(false), | 84 own_typeinfo_(false), |
| 83 done_(false), | 85 done_(false), |
| 86 ignore_unknown_fields_(false), |
| 87 use_lower_camel_for_enums_(false), |
| 84 element_(NULL), | 88 element_(NULL), |
| 85 size_insert_(), | 89 size_insert_(), |
| 86 output_(output), | 90 output_(output), |
| 87 buffer_(), | 91 buffer_(), |
| 88 adapter_(&buffer_), | 92 adapter_(&buffer_), |
| 89 stream_(new CodedOutputStream(&adapter_)), | 93 stream_(new CodedOutputStream(&adapter_)), |
| 90 listener_(listener), | 94 listener_(listener), |
| 91 invalid_depth_(0), | 95 invalid_depth_(0), |
| 92 tracker_(new ObjectLocationTracker()) {} | 96 tracker_(new ObjectLocationTracker()) {} |
| 93 | 97 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 StatusOr<string> s = data.ToString(); | 259 StatusOr<string> s = data.ToString(); |
| 256 if (s.ok()) { | 260 if (s.ok()) { |
| 257 WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream); | 261 WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream); |
| 258 } | 262 } |
| 259 return s.status(); | 263 return s.status(); |
| 260 } | 264 } |
| 261 | 265 |
| 262 // Writes an ENUM field, including tag, to the stream. | 266 // Writes an ENUM field, including tag, to the stream. |
| 263 inline Status WriteEnum(int field_number, const DataPiece& data, | 267 inline Status WriteEnum(int field_number, const DataPiece& data, |
| 264 const google::protobuf::Enum* enum_type, | 268 const google::protobuf::Enum* enum_type, |
| 265 CodedOutputStream* stream) { | 269 CodedOutputStream* stream, |
| 266 StatusOr<int> e = data.ToEnum(enum_type); | 270 bool use_lower_camel_for_enums) { |
| 271 StatusOr<int> e = data.ToEnum(enum_type, use_lower_camel_for_enums); |
| 267 if (e.ok()) { | 272 if (e.ok()) { |
| 268 WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); | 273 WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); |
| 269 } | 274 } |
| 270 return e.status(); | 275 return e.status(); |
| 271 } | 276 } |
| 272 | 277 |
| 273 // Given a google::protobuf::Type, returns the set of all required fields. | 278 // Given a google::protobuf::Type, returns the set of all required fields. |
| 274 std::set<const google::protobuf::Field*> GetRequiredFields( | 279 std::set<const google::protobuf::Field*> GetRequiredFields( |
| 275 const google::protobuf::Type& type) { | 280 const google::protobuf::Type& type) { |
| 276 std::set<const google::protobuf::Field*> required; | 281 std::set<const google::protobuf::Field*> required; |
| 277 for (int i = 0; i < type.fields_size(); i++) { | 282 for (int i = 0; i < type.fields_size(); i++) { |
| 278 const google::protobuf::Field& field = type.fields(i); | 283 const google::protobuf::Field& field = type.fields(i); |
| 279 if (field.cardinality() == | 284 if (field.cardinality() == |
| 280 google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) { | 285 google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) { |
| 281 required.insert(&field); | 286 required.insert(&field); |
| 282 } | 287 } |
| 283 } | 288 } |
| 284 return required; | 289 return required; |
| 285 } | 290 } |
| 286 | 291 |
| 287 } // namespace | 292 } // namespace |
| 288 | 293 |
| 289 ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo, | 294 ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo, |
| 290 const google::protobuf::Type& type, | 295 const google::protobuf::Type& type, |
| 291 ProtoWriter* enclosing) | 296 ProtoWriter* enclosing) |
| 292 : BaseElement(NULL), | 297 : BaseElement(NULL), |
| 293 ow_(enclosing), | 298 ow_(enclosing), |
| 294 parent_field_(NULL), | 299 parent_field_(NULL), |
| 295 typeinfo_(typeinfo), | 300 typeinfo_(typeinfo), |
| 301 proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), |
| 296 type_(type), | 302 type_(type), |
| 297 required_fields_(GetRequiredFields(type)), | |
| 298 size_index_(-1), | 303 size_index_(-1), |
| 299 array_index_(-1) {} | 304 array_index_(-1), |
| 305 // oneof_indices_ values are 1-indexed (0 means not present). |
| 306 oneof_indices_(type.oneofs_size() + 1) { |
| 307 if (!proto3_) { |
| 308 required_fields_ = GetRequiredFields(type_); |
| 309 } |
| 310 } |
| 300 | 311 |
| 301 ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, | 312 ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, |
| 302 const google::protobuf::Field* field, | 313 const google::protobuf::Field* field, |
| 303 const google::protobuf::Type& type, | 314 const google::protobuf::Type& type, |
| 304 bool is_list) | 315 bool is_list) |
| 305 : BaseElement(parent), | 316 : BaseElement(parent), |
| 306 ow_(this->parent()->ow_), | 317 ow_(this->parent()->ow_), |
| 307 parent_field_(field), | 318 parent_field_(field), |
| 308 typeinfo_(this->parent()->typeinfo_), | 319 typeinfo_(this->parent()->typeinfo_), |
| 320 proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), |
| 309 type_(type), | 321 type_(type), |
| 310 size_index_( | 322 size_index_( |
| 311 !is_list && field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE | 323 !is_list && field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE |
| 312 ? ow_->size_insert_.size() | 324 ? ow_->size_insert_.size() |
| 313 : -1), | 325 : -1), |
| 314 array_index_(is_list ? 0 : -1) { | 326 array_index_(is_list ? 0 : -1), |
| 327 // oneof_indices_ values are 1-indexed (0 means not present). |
| 328 oneof_indices_(type_.oneofs_size() + 1) { |
| 315 if (!is_list) { | 329 if (!is_list) { |
| 316 if (ow_->IsRepeated(*field)) { | 330 if (ow_->IsRepeated(*field)) { |
| 317 // Update array_index_ if it is an explicit list. | 331 // Update array_index_ if it is an explicit list. |
| 318 if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; | 332 if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; |
| 319 } else { | 333 } else if (!proto3_) { |
| 334 // For required fields tracking. |
| 320 this->parent()->RegisterField(field); | 335 this->parent()->RegisterField(field); |
| 321 } | 336 } |
| 322 | 337 |
| 323 if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { | 338 if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { |
| 324 required_fields_ = GetRequiredFields(type_); | 339 if (!proto3_) { |
| 340 required_fields_ = GetRequiredFields(type_); |
| 341 } |
| 325 int start_pos = ow_->stream_->ByteCount(); | 342 int start_pos = ow_->stream_->ByteCount(); |
| 326 // length of serialized message is the final buffer position minus | 343 // length of serialized message is the final buffer position minus |
| 327 // starting buffer position, plus length adjustments for size fields | 344 // starting buffer position, plus length adjustments for size fields |
| 328 // of any nested messages. We start with -start_pos here, so we only | 345 // of any nested messages. We start with -start_pos here, so we only |
| 329 // need to add the final buffer position to it at the end. | 346 // need to add the final buffer position to it at the end. |
| 330 SizeInfo info = {start_pos, -start_pos}; | 347 SizeInfo info = {start_pos, -start_pos}; |
| 331 ow_->size_insert_.push_back(info); | 348 ow_->size_insert_.push_back(info); |
| 332 } | 349 } |
| 333 } | 350 } |
| 334 } | 351 } |
| 335 | 352 |
| 336 ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() { | 353 ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() { |
| 337 // Calls the registered error listener for any required field(s) not yet | 354 if (!proto3_) { |
| 338 // seen. | 355 // Calls the registered error listener for any required field(s) not yet |
| 339 for (set<const google::protobuf::Field*>::iterator it = | 356 // seen. |
| 340 required_fields_.begin(); | 357 for (std::set<const google::protobuf::Field*>::iterator it = |
| 341 it != required_fields_.end(); ++it) { | 358 required_fields_.begin(); |
| 342 ow_->MissingField((*it)->name()); | 359 it != required_fields_.end(); ++it) { |
| 360 ow_->MissingField((*it)->name()); |
| 361 } |
| 343 } | 362 } |
| 344 // Computes the total number of proto bytes used by a message, also adjusts | 363 // Computes the total number of proto bytes used by a message, also adjusts |
| 345 // the size of all parent messages by the length of this size field. | 364 // the size of all parent messages by the length of this size field. |
| 346 // If size_index_ < 0, this is not a message, so no size field is added. | 365 // If size_index_ < 0, this is not a message, so no size field is added. |
| 347 if (size_index_ >= 0) { | 366 if (size_index_ >= 0) { |
| 348 // Add the final buffer position to compute the total length of this | 367 // Add the final buffer position to compute the total length of this |
| 349 // serialized message. The stored value (before this addition) already | 368 // serialized message. The stored value (before this addition) already |
| 350 // contains the total length of the size fields of all nested messages | 369 // contains the total length of the size fields of all nested messages |
| 351 // minus the initial buffer position. | 370 // minus the initial buffer position. |
| 352 ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount(); | 371 ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 StrAppend(&loc, "[\"", CEscape(name), "\"]"); | 411 StrAppend(&loc, "[\"", CEscape(name), "\"]"); |
| 393 } | 412 } |
| 394 } | 413 } |
| 395 if (ow_->IsRepeated(*parent_field_) && array_index_ > 0) { | 414 if (ow_->IsRepeated(*parent_field_) && array_index_ > 0) { |
| 396 StrAppend(&loc, "[", array_index_ - 1, "]"); | 415 StrAppend(&loc, "[", array_index_ - 1, "]"); |
| 397 } | 416 } |
| 398 return loc.empty() ? "." : loc; | 417 return loc.empty() ? "." : loc; |
| 399 } | 418 } |
| 400 | 419 |
| 401 bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) { | 420 bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) { |
| 402 return ContainsKey(oneof_indices_, index); | 421 return oneof_indices_[index]; |
| 403 } | 422 } |
| 404 | 423 |
| 405 void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) { | 424 void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) { |
| 406 InsertIfNotPresent(&oneof_indices_, index); | 425 oneof_indices_[index] = true; |
| 407 } | 426 } |
| 408 | 427 |
| 409 void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) { | 428 void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) { |
| 410 listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); | 429 listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); |
| 411 } | 430 } |
| 412 | 431 |
| 413 void ProtoWriter::InvalidValue(StringPiece type_name, StringPiece value) { | 432 void ProtoWriter::InvalidValue(StringPiece type_name, StringPiece value) { |
| 414 listener_->InvalidValue(location(), type_name, value); | 433 listener_->InvalidValue(location(), type_name, value); |
| 415 } | 434 } |
| 416 | 435 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 return this; | 573 return this; |
| 555 } | 574 } |
| 556 | 575 |
| 557 ProtoWriter* ProtoWriter::RenderPrimitiveField( | 576 ProtoWriter* ProtoWriter::RenderPrimitiveField( |
| 558 const google::protobuf::Field& field, const google::protobuf::Type& type, | 577 const google::protobuf::Field& field, const google::protobuf::Type& type, |
| 559 const DataPiece& data) { | 578 const DataPiece& data) { |
| 560 Status status; | 579 Status status; |
| 561 | 580 |
| 562 // Pushing a ProtoElement and then pop it off at the end for 2 purposes: | 581 // Pushing a ProtoElement and then pop it off at the end for 2 purposes: |
| 563 // error location reporting and required field accounting. | 582 // error location reporting and required field accounting. |
| 564 element_.reset(new ProtoElement(element_.release(), &field, type, false)); | 583 // |
| 584 // For proto3, since there is no required field tracking, we only need to push |
| 585 // ProtoElement for error cases. |
| 586 if (!element_->proto3()) { |
| 587 element_.reset(new ProtoElement(element_.release(), &field, type, false)); |
| 588 } |
| 565 | 589 |
| 566 if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN || | 590 if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN || |
| 567 field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { | 591 field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { |
| 592 // Push a ProtoElement for location reporting purposes. |
| 593 if (element_->proto3()) { |
| 594 element_.reset(new ProtoElement(element_.release(), &field, type, false)); |
| 595 } |
| 568 InvalidValue(field.type_url().empty() | 596 InvalidValue(field.type_url().empty() |
| 569 ? google::protobuf::Field_Kind_Name(field.kind()) | 597 ? google::protobuf::Field_Kind_Name(field.kind()) |
| 570 : field.type_url(), | 598 : field.type_url(), |
| 571 data.ValueAsStringOrDefault("")); | 599 data.ValueAsStringOrDefault("")); |
| 572 element_.reset(element()->pop()); | 600 element_.reset(element()->pop()); |
| 573 return this; | 601 return this; |
| 574 } | 602 } |
| 575 | 603 |
| 576 switch (field.kind()) { | 604 switch (field.kind()) { |
| 577 case google::protobuf::Field_Kind_TYPE_INT32: { | 605 case google::protobuf::Field_Kind_TYPE_INT32: { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 status = WriteBytes(field.number(), data, stream_.get()); | 658 status = WriteBytes(field.number(), data, stream_.get()); |
| 631 break; | 659 break; |
| 632 } | 660 } |
| 633 case google::protobuf::Field_Kind_TYPE_STRING: { | 661 case google::protobuf::Field_Kind_TYPE_STRING: { |
| 634 status = WriteString(field.number(), data, stream_.get()); | 662 status = WriteString(field.number(), data, stream_.get()); |
| 635 break; | 663 break; |
| 636 } | 664 } |
| 637 case google::protobuf::Field_Kind_TYPE_ENUM: { | 665 case google::protobuf::Field_Kind_TYPE_ENUM: { |
| 638 status = WriteEnum(field.number(), data, | 666 status = WriteEnum(field.number(), data, |
| 639 typeinfo_->GetEnumByTypeUrl(field.type_url()), | 667 typeinfo_->GetEnumByTypeUrl(field.type_url()), |
| 640 stream_.get()); | 668 stream_.get(), use_lower_camel_for_enums_); |
| 641 break; | 669 break; |
| 642 } | 670 } |
| 643 default: // TYPE_GROUP or TYPE_MESSAGE | 671 default: // TYPE_GROUP or TYPE_MESSAGE |
| 644 status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie()); | 672 status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie()); |
| 645 } | 673 } |
| 646 | 674 |
| 647 if (!status.ok()) { | 675 if (!status.ok()) { |
| 676 // Push a ProtoElement for location reporting purposes. |
| 677 if (element_->proto3()) { |
| 678 element_.reset(new ProtoElement(element_.release(), &field, type, false)); |
| 679 } |
| 648 InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), | 680 InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), |
| 649 status.error_message()); | 681 status.error_message()); |
| 682 element_.reset(element()->pop()); |
| 683 return this; |
| 650 } | 684 } |
| 651 | 685 |
| 652 element_.reset(element()->pop()); | 686 if (!element_->proto3()) element_.reset(element()->pop()); |
| 687 |
| 653 return this; | 688 return this; |
| 654 } | 689 } |
| 655 | 690 |
| 656 const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name, | 691 const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name, |
| 657 bool is_list) { | 692 bool is_list) { |
| 658 if (invalid_depth_ > 0) { | 693 if (invalid_depth_ > 0) { |
| 659 ++invalid_depth_; | 694 ++invalid_depth_; |
| 660 return NULL; | 695 return NULL; |
| 661 } | 696 } |
| 662 const google::protobuf::Field* field = Lookup(name); | 697 const google::protobuf::Field* field = Lookup(name); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 685 if (e->parent_field() == NULL) { | 720 if (e->parent_field() == NULL) { |
| 686 InvalidName(unnormalized_name, "Proto fields must have a name."); | 721 InvalidName(unnormalized_name, "Proto fields must have a name."); |
| 687 } else if (!IsRepeated(*e->parent_field())) { | 722 } else if (!IsRepeated(*e->parent_field())) { |
| 688 InvalidName(unnormalized_name, "Proto fields must have a name."); | 723 InvalidName(unnormalized_name, "Proto fields must have a name."); |
| 689 return NULL; | 724 return NULL; |
| 690 } | 725 } |
| 691 return e->parent_field(); | 726 return e->parent_field(); |
| 692 } | 727 } |
| 693 const google::protobuf::Field* field = | 728 const google::protobuf::Field* field = |
| 694 typeinfo_->FindField(&e->type(), unnormalized_name); | 729 typeinfo_->FindField(&e->type(), unnormalized_name); |
| 695 if (field == NULL) InvalidName(unnormalized_name, "Cannot find field."); | 730 if (field == NULL && !ignore_unknown_fields_) { |
| 731 InvalidName(unnormalized_name, "Cannot find field."); |
| 732 } |
| 696 return field; | 733 return field; |
| 697 } | 734 } |
| 698 | 735 |
| 699 const google::protobuf::Type* ProtoWriter::LookupType( | 736 const google::protobuf::Type* ProtoWriter::LookupType( |
| 700 const google::protobuf::Field* field) { | 737 const google::protobuf::Field* field) { |
| 701 return ((field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE || | 738 return ((field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE || |
| 702 field->kind() == google::protobuf::Field_Kind_TYPE_GROUP) | 739 field->kind() == google::protobuf::Field_Kind_TYPE_GROUP) |
| 703 ? typeinfo_->GetTypeByTypeUrl(field->type_url()) | 740 ? typeinfo_->GetTypeByTypeUrl(field->type_url()) |
| 704 : &element_->type()); | 741 : &element_->type()); |
| 705 } | 742 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( | 790 WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( |
| 754 static_cast<WireFormatLite::FieldType>(field.kind())); | 791 static_cast<WireFormatLite::FieldType>(field.kind())); |
| 755 stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); | 792 stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); |
| 756 } | 793 } |
| 757 | 794 |
| 758 | 795 |
| 759 } // namespace converter | 796 } // namespace converter |
| 760 } // namespace util | 797 } // namespace util |
| 761 } // namespace protobuf | 798 } // namespace protobuf |
| 762 } // namespace google | 799 } // namespace google |
| OLD | NEW |