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
48namespace google {
49namespace protobuf {
50namespace util {
51namespace converter {
52
53using google::protobuf::internal::WireFormatLite;
54using util::error::INVALID_ARGUMENT;
55using util::Status;
56using util::StatusOr;
57
58
59ProtoStreamObjectWriter::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
68ProtoStreamObjectWriter::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
76ProtoStreamObjectWriter::~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
89namespace {
90// Utility method to split a string representation of Timestamp or Duration and
91// return the parts.
92void 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
104Status 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
178ProtoStreamObjectWriter::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
188ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {}
189
190void 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
221bool 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
238void 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
260void 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
272void 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
309void 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
361void 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
375ProtoStreamObjectWriter::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
389ProtoStreamObjectWriter::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
403bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent(
404    StringPiece map_key) {
405  return InsertIfNotPresent(&map_keys_, map_key.ToString());
406}
407
408ProtoStreamObjectWriter* 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
552ProtoStreamObjectWriter* 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
569ProtoStreamObjectWriter* 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
782ProtoStreamObjectWriter* 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
799Status 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
860Status 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
883static 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
890Status 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
906Status 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
955Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow,
956                                                  const DataPiece& data) {
957  ow->ProtoWriter::RenderDataPiece("value", data);
958  return Status::OK;
959}
960
961ProtoStreamObjectWriter* 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.
1066hash_map<string, ProtoStreamObjectWriter::TypeRenderer>*
1067    ProtoStreamObjectWriter::renderers_ = NULL;
1068GOOGLE_PROTOBUF_DECLARE_ONCE(writer_renderers_init_);
1069
1070void 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
1119void ProtoStreamObjectWriter::DeleteRendererMap() {
1120  delete ProtoStreamObjectWriter::renderers_;
1121  renderers_ = NULL;
1122}
1123
1124ProtoStreamObjectWriter::TypeRenderer*
1125ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) {
1126  ::google::protobuf::GoogleOnceInit(&writer_renderers_init_, &InitRendererMap);
1127  return FindOrNull(*renderers_, type_url);
1128}
1129
1130bool 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
1143void 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
1153void 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
1164void ProtoStreamObjectWriter::PopOneElement() {
1165  current_->is_list() ? ProtoWriter::EndList() : ProtoWriter::EndObject();
1166  current_.reset(current_->pop<Item>());
1167}
1168
1169bool 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
1185bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) {
1186  return GetTypeWithoutUrl(field.type_url()) == kAnyType;
1187}
1188
1189bool ProtoStreamObjectWriter::IsStruct(const google::protobuf::Field& field) {
1190  return GetTypeWithoutUrl(field.type_url()) == kStructType;
1191}
1192
1193bool ProtoStreamObjectWriter::IsStructValue(
1194    const google::protobuf::Field& field) {
1195  return GetTypeWithoutUrl(field.type_url()) == kStructValueType;
1196}
1197
1198bool 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