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_objectwriter.h>
     32 
     33 #include <functional>
     34 #include <stack>
     35 
     36 #include <google/protobuf/stubs/once.h>
     37 #include <google/protobuf/stubs/time.h>
     38 #include <google/protobuf/wire_format_lite.h>
     39 #include <google/protobuf/util/internal/field_mask_utility.h>
     40 #include <google/protobuf/util/internal/object_location_tracker.h>
     41 #include <google/protobuf/util/internal/constants.h>
     42 #include <google/protobuf/util/internal/utility.h>
     43 #include <google/protobuf/stubs/strutil.h>
     44 #include <google/protobuf/stubs/map_util.h>
     45 #include <google/protobuf/stubs/statusor.h>
     46 
     47 
     48 namespace google {
     49 namespace protobuf {
     50 namespace util {
     51 namespace converter {
     52 
     53 using google::protobuf::internal::WireFormatLite;
     54 using util::error::INVALID_ARGUMENT;
     55 using util::Status;
     56 using util::StatusOr;
     57 
     58 
     59 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
     60     TypeResolver* type_resolver, const google::protobuf::Type& type,
     61     strings::ByteSink* output, ErrorListener* listener,
     62     const ProtoStreamObjectWriter::Options& options)
     63     : ProtoWriter(type_resolver, type, output, listener),
     64       master_type_(type),
     65       current_(NULL),
     66       options_(options) {}
     67 
     68 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
     69     const TypeInfo* typeinfo, const google::protobuf::Type& type,
     70     strings::ByteSink* output, ErrorListener* listener)
     71     : ProtoWriter(typeinfo, type, output, listener),
     72       master_type_(type),
     73       current_(NULL),
     74       options_(ProtoStreamObjectWriter::Options::Defaults()) {}
     75 
     76 ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
     77   if (current_ == NULL) return;
     78   // Cleanup explicitly in order to avoid destructor stack overflow when input
     79   // is deeply nested.
     80   // Cast to BaseElement to avoid doing additional checks (like missing fields)
     81   // during pop().
     82   google::protobuf::scoped_ptr<BaseElement> element(
     83       static_cast<BaseElement*>(current_.get())->pop<BaseElement>());
     84   while (element != NULL) {
     85     element.reset(element->pop<BaseElement>());
     86   }
     87 }
     88 
     89 namespace {
     90 // Utility method to split a string representation of Timestamp or Duration and
     91 // return the parts.
     92 void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds,
     93                           StringPiece* nanos) {
     94   size_t idx = input.rfind('.');
     95   if (idx != string::npos) {
     96     *seconds = input.substr(0, idx);
     97     *nanos = input.substr(idx + 1);
     98   } else {
     99     *seconds = input;
    100     *nanos = StringPiece();
    101   }
    102 }
    103 
    104 Status GetNanosFromStringPiece(StringPiece s_nanos,
    105                                const char* parse_failure_message,
    106                                const char* exceeded_limit_message,
    107                                int32* nanos) {
    108   *nanos = 0;
    109 
    110   // Count the number of leading 0s and consume them.
    111   int num_leading_zeros = 0;
    112   while (s_nanos.Consume("0")) {
    113     num_leading_zeros++;
    114   }
    115   int32 i_nanos = 0;
    116   // 's_nanos' contains fractional seconds -- i.e. 'nanos' is equal to
    117   // "0." + s_nanos.ToString() seconds. An int32 is used for the
    118   // conversion to 'nanos', rather than a double, so that there is no
    119   // loss of precision.
    120   if (!s_nanos.empty() && !safe_strto32(s_nanos.ToString(), &i_nanos)) {
    121     return Status(INVALID_ARGUMENT, parse_failure_message);
    122   }
    123   if (i_nanos > kNanosPerSecond || i_nanos < 0) {
    124     return Status(INVALID_ARGUMENT, exceeded_limit_message);
    125   }
    126   // s_nanos should only have digits. No whitespace.
    127   if (s_nanos.find_first_not_of("0123456789") != StringPiece::npos) {
    128     return Status(INVALID_ARGUMENT, parse_failure_message);
    129   }
    130 
    131   if (i_nanos > 0) {
    132     // 'scale' is the number of digits to the right of the decimal
    133     // point in "0." + s_nanos.ToString()
    134     int32 scale = num_leading_zeros + s_nanos.size();
    135     // 'conversion' converts i_nanos into nanoseconds.
    136     // conversion = kNanosPerSecond / static_cast<int32>(std::pow(10, scale))
    137     // For efficiency, we precompute the conversion factor.
    138     int32 conversion = 0;
    139     switch (scale) {
    140       case 1:
    141         conversion = 100000000;
    142         break;
    143       case 2:
    144         conversion = 10000000;
    145         break;
    146       case 3:
    147         conversion = 1000000;
    148         break;
    149       case 4:
    150         conversion = 100000;
    151         break;
    152       case 5:
    153         conversion = 10000;
    154         break;
    155       case 6:
    156         conversion = 1000;
    157         break;
    158       case 7:
    159         conversion = 100;
    160         break;
    161       case 8:
    162         conversion = 10;
    163         break;
    164       case 9:
    165         conversion = 1;
    166         break;
    167       default:
    168         return Status(INVALID_ARGUMENT, exceeded_limit_message);
    169     }
    170     *nanos = i_nanos * conversion;
    171   }
    172 
    173   return Status::OK;
    174 }
    175 
    176 }  // namespace
    177 
    178 ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent)
    179     : parent_(parent),
    180       ow_(),
    181       invalid_(false),
    182       data_(),
    183       output_(&data_),
    184       depth_(0),
    185       is_well_known_type_(false),
    186       well_known_type_render_(NULL) {}
    187 
    188 ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {}
    189 
    190 void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) {
    191   ++depth_;
    192   // If an object writer is absent, that means we have not called StartAny()
    193   // before reaching here. This is an invalid state. StartAny() gets called
    194   // whenever we see an "@type" being rendered (see AnyWriter::RenderDataPiece).
    195   if (ow_ == NULL) {
    196     // Make sure we are not already in an invalid state. This avoids making
    197     // multiple unnecessary InvalidValue calls.
    198     if (!invalid_) {
    199       parent_->InvalidValue("Any",
    200                             StrCat("Missing or invalid @type for any field in ",
    201                                    parent_->master_type_.name()));
    202       invalid_ = true;
    203     }
    204   } else if (is_well_known_type_ && depth_ == 1) {
    205     // For well-known types, the only other field besides "@type" should be a
    206     // "value" field.
    207     if (name != "value" && !invalid_) {
    208       parent_->InvalidValue("Any",
    209                             "Expect a \"value\" field for well-known types.");
    210       invalid_ = true;
    211     }
    212     ow_->StartObject("");
    213   } else {
    214     // Forward the call to the child writer if:
    215     //   1. the type is not a well-known type.
    216     //   2. or, we are in a nested Any, Struct, or Value object.
    217     ow_->StartObject(name);
    218   }
    219 }
    220 
    221 bool ProtoStreamObjectWriter::AnyWriter::EndObject() {
    222   --depth_;
    223   // As long as depth_ >= 0, we know we haven't reached the end of Any.
    224   // Propagate these EndObject() calls to the contained ow_. For regular
    225   // message types, we propagate the end of Any as well.
    226   if (ow_ != NULL && (depth_ >= 0 || !is_well_known_type_)) {
    227     ow_->EndObject();
    228   }
    229   // A negative depth_ implies that we have reached the end of Any
    230   // object. Now we write out its contents.
    231   if (depth_ < 0) {
    232     WriteAny();
    233     return false;
    234   }
    235   return true;
    236 }
    237 
    238 void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) {
    239   ++depth_;
    240   // We expect ow_ to be present as this call only makes sense inside an Any.
    241   if (ow_ == NULL) {
    242     if (!invalid_) {
    243       parent_->InvalidValue("Any",
    244                             StrCat("Missing or invalid @type for any field in ",
    245                                    parent_->master_type_.name()));
    246       invalid_ = true;
    247     }
    248   } else if (is_well_known_type_ && depth_ == 1) {
    249     if (name != "value" && !invalid_) {
    250       parent_->InvalidValue("Any",
    251                             "Expect a \"value\" field for well-known types.");
    252       invalid_ = true;
    253     }
    254     ow_->StartList("");
    255   } else {
    256     ow_->StartList(name);
    257   }
    258 }
    259 
    260 void ProtoStreamObjectWriter::AnyWriter::EndList() {
    261   --depth_;
    262   if (depth_ < 0) {
    263     GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible";
    264     depth_ = 0;
    265   }
    266   // We don't write an error on the close, only on the open
    267   if (ow_ != NULL) {
    268     ow_->EndList();
    269   }
    270 }
    271 
    272 void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece(
    273     StringPiece name, const DataPiece& value) {
    274   // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type"
    275   // should go to the contained ow_ as they indicate nested Anys.
    276   if (depth_ == 0 && ow_ == NULL && name == "@type") {
    277     StartAny(value);
    278   } else if (ow_ == NULL) {
    279     if (!invalid_) {
    280       parent_->InvalidValue("Any",
    281                             StrCat("Missing or invalid @type for any field in ",
    282                                    parent_->master_type_.name()));
    283       invalid_ = true;
    284     }
    285   } else if (depth_ == 0 && is_well_known_type_) {
    286     if (name != "value" && !invalid_) {
    287       parent_->InvalidValue("Any",
    288                             "Expect a \"value\" field for well-known types.");
    289       invalid_ = true;
    290     }
    291     if (well_known_type_render_ == NULL) {
    292       // Only Any and Struct don't have a special type render but both of
    293       // them expect a JSON object (i.e., a StartObject() call).
    294       if (!invalid_) {
    295         parent_->InvalidValue("Any", "Expect a JSON object.");
    296         invalid_ = true;
    297       }
    298     } else {
    299       ow_->ProtoWriter::StartObject("");
    300       Status status = (*well_known_type_render_)(ow_.get(), value);
    301       if (!status.ok()) ow_->InvalidValue("Any", status.error_message());
    302       ow_->ProtoWriter::EndObject();
    303     }
    304   } else {
    305     ow_->RenderDataPiece(name, value);
    306   }
    307 }
    308 
    309 void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) {
    310   // Figure out the type url. This is a copy-paste from WriteString but we also
    311   // need the value, so we can't just call through to that.
    312   if (value.type() == DataPiece::TYPE_STRING) {
    313     type_url_ = value.str().ToString();
    314   } else {
    315     StatusOr<string> s = value.ToString();
    316     if (!s.ok()) {
    317       parent_->InvalidValue("String", s.status().error_message());
    318       invalid_ = true;
    319       return;
    320     }
    321     type_url_ = s.ValueOrDie();
    322   }
    323   // Resolve the type url, and report an error if we failed to resolve it.
    324   StatusOr<const google::protobuf::Type*> resolved_type =
    325       parent_->typeinfo()->ResolveTypeUrl(type_url_);
    326   if (!resolved_type.ok()) {
    327     parent_->InvalidValue("Any", resolved_type.status().error_message());
    328     invalid_ = true;
    329     return;
    330   }
    331   // At this point, type is never null.
    332   const google::protobuf::Type* type = resolved_type.ValueOrDie();
    333 
    334   well_known_type_render_ = FindTypeRenderer(type_url_);
    335   if (well_known_type_render_ != NULL ||
    336       // Explicitly list Any and Struct here because they don't have a
    337       // custom renderer.
    338       type->name() == kAnyType || type->name() == kStructType) {
    339     is_well_known_type_ = true;
    340   }
    341 
    342   // Create our object writer and initialize it with the first StartObject
    343   // call.
    344   ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_,
    345                                         parent_->listener()));
    346 
    347   // Don't call StartObject() for well-known types yet. Depending on the
    348   // type of actual data, we may not need to call StartObject(). For
    349   // example:
    350   // {
    351   //   "@type": "type.googleapis.com/google.protobuf.Value",
    352   //   "value": [1, 2, 3],
    353   // }
    354   // With the above JSON representation, we will only call StartList() on the
    355   // contained ow_.
    356   if (!is_well_known_type_) {
    357     ow_->StartObject("");
    358   }
    359 }
    360 
    361 void ProtoStreamObjectWriter::AnyWriter::WriteAny() {
    362   if (ow_ == NULL) {
    363     // If we had no object writer, we never got any content, so just return
    364     // immediately, which is equivalent to writing an empty Any.
    365     return;
    366   }
    367   // Render the type_url and value fields directly to the stream.
    368   // type_url has tag 1 and value has tag 2.
    369   WireFormatLite::WriteString(1, type_url_, parent_->stream());
    370   if (!data_.empty()) {
    371     WireFormatLite::WriteBytes(2, data_, parent_->stream());
    372   }
    373 }
    374 
    375 ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing,
    376                                     ItemType item_type, bool is_placeholder,
    377                                     bool is_list)
    378     : BaseElement(NULL),
    379       ow_(enclosing),
    380       any_(),
    381       item_type_(item_type),
    382       is_placeholder_(is_placeholder),
    383       is_list_(is_list) {
    384   if (item_type_ == ANY) {
    385     any_.reset(new AnyWriter(ow_));
    386   }
    387 }
    388 
    389 ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent,
    390                                     ItemType item_type, bool is_placeholder,
    391                                     bool is_list)
    392     : BaseElement(parent),
    393       ow_(this->parent()->ow_),
    394       any_(),
    395       item_type_(item_type),
    396       is_placeholder_(is_placeholder),
    397       is_list_(is_list) {
    398   if (item_type == ANY) {
    399     any_.reset(new AnyWriter(ow_));
    400   }
    401 }
    402 
    403 bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent(
    404     StringPiece map_key) {
    405   return InsertIfNotPresent(&map_keys_, map_key.ToString());
    406 }
    407 
    408 ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
    409     StringPiece name) {
    410   if (invalid_depth() > 0) {
    411     IncrementInvalidDepth();
    412     return this;
    413   }
    414 
    415   // Starting the root message. Create the root Item and return.
    416   // ANY message type does not need special handling, just set the ItemType
    417   // to ANY.
    418   if (current_ == NULL) {
    419     ProtoWriter::StartObject(name);
    420     current_.reset(new Item(
    421         this, master_type_.name() == kAnyType ? Item::ANY : Item::MESSAGE,
    422         false, false));
    423 
    424     // If master type is a special type that needs extra values to be written to
    425     // stream, we write those values.
    426     if (master_type_.name() == kStructType) {
    427       // Struct has a map<string, Value> field called "fields".
    428       // https://github.com/google/protobuf/blob/master/src/google/protobuf/struct.proto
    429       // "fields": [
    430       Push("fields", Item::MAP, true, true);
    431       return this;
    432     }
    433 
    434     if (master_type_.name() == kStructValueType) {
    435       // We got a StartObject call with google.protobuf.Value field. The only
    436       // object within that type is a struct type. So start a struct.
    437       //
    438       // The struct field in Value type is named "struct_value"
    439       // https://github.com/google/protobuf/blob/master/src/google/protobuf/struct.proto
    440       // Also start the map field "fields" within the struct.
    441       // "struct_value": {
    442       //   "fields": [
    443       Push("struct_value", Item::MESSAGE, true, false);
    444       Push("fields", Item::MAP, true, true);
    445       return this;
    446     }
    447 
    448     if (master_type_.name() == kStructListValueType) {
    449       InvalidValue(kStructListValueType,
    450                    "Cannot start root message with ListValue.");
    451     }
    452 
    453     return this;
    454   }
    455 
    456   // Send all ANY events to AnyWriter.
    457   if (current_->IsAny()) {
    458     current_->any()->StartObject(name);
    459     return this;
    460   }
    461 
    462   // If we are within a map, we render name as keys and send StartObject to the
    463   // value field.
    464   if (current_->IsMap()) {
    465     if (!ValidMapKey(name)) {
    466       IncrementInvalidDepth();
    467       return this;
    468     }
    469 
    470     // Map is a repeated field of message type with a "key" and a "value" field.
    471     // https://developers.google.com/protocol-buffers/docs/proto3?hl=en#maps
    472     // message MapFieldEntry {
    473     //   key_type key = 1;
    474     //   value_type value = 2;
    475     // }
    476     //
    477     // repeated MapFieldEntry map_field = N;
    478     //
    479     // That means, we render the following element within a list (hence no
    480     // name):
    481     // { "key": "<name>", "value": {
    482     Push("", Item::MESSAGE, false, false);
    483     ProtoWriter::RenderDataPiece("key",
    484                                  DataPiece(name, use_strict_base64_decoding()));
    485     Push("value", Item::MESSAGE, true, false);
    486 
    487     // Make sure we are valid so far after starting map fields.
    488     if (invalid_depth() > 0) return this;
    489 
    490     // If top of stack is g.p.Struct type, start the struct the map field within
    491     // it.
    492     if (element() != NULL && IsStruct(*element()->parent_field())) {
    493       // Render "fields": [
    494       Push("fields", Item::MAP, true, true);
    495       return this;
    496     }
    497 
    498     // If top of stack is g.p.Value type, start the Struct within it.
    499     if (element() != NULL && IsStructValue(*element()->parent_field())) {
    500       // Render
    501       // "struct_value": {
    502       //   "fields": [
    503       Push("struct_value", Item::MESSAGE, true, false);
    504       Push("fields", Item::MAP, true, true);
    505     }
    506     return this;
    507   }
    508 
    509   const google::protobuf::Field* field = BeginNamed(name, false);
    510   if (field == NULL) return this;
    511 
    512   if (IsStruct(*field)) {
    513     // Start a struct object.
    514     // Render
    515     // "<name>": {
    516     //   "fields": {
    517     Push(name, Item::MESSAGE, false, false);
    518     Push("fields", Item::MAP, true, true);
    519     return this;
    520   }
    521 
    522   if (IsStructValue(*field)) {
    523     // We got a StartObject call with google.protobuf.Value field.  The only
    524     // object within that type is a struct type. So start a struct.
    525     // Render
    526     // "<name>": {
    527     //   "struct_value": {
    528     //     "fields": {
    529     Push(name, Item::MESSAGE, false, false);
    530     Push("struct_value", Item::MESSAGE, true, false);
    531     Push("fields", Item::MAP, true, true);
    532     return this;
    533   }
    534 
    535   if (IsMap(*field)) {
    536     // Begin a map. A map is triggered by a StartObject() call if the current
    537     // field has a map type.
    538     // A map type is always repeated, hence set is_list to true.
    539     // Render
    540     // "<name>": [
    541     Push(name, Item::MAP, false, true);
    542     return this;
    543   }
    544 
    545   // A regular message type. Pass it directly to ProtoWriter.
    546   // Render
    547   // "<name>": {
    548   Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false);
    549   return this;
    550 }
    551 
    552 ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() {
    553   if (invalid_depth() > 0) {
    554     DecrementInvalidDepth();
    555     return this;
    556   }
    557 
    558   if (current_ == NULL) return this;
    559 
    560   if (current_->IsAny()) {
    561     if (current_->any()->EndObject()) return this;
    562   }
    563 
    564   Pop();
    565 
    566   return this;
    567 }
    568 
    569 ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) {
    570   if (invalid_depth() > 0) {
    571     IncrementInvalidDepth();
    572     return this;
    573   }
    574 
    575   // Since we cannot have a top-level repeated item in protobuf, the only way
    576   // this is valid is if we start a special type google.protobuf.ListValue or
    577   // google.protobuf.Value.
    578   if (current_ == NULL) {
    579     if (!name.empty()) {
    580       InvalidName(name, "Root element should not be named.");
    581       IncrementInvalidDepth();
    582       return this;
    583     }
    584 
    585     // If master type is a special type that needs extra values to be written to
    586     // stream, we write those values.
    587     if (master_type_.name() == kStructValueType) {
    588       // We got a StartList with google.protobuf.Value master type. This means
    589       // we have to start the "list_value" within google.protobuf.Value.
    590       //
    591       // See
    592       // https://github.com/google/protobuf/blob/master/src/google/protobuf/struct.proto
    593       //
    594       // Render
    595       // "<name>": {
    596       //   "list_value": {
    597       //     "values": [  // Start this list.
    598       ProtoWriter::StartObject(name);
    599       current_.reset(new Item(this, Item::MESSAGE, false, false));
    600       Push("list_value", Item::MESSAGE, true, false);
    601       Push("values", Item::MESSAGE, true, true);
    602       return this;
    603     }
    604 
    605     if (master_type_.name() == kStructListValueType) {
    606       // We got a StartList with google.protobuf.ListValue master type. This
    607       // means we have to start the "values" within google.protobuf.ListValue.
    608       //
    609       // Render
    610       // "<name>": {
    611       //   "values": [  // Start this list.
    612       ProtoWriter::StartObject(name);
    613       current_.reset(new Item(this, Item::MESSAGE, false, false));
    614       Push("values", Item::MESSAGE, true, true);
    615       return this;
    616     }
    617 
    618     // Send the event to ProtoWriter so proper errors can be reported.
    619     //
    620     // Render a regular list:
    621     // "<name>": [
    622     ProtoWriter::StartList(name);
    623     current_.reset(new Item(this, Item::MESSAGE, false, true));
    624     return this;
    625   }
    626 
    627   if (current_->IsAny()) {
    628     current_->any()->StartList(name);
    629     return this;
    630   }
    631 
    632   // If the top of stack is a map, we are starting a list value within a map.
    633   // Since map does not allow repeated values, this can only happen when the map
    634   // value is of a special type that renders a list in JSON.  These can be one
    635   // of 3 cases:
    636   // i. We are rendering a list value within google.protobuf.Struct
    637   // ii. We are rendering a list value within google.protobuf.Value
    638   // iii. We are rendering a list value with type google.protobuf.ListValue.
    639   if (current_->IsMap()) {
    640     if (!ValidMapKey(name)) {
    641       IncrementInvalidDepth();
    642       return this;
    643     }
    644 
    645     // Start the repeated map entry object.
    646     // Render
    647     // { "key": "<name>", "value": {
    648     Push("", Item::MESSAGE, false, false);
    649     ProtoWriter::RenderDataPiece("key",
    650                                  DataPiece(name, use_strict_base64_decoding()));
    651     Push("value", Item::MESSAGE, true, false);
    652 
    653     // Make sure we are valid after pushing all above items.
    654     if (invalid_depth() > 0) return this;
    655 
    656     // case i and ii above. Start "list_value" field within g.p.Value
    657     if (element() != NULL && element()->parent_field() != NULL) {
    658       // Render
    659       // "list_value": {
    660       //   "values": [  // Start this list
    661       if (IsStructValue(*element()->parent_field())) {
    662         Push("list_value", Item::MESSAGE, true, false);
    663         Push("values", Item::MESSAGE, true, true);
    664         return this;
    665       }
    666 
    667       // Render
    668       // "values": [
    669       if (IsStructListValue(*element()->parent_field())) {
    670         // case iii above. Bind directly to g.p.ListValue
    671         Push("values", Item::MESSAGE, true, true);
    672         return this;
    673       }
    674     }
    675 
    676     // Report an error.
    677     InvalidValue("Map", StrCat("Cannot have repeated items ('", name,
    678                                "') within a map."));
    679     return this;
    680   }
    681 
    682   // When name is empty and stack is not empty, we are rendering an item within
    683   // a list.
    684   if (name.empty()) {
    685     if (element() != NULL && element()->parent_field() != NULL) {
    686       if (IsStructValue(*element()->parent_field())) {
    687         // Since it is g.p.Value, we bind directly to the list_value.
    688         // Render
    689         // {  // g.p.Value item within the list
    690         //   "list_value": {
    691         //     "values": [
    692         Push("", Item::MESSAGE, false, false);
    693         Push("list_value", Item::MESSAGE, true, false);
    694         Push("values", Item::MESSAGE, true, true);
    695         return this;
    696       }
    697 
    698       if (IsStructListValue(*element()->parent_field())) {
    699         // Since it is g.p.ListValue, we bind to it directly.
    700         // Render
    701         // {  // g.p.ListValue item within the list
    702         //   "values": [
    703         Push("", Item::MESSAGE, false, false);
    704         Push("values", Item::MESSAGE, true, true);
    705         return this;
    706       }
    707     }
    708 
    709     // Pass the event to underlying ProtoWriter.
    710     Push(name, Item::MESSAGE, false, true);
    711     return this;
    712   }
    713 
    714   // name is not empty
    715   const google::protobuf::Field* field = Lookup(name);
    716   if (field == NULL) {
    717     IncrementInvalidDepth();
    718     return this;
    719   }
    720 
    721   if (IsStructValue(*field)) {
    722     // If g.p.Value is repeated, start that list. Otherwise, start the
    723     // "list_value" within it.
    724     if (IsRepeated(*field)) {
    725       // Render it just like a regular repeated field.
    726       // "<name>": [
    727       Push(name, Item::MESSAGE, false, true);
    728       return this;
    729     }
    730 
    731     // Start the "list_value" field.
    732     // Render
    733     // "<name>": {
    734     //   "list_value": {
    735     //     "values": [
    736     Push(name, Item::MESSAGE, false, false);
    737     Push("list_value", Item::MESSAGE, true, false);
    738     Push("values", Item::MESSAGE, true, true);
    739     return this;
    740   }
    741 
    742   if (IsStructListValue(*field)) {
    743     // If g.p.ListValue is repeated, start that list. Otherwise, start the
    744     // "values" within it.
    745     if (IsRepeated(*field)) {
    746       // Render it just like a regular repeated field.
    747       // "<name>": [
    748       Push(name, Item::MESSAGE, false, true);
    749       return this;
    750     }
    751 
    752     // Start the "values" field within g.p.ListValue.
    753     // Render
    754     // "<name>": {
    755     //   "values": [
    756     Push(name, Item::MESSAGE, false, false);
    757     Push("values", Item::MESSAGE, true, true);
    758     return this;
    759   }
    760 
    761   // If we are here, the field should be repeated. Report an error otherwise.
    762   if (!IsRepeated(*field)) {
    763     IncrementInvalidDepth();
    764     InvalidName(name, "Proto field is not repeating, cannot start list.");
    765     return this;
    766   }
    767 
    768   if (IsMap(*field)) {
    769     InvalidValue("Map",
    770                  StrCat("Cannot bind a list to map for field '", name, "'."));
    771     IncrementInvalidDepth();
    772     return this;
    773   }
    774 
    775   // Pass the event to ProtoWriter.
    776   // Render
    777   // "<name>": [
    778   Push(name, Item::MESSAGE, false, true);
    779   return this;
    780 }
    781 
    782 ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndList() {
    783   if (invalid_depth() > 0) {
    784     DecrementInvalidDepth();
    785     return this;
    786   }
    787 
    788   if (current_ == NULL) return this;
    789 
    790   if (current_->IsAny()) {
    791     current_->any()->EndList();
    792     return this;
    793   }
    794 
    795   Pop();
    796   return this;
    797 }
    798 
    799 Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
    800                                                   const DataPiece& data) {
    801   string struct_field_name;
    802   switch (data.type()) {
    803     // Our JSON parser parses numbers as either int64, uint64, or double.
    804     case DataPiece::TYPE_INT64: {
    805       // If the option to treat integers as strings is set, then render them as
    806       // strings. Otherwise, fallback to rendering them as double.
    807       if (ow->options_.struct_integers_as_strings) {
    808         StatusOr<int64> int_value = data.ToInt64();
    809         if (int_value.ok()) {
    810           ow->ProtoWriter::RenderDataPiece(
    811               "string_value",
    812               DataPiece(SimpleItoa(int_value.ValueOrDie()), true));
    813           return Status::OK;
    814         }
    815       }
    816       struct_field_name = "number_value";
    817       break;
    818     }
    819     case DataPiece::TYPE_UINT64: {
    820       // If the option to treat integers as strings is set, then render them as
    821       // strings. Otherwise, fallback to rendering them as double.
    822       if (ow->options_.struct_integers_as_strings) {
    823         StatusOr<uint64> int_value = data.ToUint64();
    824         if (int_value.ok()) {
    825           ow->ProtoWriter::RenderDataPiece(
    826               "string_value",
    827               DataPiece(SimpleItoa(int_value.ValueOrDie()), true));
    828           return Status::OK;
    829         }
    830       }
    831       struct_field_name = "number_value";
    832       break;
    833     }
    834     case DataPiece::TYPE_DOUBLE: {
    835       struct_field_name = "number_value";
    836       break;
    837     }
    838     case DataPiece::TYPE_STRING: {
    839       struct_field_name = "string_value";
    840       break;
    841     }
    842     case DataPiece::TYPE_BOOL: {
    843       struct_field_name = "bool_value";
    844       break;
    845     }
    846     case DataPiece::TYPE_NULL: {
    847       struct_field_name = "null_value";
    848       break;
    849     }
    850     default: {
    851       return Status(INVALID_ARGUMENT,
    852                     "Invalid struct data type. Only number, string, boolean or "
    853                     "null values are supported.");
    854     }
    855   }
    856   ow->ProtoWriter::RenderDataPiece(struct_field_name, data);
    857   return Status::OK;
    858 }
    859 
    860 Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow,
    861                                                 const DataPiece& data) {
    862   if (data.type() != DataPiece::TYPE_STRING) {
    863     return Status(INVALID_ARGUMENT,
    864                   StrCat("Invalid data type for timestamp, value is ",
    865                          data.ValueAsStringOrDefault("")));
    866   }
    867 
    868   StringPiece value(data.str());
    869 
    870   int64 seconds;
    871   int32 nanos;
    872   if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds,
    873                                                &nanos)) {
    874     return Status(INVALID_ARGUMENT, StrCat("Invalid time format: ", value));
    875   }
    876 
    877 
    878   ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
    879   ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos));
    880   return Status::OK;
    881 }
    882 
    883 static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
    884                                                 StringPiece path) {
    885   ow->ProtoWriter::RenderDataPiece(
    886       "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true));
    887   return Status::OK;
    888 }
    889 
    890 Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
    891                                                 const DataPiece& data) {
    892   if (data.type() != DataPiece::TYPE_STRING) {
    893     return Status(INVALID_ARGUMENT,
    894                   StrCat("Invalid data type for field mask, value is ",
    895                          data.ValueAsStringOrDefault("")));
    896   }
    897 
    898 // TODO(tsun): figure out how to do proto descriptor based snake case
    899 // conversions as much as possible. Because ToSnakeCase sometimes returns the
    900 // wrong value.
    901   google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
    902       ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow));
    903   return DecodeCompactFieldMaskPaths(data.str(), callback.get());
    904 }
    905 
    906 Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow,
    907                                                const DataPiece& data) {
    908   if (data.type() != DataPiece::TYPE_STRING) {
    909     return Status(INVALID_ARGUMENT,
    910                   StrCat("Invalid data type for duration, value is ",
    911                          data.ValueAsStringOrDefault("")));
    912   }
    913 
    914   StringPiece value(data.str());
    915 
    916   if (!value.ends_with("s")) {
    917     return Status(INVALID_ARGUMENT,
    918                   "Illegal duration format; duration must end with 's'");
    919   }
    920   value = value.substr(0, value.size() - 1);
    921   int sign = 1;
    922   if (value.starts_with("-")) {
    923     sign = -1;
    924     value = value.substr(1);
    925   }
    926 
    927   StringPiece s_secs, s_nanos;
    928   SplitSecondsAndNanos(value, &s_secs, &s_nanos);
    929   uint64 unsigned_seconds;
    930   if (!safe_strtou64(s_secs, &unsigned_seconds)) {
    931     return Status(INVALID_ARGUMENT,
    932                   "Invalid duration format, failed to parse seconds");
    933   }
    934 
    935   int32 nanos = 0;
    936   Status nanos_status = GetNanosFromStringPiece(
    937       s_nanos, "Invalid duration format, failed to parse nano seconds",
    938       "Duration value exceeds limits", &nanos);
    939   if (!nanos_status.ok()) {
    940     return nanos_status;
    941   }
    942   nanos = sign * nanos;
    943 
    944   int64 seconds = sign * unsigned_seconds;
    945   if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds ||
    946       nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
    947     return Status(INVALID_ARGUMENT, "Duration value exceeds limits");
    948   }
    949 
    950   ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
    951   ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos));
    952   return Status::OK;
    953 }
    954 
    955 Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow,
    956                                                   const DataPiece& data) {
    957   ow->ProtoWriter::RenderDataPiece("value", data);
    958   return Status::OK;
    959 }
    960 
    961 ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
    962     StringPiece name, const DataPiece& data) {
    963   Status status;
    964   if (invalid_depth() > 0) return this;
    965 
    966   if (current_ == NULL) {
    967     const TypeRenderer* type_renderer =
    968         FindTypeRenderer(GetFullTypeWithUrl(master_type_.name()));
    969     if (type_renderer == NULL) {
    970       InvalidName(name, "Root element must be a message.");
    971       return this;
    972     }
    973     // Render the special type.
    974     // "<name>": {
    975     //   ... Render special type ...
    976     // }
    977     ProtoWriter::StartObject(name);
    978     status = (*type_renderer)(this, data);
    979     if (!status.ok()) {
    980       InvalidValue(master_type_.name(),
    981                    StrCat("Field '", name, "', ", status.error_message()));
    982     }
    983     ProtoWriter::EndObject();
    984     return this;
    985   }
    986 
    987   if (current_->IsAny()) {
    988     current_->any()->RenderDataPiece(name, data);
    989     return this;
    990   }
    991 
    992   const google::protobuf::Field* field = NULL;
    993   if (current_->IsMap()) {
    994     if (!ValidMapKey(name)) return this;
    995 
    996     // Render an item in repeated map list.
    997     // { "key": "<name>", "value":
    998     Push("", Item::MESSAGE, false, false);
    999     ProtoWriter::RenderDataPiece("key",
   1000                                  DataPiece(name, use_strict_base64_decoding()));
   1001     field = Lookup("value");
   1002     if (field == NULL) {
   1003       GOOGLE_LOG(DFATAL) << "Map does not have a value field.";
   1004       return this;
   1005     }
   1006 
   1007     const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url());
   1008     if (type_renderer != NULL) {
   1009       // Map's value type is a special type. Render it like a message:
   1010       // "value": {
   1011       //   ... Render special type ...
   1012       // }
   1013       Push("value", Item::MESSAGE, true, false);
   1014       status = (*type_renderer)(this, data);
   1015       if (!status.ok()) {
   1016         InvalidValue(field->type_url(),
   1017                      StrCat("Field '", name, "', ", status.error_message()));
   1018       }
   1019       Pop();
   1020       return this;
   1021     }
   1022 
   1023     // If we are rendering explicit null values and the backend proto field is
   1024     // not of the google.protobuf.NullType type, we do nothing.
   1025     if (data.type() == DataPiece::TYPE_NULL &&
   1026         field->type_url() != kStructNullValueTypeUrl) {
   1027       Pop();
   1028       return this;
   1029     }
   1030 
   1031     // Render the map value as a primitive type.
   1032     ProtoWriter::RenderDataPiece("value", data);
   1033     Pop();
   1034     return this;
   1035   }
   1036 
   1037   field = Lookup(name);
   1038   if (field == NULL) return this;
   1039 
   1040   // Check if the field is of special type. Render it accordingly if so.
   1041   const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url());
   1042   if (type_renderer != NULL) {
   1043     Push(name, Item::MESSAGE, false, false);
   1044     status = (*type_renderer)(this, data);
   1045     if (!status.ok()) {
   1046       InvalidValue(field->type_url(),
   1047                    StrCat("Field '", name, "', ", status.error_message()));
   1048     }
   1049     Pop();
   1050     return this;
   1051   }
   1052 
   1053   // If we are rendering explicit null values and the backend proto field is
   1054   // not of the google.protobuf.NullType type, we do nothing.
   1055   if (data.type() == DataPiece::TYPE_NULL &&
   1056       field->type_url() != kStructNullValueTypeUrl) {
   1057     return this;
   1058   }
   1059 
   1060   ProtoWriter::RenderDataPiece(name, data);
   1061   return this;
   1062 }
   1063 
   1064 // Map of functions that are responsible for rendering well known type
   1065 // represented by the key.
   1066 hash_map<string, ProtoStreamObjectWriter::TypeRenderer>*
   1067     ProtoStreamObjectWriter::renderers_ = NULL;
   1068 GOOGLE_PROTOBUF_DECLARE_ONCE(writer_renderers_init_);
   1069 
   1070 void ProtoStreamObjectWriter::InitRendererMap() {
   1071   renderers_ = new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>();
   1072   (*renderers_)["type.googleapis.com/google.protobuf.Timestamp"] =
   1073       &ProtoStreamObjectWriter::RenderTimestamp;
   1074   (*renderers_)["type.googleapis.com/google.protobuf.Duration"] =
   1075       &ProtoStreamObjectWriter::RenderDuration;
   1076   (*renderers_)["type.googleapis.com/google.protobuf.FieldMask"] =
   1077       &ProtoStreamObjectWriter::RenderFieldMask;
   1078   (*renderers_)["type.googleapis.com/google.protobuf.Double"] =
   1079       &ProtoStreamObjectWriter::RenderWrapperType;
   1080   (*renderers_)["type.googleapis.com/google.protobuf.Float"] =
   1081       &ProtoStreamObjectWriter::RenderWrapperType;
   1082   (*renderers_)["type.googleapis.com/google.protobuf.Int64"] =
   1083       &ProtoStreamObjectWriter::RenderWrapperType;
   1084   (*renderers_)["type.googleapis.com/google.protobuf.UInt64"] =
   1085       &ProtoStreamObjectWriter::RenderWrapperType;
   1086   (*renderers_)["type.googleapis.com/google.protobuf.Int32"] =
   1087       &ProtoStreamObjectWriter::RenderWrapperType;
   1088   (*renderers_)["type.googleapis.com/google.protobuf.UInt32"] =
   1089       &ProtoStreamObjectWriter::RenderWrapperType;
   1090   (*renderers_)["type.googleapis.com/google.protobuf.Bool"] =
   1091       &ProtoStreamObjectWriter::RenderWrapperType;
   1092   (*renderers_)["type.googleapis.com/google.protobuf.String"] =
   1093       &ProtoStreamObjectWriter::RenderWrapperType;
   1094   (*renderers_)["type.googleapis.com/google.protobuf.Bytes"] =
   1095       &ProtoStreamObjectWriter::RenderWrapperType;
   1096   (*renderers_)["type.googleapis.com/google.protobuf.DoubleValue"] =
   1097       &ProtoStreamObjectWriter::RenderWrapperType;
   1098   (*renderers_)["type.googleapis.com/google.protobuf.FloatValue"] =
   1099       &ProtoStreamObjectWriter::RenderWrapperType;
   1100   (*renderers_)["type.googleapis.com/google.protobuf.Int64Value"] =
   1101       &ProtoStreamObjectWriter::RenderWrapperType;
   1102   (*renderers_)["type.googleapis.com/google.protobuf.UInt64Value"] =
   1103       &ProtoStreamObjectWriter::RenderWrapperType;
   1104   (*renderers_)["type.googleapis.com/google.protobuf.Int32Value"] =
   1105       &ProtoStreamObjectWriter::RenderWrapperType;
   1106   (*renderers_)["type.googleapis.com/google.protobuf.UInt32Value"] =
   1107       &ProtoStreamObjectWriter::RenderWrapperType;
   1108   (*renderers_)["type.googleapis.com/google.protobuf.BoolValue"] =
   1109       &ProtoStreamObjectWriter::RenderWrapperType;
   1110   (*renderers_)["type.googleapis.com/google.protobuf.StringValue"] =
   1111       &ProtoStreamObjectWriter::RenderWrapperType;
   1112   (*renderers_)["type.googleapis.com/google.protobuf.BytesValue"] =
   1113       &ProtoStreamObjectWriter::RenderWrapperType;
   1114   (*renderers_)["type.googleapis.com/google.protobuf.Value"] =
   1115       &ProtoStreamObjectWriter::RenderStructValue;
   1116   ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
   1117 }
   1118 
   1119 void ProtoStreamObjectWriter::DeleteRendererMap() {
   1120   delete ProtoStreamObjectWriter::renderers_;
   1121   renderers_ = NULL;
   1122 }
   1123 
   1124 ProtoStreamObjectWriter::TypeRenderer*
   1125 ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) {
   1126   ::google::protobuf::GoogleOnceInit(&writer_renderers_init_, &InitRendererMap);
   1127   return FindOrNull(*renderers_, type_url);
   1128 }
   1129 
   1130 bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) {
   1131   if (current_ == NULL) return true;
   1132 
   1133   if (!current_->InsertMapKeyIfNotPresent(unnormalized_name)) {
   1134     listener()->InvalidName(
   1135         location(), unnormalized_name,
   1136         StrCat("Repeated map key: '", unnormalized_name, "' is already set."));
   1137     return false;
   1138   }
   1139 
   1140   return true;
   1141 }
   1142 
   1143 void ProtoStreamObjectWriter::Push(StringPiece name, Item::ItemType item_type,
   1144                                    bool is_placeholder, bool is_list) {
   1145   is_list ? ProtoWriter::StartList(name) : ProtoWriter::StartObject(name);
   1146 
   1147   // invalid_depth == 0 means it is a successful StartObject or StartList.
   1148   if (invalid_depth() == 0)
   1149     current_.reset(
   1150         new Item(current_.release(), item_type, is_placeholder, is_list));
   1151 }
   1152 
   1153 void ProtoStreamObjectWriter::Pop() {
   1154   // Pop all placeholder items sending StartObject or StartList events to
   1155   // ProtoWriter according to is_list value.
   1156   while (current_ != NULL && current_->is_placeholder()) {
   1157     PopOneElement();
   1158   }
   1159   if (current_ != NULL) {
   1160     PopOneElement();
   1161   }
   1162 }
   1163 
   1164 void ProtoStreamObjectWriter::PopOneElement() {
   1165   current_->is_list() ? ProtoWriter::EndList() : ProtoWriter::EndObject();
   1166   current_.reset(current_->pop<Item>());
   1167 }
   1168 
   1169 bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) {
   1170   if (field.type_url().empty() ||
   1171       field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE ||
   1172       field.cardinality() !=
   1173           google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
   1174     return false;
   1175   }
   1176   const google::protobuf::Type* field_type =
   1177       typeinfo()->GetTypeByTypeUrl(field.type_url());
   1178 
   1179   // TODO(xiaofeng): Unify option names.
   1180   return GetBoolOptionOrDefault(field_type->options(),
   1181                                 "google.protobuf.MessageOptions.map_entry", false) ||
   1182          GetBoolOptionOrDefault(field_type->options(), "map_entry", false);
   1183 }
   1184 
   1185 bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) {
   1186   return GetTypeWithoutUrl(field.type_url()) == kAnyType;
   1187 }
   1188 
   1189 bool ProtoStreamObjectWriter::IsStruct(const google::protobuf::Field& field) {
   1190   return GetTypeWithoutUrl(field.type_url()) == kStructType;
   1191 }
   1192 
   1193 bool ProtoStreamObjectWriter::IsStructValue(
   1194     const google::protobuf::Field& field) {
   1195   return GetTypeWithoutUrl(field.type_url()) == kStructValueType;
   1196 }
   1197 
   1198 bool ProtoStreamObjectWriter::IsStructListValue(
   1199     const google::protobuf::Field& field) {
   1200   return GetTypeWithoutUrl(field.type_url()) == kStructListValueType;
   1201 }
   1202 
   1203 }  // namespace converter
   1204 }  // namespace util
   1205 }  // namespace protobuf
   1206 }  // namespace google
   1207