Home | History | Annotate | Download | only in internal
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 #include <google/protobuf/util/internal/protostream_objectsource.h>
     32 
     33 #include <utility>
     34 
     35 #include <google/protobuf/stubs/casts.h>
     36 #include <google/protobuf/stubs/logging.h>
     37 #include <google/protobuf/stubs/common.h>
     38 #include <google/protobuf/stubs/stringprintf.h>
     39 #include <google/protobuf/stubs/time.h>
     40 #include <google/protobuf/io/coded_stream.h>
     41 #include <google/protobuf/io/zero_copy_stream_impl.h>
     42 #include <google/protobuf/descriptor.h>
     43 #include <google/protobuf/wire_format.h>
     44 #include <google/protobuf/wire_format_lite.h>
     45 #include <google/protobuf/util/internal/field_mask_utility.h>
     46 #include <google/protobuf/util/internal/constants.h>
     47 #include <google/protobuf/util/internal/utility.h>
     48 #include <google/protobuf/stubs/strutil.h>
     49 #include <google/protobuf/stubs/map_util.h>
     50 #include <google/protobuf/stubs/status_macros.h>
     51 
     52 
     53 namespace google {
     54 namespace protobuf {
     55 namespace util {
     56 using util::Status;
     57 using util::StatusOr;
     58 namespace error {
     59 using util::error::Code;
     60 using util::error::INTERNAL;
     61 }
     62 namespace converter {
     63 
     64 using google::protobuf::Descriptor;
     65 using google::protobuf::EnumValueDescriptor;
     66 using google::protobuf::FieldDescriptor;
     67 using google::protobuf::internal::WireFormat;
     68 using google::protobuf::internal::WireFormatLite;
     69 using util::Status;
     70 using util::StatusOr;
     71 
     72 namespace {
     73 
     74 static int kDefaultMaxRecursionDepth = 64;
     75 
     76 // Finds a field with the given number. NULL if none found.
     77 const google::protobuf::Field* FindFieldByNumber(
     78     const google::protobuf::Type& type, int number);
     79 
     80 // Returns true if the field is packable.
     81 bool IsPackable(const google::protobuf::Field& field);
     82 
     83 // Finds an enum value with the given number. NULL if none found.
     84 const google::protobuf::EnumValue* FindEnumValueByNumber(
     85     const google::protobuf::Enum& tech_enum, int number);
     86 
     87 // Utility function to format nanos.
     88 const string FormatNanos(uint32 nanos);
     89 
     90 StatusOr<string> MapKeyDefaultValueAsString(
     91     const google::protobuf::Field& field) {
     92   switch (field.kind()) {
     93     case google::protobuf::Field_Kind_TYPE_BOOL:
     94       return string("false");
     95     case google::protobuf::Field_Kind_TYPE_INT32:
     96     case google::protobuf::Field_Kind_TYPE_INT64:
     97     case google::protobuf::Field_Kind_TYPE_UINT32:
     98     case google::protobuf::Field_Kind_TYPE_UINT64:
     99     case google::protobuf::Field_Kind_TYPE_SINT32:
    100     case google::protobuf::Field_Kind_TYPE_SINT64:
    101     case google::protobuf::Field_Kind_TYPE_SFIXED32:
    102     case google::protobuf::Field_Kind_TYPE_SFIXED64:
    103     case google::protobuf::Field_Kind_TYPE_FIXED32:
    104     case google::protobuf::Field_Kind_TYPE_FIXED64:
    105       return string("0");
    106     case google::protobuf::Field_Kind_TYPE_STRING:
    107       return string();
    108     default:
    109       return Status(util::error::INTERNAL, "Invalid map key type.");
    110   }
    111 }
    112 }  // namespace
    113 
    114 
    115 ProtoStreamObjectSource::ProtoStreamObjectSource(
    116     google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver,
    117     const google::protobuf::Type& type)
    118     : stream_(stream),
    119       typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
    120       own_typeinfo_(true),
    121       type_(type),
    122       use_lower_camel_for_enums_(false),
    123       recursion_depth_(0),
    124       max_recursion_depth_(kDefaultMaxRecursionDepth) {
    125   GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
    126 }
    127 
    128 ProtoStreamObjectSource::ProtoStreamObjectSource(
    129     google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo,
    130     const google::protobuf::Type& type)
    131     : stream_(stream),
    132       typeinfo_(typeinfo),
    133       own_typeinfo_(false),
    134       type_(type),
    135       use_lower_camel_for_enums_(false),
    136       recursion_depth_(0),
    137       max_recursion_depth_(kDefaultMaxRecursionDepth) {
    138   GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
    139 }
    140 
    141 ProtoStreamObjectSource::~ProtoStreamObjectSource() {
    142   if (own_typeinfo_) {
    143     delete typeinfo_;
    144   }
    145 }
    146 
    147 Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name,
    148                                              ObjectWriter* ow) const {
    149   return WriteMessage(type_, name, 0, true, ow);
    150 }
    151 
    152 const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField(
    153     const google::protobuf::Type& type, uint32 tag) const {
    154   // Lookup the new field in the type by tag number.
    155   const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3);
    156   // Verify if the field corresponds to the wire type in tag.
    157   // If there is any discrepancy, mark the field as not found.
    158   if (field != NULL) {
    159     WireFormatLite::WireType expected_type =
    160         WireFormatLite::WireTypeForFieldType(
    161             static_cast<WireFormatLite::FieldType>(field->kind()));
    162     WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag);
    163     if (actual_type != expected_type &&
    164         (!IsPackable(*field) ||
    165          actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
    166       field = NULL;
    167     }
    168   }
    169   return field;
    170 }
    171 
    172 Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
    173                                              StringPiece name,
    174                                              const uint32 end_tag,
    175                                              bool include_start_and_end,
    176                                              ObjectWriter* ow) const {
    177 
    178     const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
    179     if (type_renderer != NULL) {
    180       return (*type_renderer)(this, type, name, ow);
    181     }
    182 
    183   const google::protobuf::Field* field = NULL;
    184   string field_name;
    185   // last_tag set to dummy value that is different from tag.
    186   uint32 tag = stream_->ReadTag(), last_tag = tag + 1;
    187 
    188   if (include_start_and_end) {
    189     ow->StartObject(name);
    190   }
    191   while (tag != end_tag) {
    192     if (tag != last_tag) {  // Update field only if tag is changed.
    193       last_tag = tag;
    194       field = FindAndVerifyField(type, tag);
    195       if (field != NULL) {
    196         field_name = field->json_name();
    197       }
    198     }
    199     if (field == NULL) {
    200       // If we didn't find a field, skip this unknown tag.
    201       // TODO(wpoon): Check return boolean value.
    202       WireFormat::SkipField(stream_, tag, NULL);
    203       tag = stream_->ReadTag();
    204       continue;
    205     }
    206 
    207     if (field->cardinality() ==
    208         google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
    209       bool check_maps = true;
    210 
    211       if (check_maps && IsMap(*field)) {
    212         ow->StartObject(field_name);
    213         ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow));
    214         ow->EndObject();
    215       } else {
    216         ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow));
    217       }
    218     } else {
    219       // Render the field.
    220       RETURN_IF_ERROR(RenderField(field, field_name, ow));
    221       tag = stream_->ReadTag();
    222     }
    223   }
    224   if (include_start_and_end) {
    225     ow->EndObject();
    226   }
    227   return Status::OK;
    228 }
    229 
    230 StatusOr<uint32> ProtoStreamObjectSource::RenderList(
    231     const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
    232     ObjectWriter* ow) const {
    233   uint32 tag_to_return = 0;
    234   ow->StartList(name);
    235   if (IsPackable(*field) &&
    236       list_tag ==
    237           WireFormatLite::MakeTag(field->number(),
    238                                   WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
    239     RETURN_IF_ERROR(RenderPacked(field, ow));
    240     // Since packed fields have a single tag, read another tag from stream to
    241     // return.
    242     tag_to_return = stream_->ReadTag();
    243   } else {
    244     do {
    245       RETURN_IF_ERROR(RenderField(field, "", ow));
    246     } while ((tag_to_return = stream_->ReadTag()) == list_tag);
    247   }
    248   ow->EndList();
    249   return tag_to_return;
    250 }
    251 
    252 StatusOr<uint32> ProtoStreamObjectSource::RenderMap(
    253     const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
    254     ObjectWriter* ow) const {
    255   const google::protobuf::Type* field_type =
    256       typeinfo_->GetTypeByTypeUrl(field->type_url());
    257   uint32 tag_to_return = 0;
    258   do {
    259     // Render map entry message type.
    260     uint32 buffer32;
    261     stream_->ReadVarint32(&buffer32);  // message length
    262     int old_limit = stream_->PushLimit(buffer32);
    263     string map_key;
    264     for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
    265       const google::protobuf::Field* field =
    266           FindAndVerifyField(*field_type, tag);
    267       if (field == NULL) {
    268         WireFormat::SkipField(stream_, tag, NULL);
    269         continue;
    270       }
    271       // Map field numbers are key = 1 and value = 2
    272       if (field->number() == 1) {
    273         map_key = ReadFieldValueAsString(*field);
    274       } else if (field->number() == 2) {
    275         if (map_key.empty()) {
    276           // An absent map key is treated as the default.
    277           const google::protobuf::Field* key_field =
    278               FindFieldByNumber(*field_type, 1);
    279           if (key_field == NULL) {
    280             // The Type info for this map entry is incorrect. It should always
    281             // have a field named "key" and with field number 1.
    282             return Status(util::error::INTERNAL, "Invalid map entry.");
    283           }
    284           ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field));
    285         }
    286         RETURN_IF_ERROR(RenderField(field, map_key, ow));
    287       } else {
    288         // The Type info for this map entry is incorrect. It should contain
    289         // exactly two fields with field number 1 and 2.
    290         return Status(util::error::INTERNAL, "Invalid map entry.");
    291       }
    292     }
    293     stream_->PopLimit(old_limit);
    294   } while ((tag_to_return = stream_->ReadTag()) == list_tag);
    295   return tag_to_return;
    296 }
    297 
    298 Status ProtoStreamObjectSource::RenderPacked(
    299     const google::protobuf::Field* field, ObjectWriter* ow) const {
    300   uint32 length;
    301   stream_->ReadVarint32(&length);
    302   int old_limit = stream_->PushLimit(length);
    303   while (stream_->BytesUntilLimit() > 0) {
    304     RETURN_IF_ERROR(RenderField(field, StringPiece(), ow));
    305   }
    306   stream_->PopLimit(old_limit);
    307   return Status::OK;
    308 }
    309 
    310 Status ProtoStreamObjectSource::RenderTimestamp(
    311     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
    312     StringPiece field_name, ObjectWriter* ow) {
    313   pair<int64, int32> p = os->ReadSecondsAndNanos(type);
    314   int64 seconds = p.first;
    315   int32 nanos = p.second;
    316   if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) {
    317     return Status(
    318         util::error::INTERNAL,
    319         StrCat("Timestamp seconds exceeds limit for field: ", field_name));
    320   }
    321 
    322   if (nanos < 0 || nanos >= kNanosPerSecond) {
    323     return Status(
    324         util::error::INTERNAL,
    325         StrCat("Timestamp nanos exceeds limit for field: ", field_name));
    326   }
    327 
    328   ow->RenderString(field_name,
    329                    ::google::protobuf::internal::FormatTime(seconds, nanos));
    330 
    331   return Status::OK;
    332 }
    333 
    334 Status ProtoStreamObjectSource::RenderDuration(
    335     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
    336     StringPiece field_name, ObjectWriter* ow) {
    337   pair<int64, int32> p = os->ReadSecondsAndNanos(type);
    338   int64 seconds = p.first;
    339   int32 nanos = p.second;
    340   if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) {
    341     return Status(
    342         util::error::INTERNAL,
    343         StrCat("Duration seconds exceeds limit for field: ", field_name));
    344   }
    345 
    346   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
    347     return Status(
    348         util::error::INTERNAL,
    349         StrCat("Duration nanos exceeds limit for field: ", field_name));
    350   }
    351 
    352   string sign = "";
    353   if (seconds < 0) {
    354     if (nanos > 0) {
    355       return Status(util::error::INTERNAL,
    356                     StrCat("Duration nanos is non-negative, but seconds is "
    357                            "negative for field: ",
    358                            field_name));
    359     }
    360     sign = "-";
    361     seconds = -seconds;
    362     nanos = -nanos;
    363   } else if (seconds == 0 && nanos < 0) {
    364     sign = "-";
    365     nanos = -nanos;
    366   }
    367   string formatted_duration = StringPrintf("%s%lld%ss", sign.c_str(), seconds,
    368                                            FormatNanos(nanos).c_str());
    369   ow->RenderString(field_name, formatted_duration);
    370   return Status::OK;
    371 }
    372 
    373 Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os,
    374                                              const google::protobuf::Type& type,
    375                                              StringPiece field_name,
    376                                              ObjectWriter* ow) {
    377   uint32 tag = os->stream_->ReadTag();
    378   uint64 buffer64 = 0;  // default value of Double wrapper value
    379   if (tag != 0) {
    380     os->stream_->ReadLittleEndian64(&buffer64);
    381     os->stream_->ReadTag();
    382   }
    383   ow->RenderDouble(field_name, bit_cast<double>(buffer64));
    384   return Status::OK;
    385 }
    386 
    387 Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os,
    388                                             const google::protobuf::Type& type,
    389                                             StringPiece field_name,
    390                                             ObjectWriter* ow) {
    391   uint32 tag = os->stream_->ReadTag();
    392   uint32 buffer32 = 0;  // default value of Float wrapper value
    393   if (tag != 0) {
    394     os->stream_->ReadLittleEndian32(&buffer32);
    395     os->stream_->ReadTag();
    396   }
    397   ow->RenderFloat(field_name, bit_cast<float>(buffer32));
    398   return Status::OK;
    399 }
    400 
    401 Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os,
    402                                             const google::protobuf::Type& type,
    403                                             StringPiece field_name,
    404                                             ObjectWriter* ow) {
    405   uint32 tag = os->stream_->ReadTag();
    406   uint64 buffer64 = 0;  // default value of Int64 wrapper value
    407   if (tag != 0) {
    408     os->stream_->ReadVarint64(&buffer64);
    409     os->stream_->ReadTag();
    410   }
    411   ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
    412   return Status::OK;
    413 }
    414 
    415 Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os,
    416                                              const google::protobuf::Type& type,
    417                                              StringPiece field_name,
    418                                              ObjectWriter* ow) {
    419   uint32 tag = os->stream_->ReadTag();
    420   uint64 buffer64 = 0;  // default value of UInt64 wrapper value
    421   if (tag != 0) {
    422     os->stream_->ReadVarint64(&buffer64);
    423     os->stream_->ReadTag();
    424   }
    425   ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
    426   return Status::OK;
    427 }
    428 
    429 Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os,
    430                                             const google::protobuf::Type& type,
    431                                             StringPiece field_name,
    432                                             ObjectWriter* ow) {
    433   uint32 tag = os->stream_->ReadTag();
    434   uint32 buffer32 = 0;  // default value of Int32 wrapper value
    435   if (tag != 0) {
    436     os->stream_->ReadVarint32(&buffer32);
    437     os->stream_->ReadTag();
    438   }
    439   ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
    440   return Status::OK;
    441 }
    442 
    443 Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os,
    444                                              const google::protobuf::Type& type,
    445                                              StringPiece field_name,
    446                                              ObjectWriter* ow) {
    447   uint32 tag = os->stream_->ReadTag();
    448   uint32 buffer32 = 0;  // default value of UInt32 wrapper value
    449   if (tag != 0) {
    450     os->stream_->ReadVarint32(&buffer32);
    451     os->stream_->ReadTag();
    452   }
    453   ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
    454   return Status::OK;
    455 }
    456 
    457 Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os,
    458                                            const google::protobuf::Type& type,
    459                                            StringPiece field_name,
    460                                            ObjectWriter* ow) {
    461   uint32 tag = os->stream_->ReadTag();
    462   uint64 buffer64 = 0;  // results in 'false' value as default, which is the
    463                         // default value of Bool wrapper
    464   if (tag != 0) {
    465     os->stream_->ReadVarint64(&buffer64);
    466     os->stream_->ReadTag();
    467   }
    468   ow->RenderBool(field_name, buffer64 != 0);
    469   return Status::OK;
    470 }
    471 
    472 Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os,
    473                                              const google::protobuf::Type& type,
    474                                              StringPiece field_name,
    475                                              ObjectWriter* ow) {
    476   uint32 tag = os->stream_->ReadTag();
    477   uint32 buffer32;
    478   string str;  // default value of empty for String wrapper
    479   if (tag != 0) {
    480     os->stream_->ReadVarint32(&buffer32);  // string size.
    481     os->stream_->ReadString(&str, buffer32);
    482     os->stream_->ReadTag();
    483   }
    484   ow->RenderString(field_name, str);
    485   return Status::OK;
    486 }
    487 
    488 Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os,
    489                                             const google::protobuf::Type& type,
    490                                             StringPiece field_name,
    491                                             ObjectWriter* ow) {
    492   uint32 tag = os->stream_->ReadTag();
    493   uint32 buffer32;
    494   string str;
    495   if (tag != 0) {
    496     os->stream_->ReadVarint32(&buffer32);
    497     os->stream_->ReadString(&str, buffer32);
    498     os->stream_->ReadTag();
    499   }
    500   ow->RenderBytes(field_name, str);
    501   return Status::OK;
    502 }
    503 
    504 Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os,
    505                                              const google::protobuf::Type& type,
    506                                              StringPiece field_name,
    507                                              ObjectWriter* ow) {
    508   const google::protobuf::Field* field = NULL;
    509   uint32 tag = os->stream_->ReadTag();
    510   ow->StartObject(field_name);
    511   while (tag != 0) {
    512     field = os->FindAndVerifyField(type, tag);
    513     // google.protobuf.Struct has only one field that is a map. Hence we use
    514     // RenderMap to render that field.
    515     if (os->IsMap(*field)) {
    516       ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow));
    517     }
    518   }
    519   ow->EndObject();
    520   return Status::OK;
    521 }
    522 
    523 Status ProtoStreamObjectSource::RenderStructValue(
    524     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
    525     StringPiece field_name, ObjectWriter* ow) {
    526   const google::protobuf::Field* field = NULL;
    527   for (uint32 tag = os->stream_->ReadTag(); tag != 0;
    528        tag = os->stream_->ReadTag()) {
    529     field = os->FindAndVerifyField(type, tag);
    530     if (field == NULL) {
    531       WireFormat::SkipField(os->stream_, tag, NULL);
    532       continue;
    533     }
    534     RETURN_IF_ERROR(os->RenderField(field, field_name, ow));
    535   }
    536   return Status::OK;
    537 }
    538 
    539 // TODO(skarvaje): Avoid code duplication of for loops and SkipField logic.
    540 Status ProtoStreamObjectSource::RenderStructListValue(
    541     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
    542     StringPiece field_name, ObjectWriter* ow) {
    543   uint32 tag = os->stream_->ReadTag();
    544 
    545   // Render empty list when we find empty ListValue message.
    546   if (tag == 0) {
    547     ow->StartList(field_name);
    548     ow->EndList();
    549     return Status::OK;
    550   }
    551 
    552   while (tag != 0) {
    553     const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
    554     if (field == NULL) {
    555       WireFormat::SkipField(os->stream_, tag, NULL);
    556       tag = os->stream_->ReadTag();
    557       continue;
    558     }
    559     ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow));
    560   }
    561   return Status::OK;
    562 }
    563 
    564 Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os,
    565                                           const google::protobuf::Type& type,
    566                                           StringPiece field_name,
    567                                           ObjectWriter* ow) {
    568   // An Any is of the form { string type_url = 1; bytes value = 2; }
    569   uint32 tag;
    570   string type_url;
    571   string value;
    572 
    573   // First read out the type_url and value from the proto stream
    574   for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) {
    575     const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
    576     if (field == NULL) {
    577       WireFormat::SkipField(os->stream_, tag, NULL);
    578       continue;
    579     }
    580     // 'type_url' has field number of 1 and 'value' has field number 2
    581     // //google/protobuf/any.proto
    582     if (field->number() == 1) {
    583       // read type_url
    584       uint32 type_url_size;
    585       os->stream_->ReadVarint32(&type_url_size);
    586       os->stream_->ReadString(&type_url, type_url_size);
    587     } else if (field->number() == 2) {
    588       // read value
    589       uint32 value_size;
    590       os->stream_->ReadVarint32(&value_size);
    591       os->stream_->ReadString(&value, value_size);
    592     }
    593   }
    594 
    595   // If there is no value, we don't lookup the type, we just output it (if
    596   // present). If both type and value are empty we output an empty object.
    597   if (value.empty()) {
    598     ow->StartObject(field_name);
    599     if (!type_url.empty()) {
    600       ow->RenderString("@type", type_url);
    601     }
    602     ow->EndObject();
    603     return util::Status::OK;
    604   }
    605 
    606   // If there is a value but no type, we cannot render it, so report an error.
    607   if (type_url.empty()) {
    608     // TODO(sven): Add an external message once those are ready.
    609     return util::Status(util::error::INTERNAL,
    610                         "Invalid Any, the type_url is missing.");
    611   }
    612 
    613   util::StatusOr<const google::protobuf::Type*> resolved_type =
    614       os->typeinfo_->ResolveTypeUrl(type_url);
    615 
    616   if (!resolved_type.ok()) {
    617     // Convert into an internal error, since this means the backend gave us
    618     // an invalid response (missing or invalid type information).
    619     return util::Status(util::error::INTERNAL,
    620                         resolved_type.status().error_message());
    621   }
    622   // nested_type cannot be null at this time.
    623   const google::protobuf::Type* nested_type = resolved_type.ValueOrDie();
    624 
    625   google::protobuf::io::ArrayInputStream zero_copy_stream(value.data(), value.size());
    626   google::protobuf::io::CodedInputStream in_stream(&zero_copy_stream);
    627   // We know the type so we can render it. Recursively parse the nested stream
    628   // using a nested ProtoStreamObjectSource using our nested type information.
    629   ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type);
    630 
    631   // We manually call start and end object here so we can inject the @type.
    632   ow->StartObject(field_name);
    633   ow->RenderString("@type", type_url);
    634   util::Status result =
    635       nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow);
    636   ow->EndObject();
    637   return result;
    638 }
    639 
    640 Status ProtoStreamObjectSource::RenderFieldMask(
    641     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
    642     StringPiece field_name, ObjectWriter* ow) {
    643   string combined;
    644   uint32 buffer32;
    645   uint32 paths_field_tag = 0;
    646   for (uint32 tag = os->stream_->ReadTag(); tag != 0;
    647        tag = os->stream_->ReadTag()) {
    648     if (paths_field_tag == 0) {
    649       const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
    650       if (field != NULL && field->number() == 1 &&
    651           field->name() == "paths") {
    652         paths_field_tag = tag;
    653       }
    654     }
    655     if (paths_field_tag != tag) {
    656       return util::Status(util::error::INTERNAL,
    657                           "Invalid FieldMask, unexpected field.");
    658     }
    659     string str;
    660     os->stream_->ReadVarint32(&buffer32);  // string size.
    661     os->stream_->ReadString(&str, buffer32);
    662     if (!combined.empty()) {
    663       combined.append(",");
    664     }
    665     combined.append(ConvertFieldMaskPath(str, &ToCamelCase));
    666   }
    667   ow->RenderString(field_name, combined);
    668   return Status::OK;
    669 }
    670 
    671 
    672 hash_map<string, ProtoStreamObjectSource::TypeRenderer>*
    673     ProtoStreamObjectSource::renderers_ = NULL;
    674 GOOGLE_PROTOBUF_DECLARE_ONCE(source_renderers_init_);
    675 
    676 void ProtoStreamObjectSource::InitRendererMap() {
    677   renderers_ = new hash_map<string, ProtoStreamObjectSource::TypeRenderer>();
    678   (*renderers_)["google.protobuf.Timestamp"] =
    679       &ProtoStreamObjectSource::RenderTimestamp;
    680   (*renderers_)["google.protobuf.Duration"] =
    681       &ProtoStreamObjectSource::RenderDuration;
    682   (*renderers_)["google.protobuf.DoubleValue"] =
    683       &ProtoStreamObjectSource::RenderDouble;
    684   (*renderers_)["google.protobuf.FloatValue"] =
    685       &ProtoStreamObjectSource::RenderFloat;
    686   (*renderers_)["google.protobuf.Int64Value"] =
    687       &ProtoStreamObjectSource::RenderInt64;
    688   (*renderers_)["google.protobuf.UInt64Value"] =
    689       &ProtoStreamObjectSource::RenderUInt64;
    690   (*renderers_)["google.protobuf.Int32Value"] =
    691       &ProtoStreamObjectSource::RenderInt32;
    692   (*renderers_)["google.protobuf.UInt32Value"] =
    693       &ProtoStreamObjectSource::RenderUInt32;
    694   (*renderers_)["google.protobuf.BoolValue"] =
    695       &ProtoStreamObjectSource::RenderBool;
    696   (*renderers_)["google.protobuf.StringValue"] =
    697       &ProtoStreamObjectSource::RenderString;
    698   (*renderers_)["google.protobuf.BytesValue"] =
    699       &ProtoStreamObjectSource::RenderBytes;
    700   (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
    701   (*renderers_)["google.protobuf.Struct"] =
    702       &ProtoStreamObjectSource::RenderStruct;
    703   (*renderers_)["google.protobuf.Value"] =
    704       &ProtoStreamObjectSource::RenderStructValue;
    705   (*renderers_)["google.protobuf.ListValue"] =
    706       &ProtoStreamObjectSource::RenderStructListValue;
    707   (*renderers_)["google.protobuf.FieldMask"] =
    708       &ProtoStreamObjectSource::RenderFieldMask;
    709   ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
    710 }
    711 
    712 void ProtoStreamObjectSource::DeleteRendererMap() {
    713   delete ProtoStreamObjectSource::renderers_;
    714   renderers_ = NULL;
    715 }
    716 
    717 // static
    718 ProtoStreamObjectSource::TypeRenderer*
    719 ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) {
    720   ::google::protobuf::GoogleOnceInit(&source_renderers_init_, &InitRendererMap);
    721   return FindOrNull(*renderers_, type_url);
    722 }
    723 
    724 Status ProtoStreamObjectSource::RenderField(
    725     const google::protobuf::Field* field, StringPiece field_name,
    726     ObjectWriter* ow) const {
    727   // Short-circuit message types as it tends to call WriteMessage recursively
    728   // and ends up using a lot of stack space. Keep the stack usage of this
    729   // message small in order to preserve stack space and not crash.
    730   if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) {
    731     uint32 buffer32;
    732     stream_->ReadVarint32(&buffer32);  // message length
    733     int old_limit = stream_->PushLimit(buffer32);
    734     // Get the nested message type for this field.
    735     const google::protobuf::Type* type =
    736         typeinfo_->GetTypeByTypeUrl(field->type_url());
    737     if (type == NULL) {
    738       return Status(util::error::INTERNAL,
    739                     StrCat("Invalid configuration. Could not find the type: ",
    740                            field->type_url()));
    741     }
    742 
    743     // Short-circuit any special type rendering to save call-stack space.
    744     const TypeRenderer* type_renderer = FindTypeRenderer(type->name());
    745 
    746     bool use_type_renderer = type_renderer != NULL;
    747 
    748     if (use_type_renderer) {
    749       RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow));
    750     } else {
    751       RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name));
    752       RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
    753       --recursion_depth_;
    754     }
    755     if (!stream_->ConsumedEntireMessage()) {
    756       return Status(util::error::INVALID_ARGUMENT,
    757                     "Nested protocol message not parsed in its entirety.");
    758     }
    759     stream_->PopLimit(old_limit);
    760   } else {
    761     // Render all other non-message types.
    762     return RenderNonMessageField(field, field_name, ow);
    763   }
    764   return Status::OK;
    765 }
    766 
    767 Status ProtoStreamObjectSource::RenderNonMessageField(
    768     const google::protobuf::Field* field, StringPiece field_name,
    769     ObjectWriter* ow) const {
    770   // Temporary buffers of different types.
    771   uint32 buffer32;
    772   uint64 buffer64;
    773   string strbuffer;
    774   switch (field->kind()) {
    775     case google::protobuf::Field_Kind_TYPE_BOOL: {
    776       stream_->ReadVarint64(&buffer64);
    777       ow->RenderBool(field_name, buffer64 != 0);
    778       break;
    779     }
    780     case google::protobuf::Field_Kind_TYPE_INT32: {
    781       stream_->ReadVarint32(&buffer32);
    782       ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
    783       break;
    784     }
    785     case google::protobuf::Field_Kind_TYPE_INT64: {
    786       stream_->ReadVarint64(&buffer64);
    787       ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
    788       break;
    789     }
    790     case google::protobuf::Field_Kind_TYPE_UINT32: {
    791       stream_->ReadVarint32(&buffer32);
    792       ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
    793       break;
    794     }
    795     case google::protobuf::Field_Kind_TYPE_UINT64: {
    796       stream_->ReadVarint64(&buffer64);
    797       ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
    798       break;
    799     }
    800     case google::protobuf::Field_Kind_TYPE_SINT32: {
    801       stream_->ReadVarint32(&buffer32);
    802       ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32));
    803       break;
    804     }
    805     case google::protobuf::Field_Kind_TYPE_SINT64: {
    806       stream_->ReadVarint64(&buffer64);
    807       ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64));
    808       break;
    809     }
    810     case google::protobuf::Field_Kind_TYPE_SFIXED32: {
    811       stream_->ReadLittleEndian32(&buffer32);
    812       ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
    813       break;
    814     }
    815     case google::protobuf::Field_Kind_TYPE_SFIXED64: {
    816       stream_->ReadLittleEndian64(&buffer64);
    817       ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
    818       break;
    819     }
    820     case google::protobuf::Field_Kind_TYPE_FIXED32: {
    821       stream_->ReadLittleEndian32(&buffer32);
    822       ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
    823       break;
    824     }
    825     case google::protobuf::Field_Kind_TYPE_FIXED64: {
    826       stream_->ReadLittleEndian64(&buffer64);
    827       ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
    828       break;
    829     }
    830     case google::protobuf::Field_Kind_TYPE_FLOAT: {
    831       stream_->ReadLittleEndian32(&buffer32);
    832       ow->RenderFloat(field_name, bit_cast<float>(buffer32));
    833       break;
    834     }
    835     case google::protobuf::Field_Kind_TYPE_DOUBLE: {
    836       stream_->ReadLittleEndian64(&buffer64);
    837       ow->RenderDouble(field_name, bit_cast<double>(buffer64));
    838       break;
    839     }
    840     case google::protobuf::Field_Kind_TYPE_ENUM: {
    841       stream_->ReadVarint32(&buffer32);
    842 
    843       // If the field represents an explicit NULL value, render null.
    844       if (field->type_url() == kStructNullValueTypeUrl) {
    845         ow->RenderNull(field_name);
    846         break;
    847       }
    848 
    849       // Get the nested enum type for this field.
    850       // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
    851       // up.
    852       const google::protobuf::Enum* en =
    853           typeinfo_->GetEnumByTypeUrl(field->type_url());
    854       // Lookup the name of the enum, and render that. Skips unknown enums.
    855       if (en != NULL) {
    856         const google::protobuf::EnumValue* enum_value =
    857             FindEnumValueByNumber(*en, buffer32);
    858         if (enum_value != NULL) {
    859           if (use_lower_camel_for_enums_)
    860             ow->RenderString(field_name, ToCamelCase(enum_value->name()));
    861           else
    862             ow->RenderString(field_name, enum_value->name());
    863         }
    864       } else {
    865         GOOGLE_LOG(INFO) << "Unknown enum skipped: " << field->type_url();
    866       }
    867       break;
    868     }
    869     case google::protobuf::Field_Kind_TYPE_STRING: {
    870       stream_->ReadVarint32(&buffer32);  // string size.
    871       stream_->ReadString(&strbuffer, buffer32);
    872       ow->RenderString(field_name, strbuffer);
    873       break;
    874     }
    875     case google::protobuf::Field_Kind_TYPE_BYTES: {
    876       stream_->ReadVarint32(&buffer32);  // bytes size.
    877       stream_->ReadString(&strbuffer, buffer32);
    878       ow->RenderBytes(field_name, strbuffer);
    879       break;
    880     }
    881     default:
    882       break;
    883   }
    884   return Status::OK;
    885 }
    886 
    887 // TODO(skarvaje): Fix this to avoid code duplication.
    888 const string ProtoStreamObjectSource::ReadFieldValueAsString(
    889     const google::protobuf::Field& field) const {
    890   string result;
    891   switch (field.kind()) {
    892     case google::protobuf::Field_Kind_TYPE_BOOL: {
    893       uint64 buffer64;
    894       stream_->ReadVarint64(&buffer64);
    895       result = buffer64 != 0 ? "true" : "false";
    896       break;
    897     }
    898     case google::protobuf::Field_Kind_TYPE_INT32: {
    899       uint32 buffer32;
    900       stream_->ReadVarint32(&buffer32);
    901       result = SimpleItoa(bit_cast<int32>(buffer32));
    902       break;
    903     }
    904     case google::protobuf::Field_Kind_TYPE_INT64: {
    905       uint64 buffer64;
    906       stream_->ReadVarint64(&buffer64);
    907       result = SimpleItoa(bit_cast<int64>(buffer64));
    908       break;
    909     }
    910     case google::protobuf::Field_Kind_TYPE_UINT32: {
    911       uint32 buffer32;
    912       stream_->ReadVarint32(&buffer32);
    913       result = SimpleItoa(bit_cast<uint32>(buffer32));
    914       break;
    915     }
    916     case google::protobuf::Field_Kind_TYPE_UINT64: {
    917       uint64 buffer64;
    918       stream_->ReadVarint64(&buffer64);
    919       result = SimpleItoa(bit_cast<uint64>(buffer64));
    920       break;
    921     }
    922     case google::protobuf::Field_Kind_TYPE_SINT32: {
    923       uint32 buffer32;
    924       stream_->ReadVarint32(&buffer32);
    925       result = SimpleItoa(WireFormatLite::ZigZagDecode32(buffer32));
    926       break;
    927     }
    928     case google::protobuf::Field_Kind_TYPE_SINT64: {
    929       uint64 buffer64;
    930       stream_->ReadVarint64(&buffer64);
    931       result = SimpleItoa(WireFormatLite::ZigZagDecode64(buffer64));
    932       break;
    933     }
    934     case google::protobuf::Field_Kind_TYPE_SFIXED32: {
    935       uint32 buffer32;
    936       stream_->ReadLittleEndian32(&buffer32);
    937       result = SimpleItoa(bit_cast<int32>(buffer32));
    938       break;
    939     }
    940     case google::protobuf::Field_Kind_TYPE_SFIXED64: {
    941       uint64 buffer64;
    942       stream_->ReadLittleEndian64(&buffer64);
    943       result = SimpleItoa(bit_cast<int64>(buffer64));
    944       break;
    945     }
    946     case google::protobuf::Field_Kind_TYPE_FIXED32: {
    947       uint32 buffer32;
    948       stream_->ReadLittleEndian32(&buffer32);
    949       result = SimpleItoa(bit_cast<uint32>(buffer32));
    950       break;
    951     }
    952     case google::protobuf::Field_Kind_TYPE_FIXED64: {
    953       uint64 buffer64;
    954       stream_->ReadLittleEndian64(&buffer64);
    955       result = SimpleItoa(bit_cast<uint64>(buffer64));
    956       break;
    957     }
    958     case google::protobuf::Field_Kind_TYPE_FLOAT: {
    959       uint32 buffer32;
    960       stream_->ReadLittleEndian32(&buffer32);
    961       result = SimpleFtoa(bit_cast<float>(buffer32));
    962       break;
    963     }
    964     case google::protobuf::Field_Kind_TYPE_DOUBLE: {
    965       uint64 buffer64;
    966       stream_->ReadLittleEndian64(&buffer64);
    967       result = SimpleDtoa(bit_cast<double>(buffer64));
    968       break;
    969     }
    970     case google::protobuf::Field_Kind_TYPE_ENUM: {
    971       uint32 buffer32;
    972       stream_->ReadVarint32(&buffer32);
    973       // Get the nested enum type for this field.
    974       // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
    975       // up.
    976       const google::protobuf::Enum* en =
    977           typeinfo_->GetEnumByTypeUrl(field.type_url());
    978       // Lookup the name of the enum, and render that. Skips unknown enums.
    979       if (en != NULL) {
    980         const google::protobuf::EnumValue* enum_value =
    981             FindEnumValueByNumber(*en, buffer32);
    982         if (enum_value != NULL) {
    983           result = enum_value->name();
    984         }
    985       }
    986       break;
    987     }
    988     case google::protobuf::Field_Kind_TYPE_STRING: {
    989       uint32 buffer32;
    990       stream_->ReadVarint32(&buffer32);  // string size.
    991       stream_->ReadString(&result, buffer32);
    992       break;
    993     }
    994     case google::protobuf::Field_Kind_TYPE_BYTES: {
    995       uint32 buffer32;
    996       stream_->ReadVarint32(&buffer32);  // bytes size.
    997       stream_->ReadString(&result, buffer32);
    998       break;
    999     }
   1000     default:
   1001       break;
   1002   }
   1003   return result;
   1004 }
   1005 
   1006 // Field is a map if it is a repeated message and it has an option "map_type".
   1007 // TODO(skarvaje): Consider pre-computing the IsMap() into Field directly.
   1008 bool ProtoStreamObjectSource::IsMap(
   1009     const google::protobuf::Field& field) const {
   1010   const google::protobuf::Type* field_type =
   1011       typeinfo_->GetTypeByTypeUrl(field.type_url());
   1012 
   1013   // TODO(xiaofeng): Unify option names.
   1014   return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE &&
   1015          (GetBoolOptionOrDefault(field_type->options(),
   1016                                  "google.protobuf.MessageOptions.map_entry", false) ||
   1017           GetBoolOptionOrDefault(field_type->options(), "map_entry", false));
   1018 }
   1019 
   1020 std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
   1021     const google::protobuf::Type& type) const {
   1022   uint64 seconds = 0;
   1023   uint32 nanos = 0;
   1024   uint32 tag = 0;
   1025   int64 signed_seconds = 0;
   1026   int32 signed_nanos = 0;
   1027 
   1028   for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
   1029     const google::protobuf::Field* field = FindAndVerifyField(type, tag);
   1030     if (field == NULL) {
   1031       WireFormat::SkipField(stream_, tag, NULL);
   1032       continue;
   1033     }
   1034     // 'seconds' has field number of 1 and 'nanos' has field number 2
   1035     // //google/protobuf/timestamp.proto & duration.proto
   1036     if (field->number() == 1) {
   1037       // read seconds
   1038       stream_->ReadVarint64(&seconds);
   1039       signed_seconds = bit_cast<int64>(seconds);
   1040     } else if (field->number() == 2) {
   1041       // read nanos
   1042       stream_->ReadVarint32(&nanos);
   1043       signed_nanos = bit_cast<int32>(nanos);
   1044     }
   1045   }
   1046   return std::pair<int64, int32>(signed_seconds, signed_nanos);
   1047 }
   1048 
   1049 Status ProtoStreamObjectSource::IncrementRecursionDepth(
   1050     StringPiece type_name, StringPiece field_name) const {
   1051   if (++recursion_depth_ > max_recursion_depth_) {
   1052     return Status(
   1053         util::error::INVALID_ARGUMENT,
   1054         StrCat("Message too deep. Max recursion depth reached for type '",
   1055                type_name, "', field '", field_name, "'"));
   1056   }
   1057   return Status::OK;
   1058 }
   1059 
   1060 namespace {
   1061 // TODO(skarvaje): Speed this up by not doing a linear scan.
   1062 const google::protobuf::Field* FindFieldByNumber(
   1063     const google::protobuf::Type& type, int number) {
   1064   for (int i = 0; i < type.fields_size(); ++i) {
   1065     if (type.fields(i).number() == number) {
   1066       return &type.fields(i);
   1067     }
   1068   }
   1069   return NULL;
   1070 }
   1071 
   1072 // TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable()
   1073 // using tech Field.
   1074 bool IsPackable(const google::protobuf::Field& field) {
   1075   return field.cardinality() ==
   1076              google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
   1077          google::protobuf::FieldDescriptor::IsTypePackable(
   1078              static_cast<google::protobuf::FieldDescriptor::Type>(field.kind()));
   1079 }
   1080 
   1081 // TODO(skarvaje): Speed this up by not doing a linear scan.
   1082 const google::protobuf::EnumValue* FindEnumValueByNumber(
   1083     const google::protobuf::Enum& tech_enum, int number) {
   1084   for (int i = 0; i < tech_enum.enumvalue_size(); ++i) {
   1085     const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i);
   1086     if (ev.number() == number) {
   1087       return &ev;
   1088     }
   1089   }
   1090   return NULL;
   1091 }
   1092 
   1093 // TODO(skarvaje): Look into optimizing this by not doing computation on
   1094 // double.
   1095 const string FormatNanos(uint32 nanos) {
   1096   const char* format =
   1097       (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f";
   1098   string formatted =
   1099       StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond);
   1100   // remove the leading 0 before decimal.
   1101   return formatted.substr(1);
   1102 }
   1103 }  // namespace
   1104 
   1105 }  // namespace converter
   1106 }  // namespace util
   1107 }  // namespace protobuf
   1108 }  // namespace google
   1109