Index: third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc |
diff --git a/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc b/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc |
deleted file mode 100644 |
index 8e0897d82d653227a81936eb179315b74fc27515..0000000000000000000000000000000000000000 |
--- a/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc |
+++ /dev/null |
@@ -1,1051 +0,0 @@ |
-// Protocol Buffers - Google's data interchange format |
-// Copyright 2008 Google Inc. All rights reserved. |
-// https://developers.google.com/protocol-buffers/ |
-// |
-// Redistribution and use in source and binary forms, with or without |
-// modification, are permitted provided that the following conditions are |
-// met: |
-// |
-// * Redistributions of source code must retain the above copyright |
-// notice, this list of conditions and the following disclaimer. |
-// * Redistributions in binary form must reproduce the above |
-// copyright notice, this list of conditions and the following disclaimer |
-// in the documentation and/or other materials provided with the |
-// distribution. |
-// * Neither the name of Google Inc. nor the names of its |
-// contributors may be used to endorse or promote products derived from |
-// this software without specific prior written permission. |
-// |
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- |
-#include <google/protobuf/util/internal/protostream_objectsource.h> |
- |
-#include <utility> |
- |
-#include <google/protobuf/stubs/casts.h> |
-#include <google/protobuf/stubs/common.h> |
-#include <google/protobuf/stubs/stringprintf.h> |
-#include <google/protobuf/stubs/time.h> |
-#include <google/protobuf/io/coded_stream.h> |
-#include <google/protobuf/io/zero_copy_stream_impl.h> |
-#include <google/protobuf/descriptor.h> |
-#include <google/protobuf/wire_format.h> |
-#include <google/protobuf/wire_format_lite.h> |
-#include <google/protobuf/util/internal/field_mask_utility.h> |
-#include <google/protobuf/util/internal/constants.h> |
-#include <google/protobuf/util/internal/utility.h> |
-#include <google/protobuf/stubs/strutil.h> |
-#include <google/protobuf/stubs/map_util.h> |
-#include <google/protobuf/stubs/status_macros.h> |
- |
- |
-namespace google { |
-namespace protobuf { |
-namespace util { |
-using util::Status; |
-using util::StatusOr; |
-namespace error { |
-using util::error::Code; |
-using util::error::INTERNAL; |
-} |
-namespace converter { |
- |
-using google::protobuf::Descriptor; |
-using google::protobuf::EnumValueDescriptor; |
-using google::protobuf::FieldDescriptor; |
-using google::protobuf::internal::WireFormat; |
-using google::protobuf::internal::WireFormatLite; |
-using util::Status; |
-using util::StatusOr; |
- |
-namespace { |
-// Finds a field with the given number. NULL if none found. |
-const google::protobuf::Field* FindFieldByNumber( |
- const google::protobuf::Type& type, int number); |
- |
-// Returns true if the field is packable. |
-bool IsPackable(const google::protobuf::Field& field); |
- |
-// Finds an enum value with the given number. NULL if none found. |
-const google::protobuf::EnumValue* FindEnumValueByNumber( |
- const google::protobuf::Enum& tech_enum, int number); |
- |
-// Utility function to format nanos. |
-const string FormatNanos(uint32 nanos); |
-} // namespace |
- |
- |
-ProtoStreamObjectSource::ProtoStreamObjectSource( |
- google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver, |
- const google::protobuf::Type& type) |
- : stream_(stream), |
- typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), |
- own_typeinfo_(true), |
- type_(type) { |
- GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; |
-} |
- |
-ProtoStreamObjectSource::ProtoStreamObjectSource( |
- google::protobuf::io::CodedInputStream* stream, TypeInfo* typeinfo, |
- const google::protobuf::Type& type) |
- : stream_(stream), typeinfo_(typeinfo), own_typeinfo_(false), type_(type) { |
- GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; |
-} |
- |
-ProtoStreamObjectSource::~ProtoStreamObjectSource() { |
- if (own_typeinfo_) { |
- delete typeinfo_; |
- } |
-} |
- |
-Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, |
- ObjectWriter* ow) const { |
- return WriteMessage(type_, name, 0, true, ow); |
-} |
- |
-const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField( |
- const google::protobuf::Type& type, uint32 tag) const { |
- // Lookup the new field in the type by tag number. |
- const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3); |
- // Verify if the field corresponds to the wire type in tag. |
- // If there is any discrepancy, mark the field as not found. |
- if (field != NULL) { |
- WireFormatLite::WireType expected_type = |
- WireFormatLite::WireTypeForFieldType( |
- static_cast<WireFormatLite::FieldType>(field->kind())); |
- WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag); |
- if (actual_type != expected_type && |
- (!IsPackable(*field) || |
- actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { |
- field = NULL; |
- } |
- } |
- return field; |
-} |
- |
-Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, |
- StringPiece name, |
- const uint32 end_tag, |
- bool include_start_and_end, |
- ObjectWriter* ow) const { |
- const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); |
- if (type_renderer != NULL) { |
- return (*type_renderer)(this, type, name, ow); |
- } |
- |
- const google::protobuf::Field* field = NULL; |
- string field_name; |
- // last_tag set to dummy value that is different from tag. |
- uint32 tag = stream_->ReadTag(), last_tag = tag + 1; |
- |
- if (include_start_and_end) { |
- ow->StartObject(name); |
- } |
- while (tag != end_tag) { |
- if (tag != last_tag) { // Update field only if tag is changed. |
- last_tag = tag; |
- field = FindAndVerifyField(type, tag); |
- if (field != NULL) { |
- field_name = field->name(); |
- } |
- } |
- if (field == NULL) { |
- // If we didn't find a field, skip this unknown tag. |
- // TODO(wpoon): Check return boolean value. |
- WireFormatLite::SkipField(stream_, tag); |
- tag = stream_->ReadTag(); |
- continue; |
- } |
- |
- if (field->cardinality() == |
- google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { |
- if (IsMap(*field)) { |
- ow->StartObject(field_name); |
- ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow)); |
- ow->EndObject(); |
- } else { |
- ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow)); |
- } |
- } else { |
- // Render the field. |
- RETURN_IF_ERROR(RenderField(field, field_name, ow)); |
- tag = stream_->ReadTag(); |
- } |
- } |
- if (include_start_and_end) { |
- ow->EndObject(); |
- } |
- return Status::OK; |
-} |
- |
-StatusOr<uint32> ProtoStreamObjectSource::RenderList( |
- const google::protobuf::Field* field, StringPiece name, uint32 list_tag, |
- ObjectWriter* ow) const { |
- uint32 tag_to_return = 0; |
- ow->StartList(name); |
- if (IsPackable(*field) && |
- list_tag == |
- WireFormatLite::MakeTag(field->number(), |
- WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { |
- RETURN_IF_ERROR(RenderPacked(field, ow)); |
- // Since packed fields have a single tag, read another tag from stream to |
- // return. |
- tag_to_return = stream_->ReadTag(); |
- } else { |
- do { |
- RETURN_IF_ERROR(RenderField(field, "", ow)); |
- } while ((tag_to_return = stream_->ReadTag()) == list_tag); |
- } |
- ow->EndList(); |
- return tag_to_return; |
-} |
- |
-StatusOr<uint32> ProtoStreamObjectSource::RenderMap( |
- const google::protobuf::Field* field, StringPiece name, uint32 list_tag, |
- ObjectWriter* ow) const { |
- const google::protobuf::Type* field_type = |
- typeinfo_->GetType(field->type_url()); |
- uint32 tag_to_return = 0; |
- if (IsPackable(*field) && |
- list_tag == |
- WireFormatLite::MakeTag(field->number(), |
- WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { |
- RETURN_IF_ERROR(RenderPackedMapEntry(field_type, ow)); |
- tag_to_return = stream_->ReadTag(); |
- } else { |
- do { |
- RETURN_IF_ERROR(RenderMapEntry(field_type, ow)); |
- } while ((tag_to_return = stream_->ReadTag()) == list_tag); |
- } |
- return tag_to_return; |
-} |
- |
-Status ProtoStreamObjectSource::RenderMapEntry( |
- const google::protobuf::Type* type, ObjectWriter* ow) const { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); // message length |
- int old_limit = stream_->PushLimit(buffer32); |
- string map_key; |
- for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { |
- const google::protobuf::Field* field = FindAndVerifyField(*type, tag); |
- if (field == NULL) { |
- WireFormatLite::SkipField(stream_, tag); |
- continue; |
- } |
- // Map field numbers are key = 1 and value = 2 |
- if (field->number() == 1) { |
- map_key = ReadFieldValueAsString(*field); |
- } else if (field->number() == 2) { |
- if (map_key.empty()) { |
- return Status(util::error::INTERNAL, "Map key must be non-empty"); |
- } |
- // Disable case normalization for map keys as they are just data. We |
- // retain them intact. |
- ow->DisableCaseNormalizationForNextKey(); |
- RETURN_IF_ERROR(RenderField(field, map_key, ow)); |
- } |
- } |
- stream_->PopLimit(old_limit); |
- |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderPacked( |
- const google::protobuf::Field* field, ObjectWriter* ow) const { |
- uint32 length; |
- stream_->ReadVarint32(&length); |
- int old_limit = stream_->PushLimit(length); |
- while (stream_->BytesUntilLimit() > 0) { |
- RETURN_IF_ERROR(RenderField(field, StringPiece(), ow)); |
- } |
- stream_->PopLimit(old_limit); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderPackedMapEntry( |
- const google::protobuf::Type* type, ObjectWriter* ow) const { |
- uint32 length; |
- stream_->ReadVarint32(&length); |
- int old_limit = stream_->PushLimit(length); |
- while (stream_->BytesUntilLimit() > 0) { |
- RETURN_IF_ERROR(RenderMapEntry(type, ow)); |
- } |
- stream_->PopLimit(old_limit); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderTimestamp( |
- const ProtoStreamObjectSource* os, const google::protobuf::Type& type, |
- StringPiece field_name, ObjectWriter* ow) { |
- pair<int64, int32> p = os->ReadSecondsAndNanos(type); |
- int64 seconds = p.first; |
- int32 nanos = p.second; |
- if (seconds > kMaxSeconds || seconds < kMinSeconds) { |
- return Status( |
- util::error::INTERNAL, |
- StrCat("Timestamp seconds exceeds limit for field: ", field_name)); |
- } |
- |
- if (nanos < 0 || nanos >= kNanosPerSecond) { |
- return Status( |
- util::error::INTERNAL, |
- StrCat("Timestamp nanos exceeds limit for field: ", field_name)); |
- } |
- |
- ow->RenderString(field_name, |
- ::google::protobuf::internal::FormatTime(seconds, nanos)); |
- |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderDuration( |
- const ProtoStreamObjectSource* os, const google::protobuf::Type& type, |
- StringPiece field_name, ObjectWriter* ow) { |
- pair<int64, int32> p = os->ReadSecondsAndNanos(type); |
- int64 seconds = p.first; |
- int32 nanos = p.second; |
- if (seconds > kMaxSeconds || seconds < kMinSeconds) { |
- return Status( |
- util::error::INTERNAL, |
- StrCat("Duration seconds exceeds limit for field: ", field_name)); |
- } |
- |
- if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { |
- return Status( |
- util::error::INTERNAL, |
- StrCat("Duration nanos exceeds limit for field: ", field_name)); |
- } |
- |
- string sign = ""; |
- if (seconds < 0) { |
- if (nanos > 0) { |
- return Status(util::error::INTERNAL, |
- StrCat( |
- "Duration nanos is non-negative, but seconds is " |
- "negative for field: ", |
- field_name)); |
- } |
- sign = "-"; |
- seconds = -seconds; |
- nanos = -nanos; |
- } else if (seconds == 0 && nanos < 0) { |
- sign = "-"; |
- nanos = -nanos; |
- } |
- string formatted_duration = StringPrintf("%s%lld%ss", sign.c_str(), seconds, |
- FormatNanos(nanos).c_str()); |
- ow->RenderString(field_name, formatted_duration); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint64 buffer64 = 0; // default value of Double wrapper value |
- if (tag != 0) { |
- os->stream_->ReadLittleEndian64(&buffer64); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderDouble(field_name, bit_cast<double>(buffer64)); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint32 buffer32 = 0; // default value of Float wrapper value |
- if (tag != 0) { |
- os->stream_->ReadLittleEndian32(&buffer32); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderFloat(field_name, bit_cast<float>(buffer32)); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint64 buffer64 = 0; // default value of Int64 wrapper value |
- if (tag != 0) { |
- os->stream_->ReadVarint64(&buffer64); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint64 buffer64 = 0; // default value of UInt64 wrapper value |
- if (tag != 0) { |
- os->stream_->ReadVarint64(&buffer64); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint32 buffer32 = 0; // default value of Int32 wrapper value |
- if (tag != 0) { |
- os->stream_->ReadVarint32(&buffer32); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint32 buffer32 = 0; // default value of UInt32 wrapper value |
- if (tag != 0) { |
- os->stream_->ReadVarint32(&buffer32); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint64 buffer64 = 0; // results in 'false' value as default, which is the |
- // default value of Bool wrapper |
- if (tag != 0) { |
- os->stream_->ReadVarint64(&buffer64); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderBool(field_name, buffer64 != 0); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint32 buffer32; |
- string str; // default value of empty for String wrapper |
- if (tag != 0) { |
- os->stream_->ReadVarint32(&buffer32); // string size. |
- os->stream_->ReadString(&str, buffer32); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderString(field_name, str); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- uint32 buffer32; |
- string str; |
- if (tag != 0) { |
- os->stream_->ReadVarint32(&buffer32); |
- os->stream_->ReadString(&str, buffer32); |
- os->stream_->ReadTag(); |
- } |
- ow->RenderBytes(field_name, str); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- const google::protobuf::Field* field = NULL; |
- uint32 tag = os->stream_->ReadTag(); |
- ow->StartObject(field_name); |
- while (tag != 0) { |
- field = os->FindAndVerifyField(type, tag); |
- // google.protobuf.Struct has only one field that is a map. Hence we use |
- // RenderMap to render that field. |
- if (os->IsMap(*field)) { |
- ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow)); |
- } |
- } |
- ow->EndObject(); |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderStructValue( |
- const ProtoStreamObjectSource* os, const google::protobuf::Type& type, |
- StringPiece field_name, ObjectWriter* ow) { |
- const google::protobuf::Field* field = NULL; |
- for (uint32 tag = os->stream_->ReadTag(); tag != 0; |
- tag = os->stream_->ReadTag()) { |
- field = os->FindAndVerifyField(type, tag); |
- if (field == NULL) { |
- WireFormatLite::SkipField(os->stream_, tag); |
- continue; |
- } |
- RETURN_IF_ERROR(os->RenderField(field, field_name, ow)); |
- } |
- return Status::OK; |
-} |
- |
-// TODO(skarvaje): Avoid code duplication of for loops and SkipField logic. |
-Status ProtoStreamObjectSource::RenderStructListValue( |
- const ProtoStreamObjectSource* os, const google::protobuf::Type& type, |
- StringPiece field_name, ObjectWriter* ow) { |
- uint32 tag = os->stream_->ReadTag(); |
- |
- // Render empty list when we find empty ListValue message. |
- if (tag == 0) { |
- ow->StartList(field_name); |
- ow->EndList(); |
- return Status::OK; |
- } |
- |
- while (tag != 0) { |
- const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); |
- if (field == NULL) { |
- WireFormatLite::SkipField(os->stream_, tag); |
- tag = os->stream_->ReadTag(); |
- continue; |
- } |
- ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow)); |
- } |
- return Status::OK; |
-} |
- |
-Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, |
- const google::protobuf::Type& type, |
- StringPiece field_name, |
- ObjectWriter* ow) { |
- // An Any is of the form { string type_url = 1; bytes value = 2; } |
- uint32 tag; |
- string type_url; |
- string value; |
- |
- // First read out the type_url and value from the proto stream |
- for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) { |
- const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); |
- if (field == NULL) { |
- WireFormatLite::SkipField(os->stream_, tag); |
- continue; |
- } |
- // 'type_url' has field number of 1 and 'value' has field number 2 |
- // //google/protobuf/any.proto |
- if (field->number() == 1) { |
- // read type_url |
- uint32 type_url_size; |
- os->stream_->ReadVarint32(&type_url_size); |
- os->stream_->ReadString(&type_url, type_url_size); |
- } else if (field->number() == 2) { |
- // read value |
- uint32 value_size; |
- os->stream_->ReadVarint32(&value_size); |
- os->stream_->ReadString(&value, value_size); |
- } |
- } |
- |
- // If there is no value, we don't lookup the type, we just output it (if |
- // present). If both type and value are empty we output an empty object. |
- if (value.empty()) { |
- ow->StartObject(field_name); |
- if (!type_url.empty()) { |
- ow->RenderString("@type", type_url); |
- } |
- ow->EndObject(); |
- return util::Status::OK; |
- } |
- |
- // If there is a value but no type, we cannot render it, so report an error. |
- if (type_url.empty()) { |
- // TODO(sven): Add an external message once those are ready. |
- return util::Status(util::error::INTERNAL, |
- "Invalid Any, the type_url is missing."); |
- } |
- |
- util::StatusOr<const google::protobuf::Type*> resolved_type = |
- os->typeinfo_->ResolveTypeUrl(type_url); |
- |
- if (!resolved_type.ok()) { |
- // Convert into an internal error, since this means the backend gave us |
- // an invalid response (missing or invalid type information). |
- return util::Status(util::error::INTERNAL, |
- resolved_type.status().error_message()); |
- } |
- // nested_type cannot be null at this time. |
- const google::protobuf::Type* nested_type = resolved_type.ValueOrDie(); |
- |
- // We know the type so we can render it. Recursively parse the nested stream |
- // using a nested ProtoStreamObjectSource using our nested type information. |
- google::protobuf::io::ArrayInputStream zero_copy_stream(value.data(), value.size()); |
- google::protobuf::io::CodedInputStream in_stream(&zero_copy_stream); |
- ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type); |
- |
- // We manually call start and end object here so we can inject the @type. |
- ow->StartObject(field_name); |
- ow->RenderString("@type", type_url); |
- util::Status result = |
- nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow); |
- ow->EndObject(); |
- return result; |
-} |
- |
-Status ProtoStreamObjectSource::RenderFieldMask( |
- const ProtoStreamObjectSource* os, const google::protobuf::Type& type, |
- StringPiece field_name, ObjectWriter* ow) { |
- string combined; |
- uint32 buffer32; |
- uint32 paths_field_tag = 0; |
- for (uint32 tag = os->stream_->ReadTag(); tag != 0; |
- tag = os->stream_->ReadTag()) { |
- if (paths_field_tag == 0) { |
- const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); |
- if (field != NULL && field->number() == 1 && |
- field->name() == "paths") { |
- paths_field_tag = tag; |
- } |
- } |
- if (paths_field_tag != tag) { |
- return util::Status(util::error::INTERNAL, |
- "Invalid FieldMask, unexpected field."); |
- } |
- string str; |
- os->stream_->ReadVarint32(&buffer32); // string size. |
- os->stream_->ReadString(&str, buffer32); |
- if (!combined.empty()) { |
- combined.append(","); |
- } |
- combined.append(ConvertFieldMaskPath(str, &ToCamelCase)); |
- } |
- ow->RenderString(field_name, combined); |
- return Status::OK; |
-} |
- |
-hash_map<string, ProtoStreamObjectSource::TypeRenderer>* |
-ProtoStreamObjectSource::CreateRendererMap() { |
- hash_map<string, ProtoStreamObjectSource::TypeRenderer>* result = |
- new hash_map<string, ProtoStreamObjectSource::TypeRenderer>(); |
- (*result)["google.protobuf.Timestamp"] = |
- &ProtoStreamObjectSource::RenderTimestamp; |
- (*result)["google.protobuf.Duration"] = |
- &ProtoStreamObjectSource::RenderDuration; |
- (*result)["google.protobuf.DoubleValue"] = |
- &ProtoStreamObjectSource::RenderDouble; |
- (*result)["google.protobuf.FloatValue"] = |
- &ProtoStreamObjectSource::RenderFloat; |
- (*result)["google.protobuf.Int64Value"] = |
- &ProtoStreamObjectSource::RenderInt64; |
- (*result)["google.protobuf.UInt64Value"] = |
- &ProtoStreamObjectSource::RenderUInt64; |
- (*result)["google.protobuf.Int32Value"] = |
- &ProtoStreamObjectSource::RenderInt32; |
- (*result)["google.protobuf.UInt32Value"] = |
- &ProtoStreamObjectSource::RenderUInt32; |
- (*result)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool; |
- (*result)["google.protobuf.StringValue"] = |
- &ProtoStreamObjectSource::RenderString; |
- (*result)["google.protobuf.BytesValue"] = |
- &ProtoStreamObjectSource::RenderBytes; |
- (*result)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny; |
- (*result)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct; |
- (*result)["google.protobuf.Value"] = |
- &ProtoStreamObjectSource::RenderStructValue; |
- (*result)["google.protobuf.ListValue"] = |
- &ProtoStreamObjectSource::RenderStructListValue; |
- (*result)["google.protobuf.FieldMask"] = |
- &ProtoStreamObjectSource::RenderFieldMask; |
- return result; |
-} |
- |
-// static |
-ProtoStreamObjectSource::TypeRenderer* |
-ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) { |
- static hash_map<string, TypeRenderer>* renderers = CreateRendererMap(); |
- return FindOrNull(*renderers, type_url); |
-} |
- |
-Status ProtoStreamObjectSource::RenderField( |
- const google::protobuf::Field* field, StringPiece field_name, |
- ObjectWriter* ow) const { |
- switch (field->kind()) { |
- case google::protobuf::Field_Kind_TYPE_BOOL: { |
- uint64 buffer64; |
- stream_->ReadVarint64(&buffer64); |
- ow->RenderBool(field_name, buffer64 != 0); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_INT32: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); |
- ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_INT64: { |
- uint64 buffer64; |
- stream_->ReadVarint64(&buffer64); |
- ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_UINT32: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); |
- ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_UINT64: { |
- uint64 buffer64; |
- stream_->ReadVarint64(&buffer64); |
- ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_SINT32: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); |
- ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_SINT64: { |
- uint64 buffer64; |
- stream_->ReadVarint64(&buffer64); |
- ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_SFIXED32: { |
- uint32 buffer32; |
- stream_->ReadLittleEndian32(&buffer32); |
- ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_SFIXED64: { |
- uint64 buffer64; |
- stream_->ReadLittleEndian64(&buffer64); |
- ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_FIXED32: { |
- uint32 buffer32; |
- stream_->ReadLittleEndian32(&buffer32); |
- ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_FIXED64: { |
- uint64 buffer64; |
- stream_->ReadLittleEndian64(&buffer64); |
- ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_FLOAT: { |
- uint32 buffer32; |
- stream_->ReadLittleEndian32(&buffer32); |
- ow->RenderFloat(field_name, bit_cast<float>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_DOUBLE: { |
- uint64 buffer64; |
- stream_->ReadLittleEndian64(&buffer64); |
- ow->RenderDouble(field_name, bit_cast<double>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_ENUM: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); |
- |
- // If the field represents an explicit NULL value, render null. |
- if (field->type_url() == kStructNullValueTypeUrl) { |
- ow->RenderNull(field_name); |
- break; |
- } |
- |
- // Get the nested enum type for this field. |
- // TODO(skarvaje): Avoid string manipulation. Find ways to speed this |
- // up. |
- const google::protobuf::Enum* en = typeinfo_->GetEnum(field->type_url()); |
- // Lookup the name of the enum, and render that. Skips unknown enums. |
- if (en != NULL) { |
- const google::protobuf::EnumValue* enum_value = |
- FindEnumValueByNumber(*en, buffer32); |
- if (enum_value != NULL) { |
- ow->RenderString(field_name, enum_value->name()); |
- } |
- } else { |
- GOOGLE_LOG(INFO) << "Unkown enum skipped: " << field->type_url(); |
- } |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_STRING: { |
- uint32 buffer32; |
- string str; |
- stream_->ReadVarint32(&buffer32); // string size. |
- stream_->ReadString(&str, buffer32); |
- ow->RenderString(field_name, str); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_BYTES: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); // bytes size. |
- string value; |
- stream_->ReadString(&value, buffer32); |
- ow->RenderBytes(field_name, value); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_MESSAGE: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); // message length |
- int old_limit = stream_->PushLimit(buffer32); |
- // Get the nested message type for this field. |
- const google::protobuf::Type* type = |
- typeinfo_->GetType(field->type_url()); |
- if (type == NULL) { |
- return Status(util::error::INTERNAL, |
- StrCat("Invalid configuration. Could not find the type: ", |
- field->type_url())); |
- } |
- RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow)); |
- if (!stream_->ConsumedEntireMessage()) { |
- return Status(util::error::INVALID_ARGUMENT, |
- "Nested protocol message not parsed in its entirety."); |
- } |
- stream_->PopLimit(old_limit); |
- break; |
- } |
- default: |
- break; |
- } |
- return Status::OK; |
-} |
- |
-// TODO(skarvaje): Fix this to avoid code duplication. |
-const string ProtoStreamObjectSource::ReadFieldValueAsString( |
- const google::protobuf::Field& field) const { |
- string result; |
- switch (field.kind()) { |
- case google::protobuf::Field_Kind_TYPE_BOOL: { |
- uint64 buffer64; |
- stream_->ReadVarint64(&buffer64); |
- result = buffer64 != 0 ? "true" : "false"; |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_INT32: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); |
- result = SimpleItoa(bit_cast<int32>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_INT64: { |
- uint64 buffer64; |
- stream_->ReadVarint64(&buffer64); |
- result = SimpleItoa(bit_cast<int64>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_UINT32: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); |
- result = SimpleItoa(bit_cast<uint32>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_UINT64: { |
- uint64 buffer64; |
- stream_->ReadVarint64(&buffer64); |
- result = SimpleItoa(bit_cast<uint64>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_SINT32: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); |
- result = SimpleItoa(WireFormatLite::ZigZagDecode32(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_SINT64: { |
- uint64 buffer64; |
- stream_->ReadVarint64(&buffer64); |
- result = SimpleItoa(WireFormatLite::ZigZagDecode64(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_SFIXED32: { |
- uint32 buffer32; |
- stream_->ReadLittleEndian32(&buffer32); |
- result = SimpleItoa(bit_cast<int32>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_SFIXED64: { |
- uint64 buffer64; |
- stream_->ReadLittleEndian64(&buffer64); |
- result = SimpleItoa(bit_cast<int64>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_FIXED32: { |
- uint32 buffer32; |
- stream_->ReadLittleEndian32(&buffer32); |
- result = SimpleItoa(bit_cast<uint32>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_FIXED64: { |
- uint64 buffer64; |
- stream_->ReadLittleEndian64(&buffer64); |
- result = SimpleItoa(bit_cast<uint64>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_FLOAT: { |
- uint32 buffer32; |
- stream_->ReadLittleEndian32(&buffer32); |
- result = SimpleFtoa(bit_cast<float>(buffer32)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_DOUBLE: { |
- uint64 buffer64; |
- stream_->ReadLittleEndian64(&buffer64); |
- result = SimpleDtoa(bit_cast<double>(buffer64)); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_ENUM: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); |
- // Get the nested enum type for this field. |
- // TODO(skarvaje): Avoid string manipulation. Find ways to speed this |
- // up. |
- const google::protobuf::Enum* en = typeinfo_->GetEnum(field.type_url()); |
- // Lookup the name of the enum, and render that. Skips unknown enums. |
- if (en != NULL) { |
- const google::protobuf::EnumValue* enum_value = |
- FindEnumValueByNumber(*en, buffer32); |
- if (enum_value != NULL) { |
- result = enum_value->name(); |
- } |
- } |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_STRING: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); // string size. |
- stream_->ReadString(&result, buffer32); |
- break; |
- } |
- case google::protobuf::Field_Kind_TYPE_BYTES: { |
- uint32 buffer32; |
- stream_->ReadVarint32(&buffer32); // bytes size. |
- stream_->ReadString(&result, buffer32); |
- break; |
- } |
- default: |
- break; |
- } |
- return result; |
-} |
- |
-// Field is a map if it is a repeated message and it has an option "map_type". |
-// TODO(skarvaje): Consider pre-computing the IsMap() into Field directly. |
-bool ProtoStreamObjectSource::IsMap( |
- const google::protobuf::Field& field) const { |
- const google::protobuf::Type* field_type = |
- typeinfo_->GetType(field.type_url()); |
- |
- // TODO(xiaofeng): Unify option names. |
- return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && |
- (GetBoolOptionOrDefault(field_type->options(), |
- "google.protobuf.MessageOptions.map_entry", false) || |
- GetBoolOptionOrDefault(field_type->options(), "map_entry", false)); |
-} |
- |
-std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( |
- const google::protobuf::Type& type) const { |
- uint64 seconds = 0; |
- uint32 nanos = 0; |
- uint32 tag = 0; |
- int64 signed_seconds = 0; |
- int64 signed_nanos = 0; |
- |
- for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { |
- const google::protobuf::Field* field = FindAndVerifyField(type, tag); |
- if (field == NULL) { |
- WireFormatLite::SkipField(stream_, tag); |
- continue; |
- } |
- // 'seconds' has field number of 1 and 'nanos' has field number 2 |
- // //google/protobuf/timestamp.proto & duration.proto |
- if (field->number() == 1) { |
- // read seconds |
- stream_->ReadVarint64(&seconds); |
- signed_seconds = bit_cast<int64>(seconds); |
- } else if (field->number() == 2) { |
- // read nanos |
- stream_->ReadVarint32(&nanos); |
- signed_nanos = bit_cast<int32>(nanos); |
- } |
- } |
- return std::pair<int64, int32>(signed_seconds, signed_nanos); |
-} |
- |
-namespace { |
-// TODO(skarvaje): Speed this up by not doing a linear scan. |
-const google::protobuf::Field* FindFieldByNumber( |
- const google::protobuf::Type& type, int number) { |
- for (int i = 0; i < type.fields_size(); ++i) { |
- if (type.fields(i).number() == number) { |
- return &type.fields(i); |
- } |
- } |
- return NULL; |
-} |
- |
-// TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable() |
-// using tech Field. |
-bool IsPackable(const google::protobuf::Field& field) { |
- return field.cardinality() == |
- google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && |
- google::protobuf::FieldDescriptor::IsTypePackable( |
- static_cast<google::protobuf::FieldDescriptor::Type>(field.kind())); |
-} |
- |
-// TODO(skarvaje): Speed this up by not doing a linear scan. |
-const google::protobuf::EnumValue* FindEnumValueByNumber( |
- const google::protobuf::Enum& tech_enum, int number) { |
- for (int i = 0; i < tech_enum.enumvalue_size(); ++i) { |
- const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i); |
- if (ev.number() == number) { |
- return &ev; |
- } |
- } |
- return NULL; |
-} |
- |
-// TODO(skarvaje): Look into optimizing this by not doing computation on |
-// double. |
-const string FormatNanos(uint32 nanos) { |
- const char* format = |
- (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f"; |
- string formatted = |
- StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond); |
- // remove the leading 0 before decimal. |
- return formatted.substr(1); |
-} |
-} // namespace |
- |
-} // namespace converter |
-} // namespace util |
-} // namespace protobuf |
-} // namespace google |