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/default_value_objectwriter.h>
32 
33 #include <unordered_map>
34 
35 #include <google/protobuf/util/internal/constants.h>
36 #include <google/protobuf/util/internal/utility.h>
37 #include <google/protobuf/stubs/map_util.h>
38 
39 namespace google {
40 namespace protobuf {
41 namespace util {
42 using util::Status;
43 using util::StatusOr;
44 namespace converter {
45 
46 namespace {
47 // Helper function to convert string value to given data type by calling the
48 // passed converter function on the DataPiece created from "value" argument.
49 // If value is empty or if conversion fails, the default_value is returned.
50 template <typename T>
ConvertTo(StringPiece value,StatusOr<T> (DataPiece::* converter_fn)()const,T default_value)51 T ConvertTo(StringPiece value,
52             StatusOr<T> (DataPiece::*converter_fn)() const, T default_value) {
53   if (value.empty()) return default_value;
54   StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
55   return result.ok() ? result.ValueOrDie() : default_value;
56 }
57 }  // namespace
58 
DefaultValueObjectWriter(TypeResolver * type_resolver,const google::protobuf::Type & type,ObjectWriter * ow)59 DefaultValueObjectWriter::DefaultValueObjectWriter(
60     TypeResolver* type_resolver, const google::protobuf::Type& type,
61     ObjectWriter* ow)
62     : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
63       own_typeinfo_(true),
64       type_(type),
65       current_(nullptr),
66       root_(nullptr),
67       suppress_empty_list_(false),
68       preserve_proto_field_names_(false),
69       use_ints_for_enums_(false),
70       ow_(ow) {}
71 
~DefaultValueObjectWriter()72 DefaultValueObjectWriter::~DefaultValueObjectWriter() {
73   if (own_typeinfo_) {
74     delete typeinfo_;
75   }
76 }
77 
RenderBool(StringPiece name,bool value)78 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(
79     StringPiece name, bool value) {
80   if (current_ == nullptr) {
81     ow_->RenderBool(name, value);
82   } else {
83     RenderDataPiece(name, DataPiece(value));
84   }
85   return this;
86 }
87 
RenderInt32(StringPiece name,int32 value)88 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32(
89     StringPiece name, int32 value) {
90   if (current_ == nullptr) {
91     ow_->RenderInt32(name, value);
92   } else {
93     RenderDataPiece(name, DataPiece(value));
94   }
95   return this;
96 }
97 
RenderUint32(StringPiece name,uint32 value)98 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32(
99     StringPiece name, uint32 value) {
100   if (current_ == nullptr) {
101     ow_->RenderUint32(name, value);
102   } else {
103     RenderDataPiece(name, DataPiece(value));
104   }
105   return this;
106 }
107 
RenderInt64(StringPiece name,int64 value)108 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64(
109     StringPiece name, int64 value) {
110   if (current_ == nullptr) {
111     ow_->RenderInt64(name, value);
112   } else {
113     RenderDataPiece(name, DataPiece(value));
114   }
115   return this;
116 }
117 
RenderUint64(StringPiece name,uint64 value)118 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64(
119     StringPiece name, uint64 value) {
120   if (current_ == nullptr) {
121     ow_->RenderUint64(name, value);
122   } else {
123     RenderDataPiece(name, DataPiece(value));
124   }
125   return this;
126 }
127 
RenderDouble(StringPiece name,double value)128 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble(
129     StringPiece name, double value) {
130   if (current_ == nullptr) {
131     ow_->RenderDouble(name, value);
132   } else {
133     RenderDataPiece(name, DataPiece(value));
134   }
135   return this;
136 }
137 
RenderFloat(StringPiece name,float value)138 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat(
139     StringPiece name, float value) {
140   if (current_ == nullptr) {
141     ow_->RenderBool(name, value);
142   } else {
143     RenderDataPiece(name, DataPiece(value));
144   }
145   return this;
146 }
147 
RenderString(StringPiece name,StringPiece value)148 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString(
149     StringPiece name, StringPiece value) {
150   if (current_ == nullptr) {
151     ow_->RenderString(name, value);
152   } else {
153     // Since StringPiece is essentially a pointer, takes a copy of "value" to
154     // avoid ownership issues.
155     string_values_.emplace_back(new std::string(value));
156     RenderDataPiece(name, DataPiece(*string_values_.back(), true));
157   }
158   return this;
159 }
160 
RenderBytes(StringPiece name,StringPiece value)161 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
162     StringPiece name, StringPiece value) {
163   if (current_ == nullptr) {
164     ow_->RenderBytes(name, value);
165   } else {
166     // Since StringPiece is essentially a pointer, takes a copy of "value" to
167     // avoid ownership issues.
168     string_values_.emplace_back(new std::string(value));
169     RenderDataPiece(name, DataPiece(*string_values_.back(), false, true));
170   }
171   return this;
172 }
173 
RenderNull(StringPiece name)174 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull(
175     StringPiece name) {
176   if (current_ == nullptr) {
177     ow_->RenderNull(name);
178   } else {
179     RenderDataPiece(name, DataPiece::NullData());
180   }
181   return this;
182 }
183 
RegisterFieldScrubCallBack(FieldScrubCallBack field_scrub_callback)184 void DefaultValueObjectWriter::RegisterFieldScrubCallBack(
185     FieldScrubCallBack field_scrub_callback) {
186   field_scrub_callback_ = std::move(field_scrub_callback);
187 }
188 
CreateNewNode(const std::string & name,const google::protobuf::Type * type,NodeKind kind,const DataPiece & data,bool is_placeholder,const std::vector<std::string> & path,bool suppress_empty_list,bool preserve_proto_field_names,bool use_ints_for_enums,FieldScrubCallBack field_scrub_callback)189 DefaultValueObjectWriter::Node* DefaultValueObjectWriter::CreateNewNode(
190     const std::string& name, const google::protobuf::Type* type, NodeKind kind,
191     const DataPiece& data, bool is_placeholder,
192     const std::vector<std::string>& path, bool suppress_empty_list,
193     bool preserve_proto_field_names, bool use_ints_for_enums,
194     FieldScrubCallBack field_scrub_callback) {
195   return new Node(name, type, kind, data, is_placeholder, path,
196                   suppress_empty_list, preserve_proto_field_names,
197                   use_ints_for_enums, std::move(field_scrub_callback));
198 }
199 
Node(const std::string & name,const google::protobuf::Type * type,NodeKind kind,const DataPiece & data,bool is_placeholder,const std::vector<std::string> & path,bool suppress_empty_list,bool preserve_proto_field_names,bool use_ints_for_enums,FieldScrubCallBack field_scrub_callback)200 DefaultValueObjectWriter::Node::Node(
201     const std::string& name, const google::protobuf::Type* type, NodeKind kind,
202     const DataPiece& data, bool is_placeholder,
203     const std::vector<std::string>& path, bool suppress_empty_list,
204     bool preserve_proto_field_names, bool use_ints_for_enums,
205     FieldScrubCallBack field_scrub_callback)
206     : name_(name),
207       type_(type),
208       kind_(kind),
209       is_any_(false),
210       data_(data),
211       is_placeholder_(is_placeholder),
212       path_(path),
213       suppress_empty_list_(suppress_empty_list),
214       preserve_proto_field_names_(preserve_proto_field_names),
215       use_ints_for_enums_(use_ints_for_enums),
216       field_scrub_callback_(std::move(field_scrub_callback)) {}
217 
FindChild(StringPiece name)218 DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
219     StringPiece name) {
220   if (name.empty() || kind_ != OBJECT) {
221     return nullptr;
222   }
223   for (int i = 0; i < children_.size(); ++i) {
224     Node* child = children_[i];
225     if (child->name() == name) {
226       return child;
227     }
228   }
229   return nullptr;
230 }
231 
WriteTo(ObjectWriter * ow)232 void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) {
233   if (kind_ == PRIMITIVE) {
234     ObjectWriter::RenderDataPieceTo(data_, name_, ow);
235     return;
236   }
237 
238   // Render maps. Empty maps are rendered as "{}".
239   if (kind_ == MAP) {
240     ow->StartObject(name_);
241     WriteChildren(ow);
242     ow->EndObject();
243     return;
244   }
245 
246   // Write out lists. If we didn't have any list in response, write out empty
247   // list.
248   if (kind_ == LIST) {
249     // Suppress empty lists if requested.
250     if (suppress_empty_list_ && is_placeholder_) return;
251 
252     ow->StartList(name_);
253     WriteChildren(ow);
254     ow->EndList();
255     return;
256   }
257 
258   // If is_placeholder_ = true, we didn't see this node in the response, so
259   // skip output.
260   if (is_placeholder_) return;
261 
262   ow->StartObject(name_);
263   WriteChildren(ow);
264   ow->EndObject();
265 }
266 
WriteChildren(ObjectWriter * ow)267 void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) {
268   for (int i = 0; i < children_.size(); ++i) {
269     Node* child = children_[i];
270     child->WriteTo(ow);
271   }
272 }
273 
GetMapValueType(const google::protobuf::Type & found_type,const TypeInfo * typeinfo)274 const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
275     const google::protobuf::Type& found_type, const TypeInfo* typeinfo) {
276   // If this field is a map, we should use the type of its "Value" as
277   // the type of the child node.
278   for (int i = 0; i < found_type.fields_size(); ++i) {
279     const google::protobuf::Field& sub_field = found_type.fields(i);
280     if (sub_field.number() != 2) {
281       continue;
282     }
283     if (sub_field.kind() != google::protobuf::Field::TYPE_MESSAGE) {
284       // This map's value type is not a message type. We don't need to
285       // get the field_type in this case.
286       break;
287     }
288     util::StatusOr<const google::protobuf::Type*> sub_type =
289         typeinfo->ResolveTypeUrl(sub_field.type_url());
290     if (!sub_type.ok()) {
291       GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'.";
292     } else {
293       return sub_type.ValueOrDie();
294     }
295     break;
296   }
297   return nullptr;
298 }
299 
PopulateChildren(const TypeInfo * typeinfo)300 void DefaultValueObjectWriter::Node::PopulateChildren(
301     const TypeInfo* typeinfo) {
302   // Ignores well known types that don't require automatically populating their
303   // primitive children. For type "Any", we only populate its children when the
304   // "@type" field is set.
305   // TODO(tsun): remove "kStructValueType" from the list. It's being checked
306   //     now because of a bug in the tool-chain that causes the "oneof_index"
307   //     of kStructValueType to not be set correctly.
308   if (type_ == nullptr || type_->name() == kAnyType ||
309       type_->name() == kStructType || type_->name() == kTimestampType ||
310       type_->name() == kDurationType || type_->name() == kStructValueType) {
311     return;
312   }
313   std::vector<Node*> new_children;
314   std::unordered_map<std::string, int> orig_children_map;
315 
316   // Creates a map of child nodes to speed up lookup.
317   for (int i = 0; i < children_.size(); ++i) {
318     InsertIfNotPresent(&orig_children_map, children_[i]->name_, i);
319   }
320 
321   for (int i = 0; i < type_->fields_size(); ++i) {
322     const google::protobuf::Field& field = type_->fields(i);
323 
324     // This code is checking if the field to be added to the tree should be
325     // scrubbed or not by calling the field_scrub_callback_ callback function.
326     std::vector<std::string> path;
327     if (!path_.empty()) {
328       path.insert(path.begin(), path_.begin(), path_.end());
329     }
330     path.push_back(field.name());
331     if (field_scrub_callback_ && field_scrub_callback_(path, &field)) {
332       continue;
333     }
334 
335     std::unordered_map<std::string, int>::iterator found =
336         orig_children_map.find(field.name());
337     // If the child field has already been set, we just add it to the new list
338     // of children.
339     if (found != orig_children_map.end()) {
340       new_children.push_back(children_[found->second]);
341       children_[found->second] = nullptr;
342       continue;
343     }
344 
345     const google::protobuf::Type* field_type = nullptr;
346     bool is_map = false;
347     NodeKind kind = PRIMITIVE;
348 
349     if (field.kind() == google::protobuf::Field::TYPE_MESSAGE) {
350       kind = OBJECT;
351       util::StatusOr<const google::protobuf::Type*> found_result =
352           typeinfo->ResolveTypeUrl(field.type_url());
353       if (!found_result.ok()) {
354         // "field" is of an unknown type.
355         GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'.";
356       } else {
357         const google::protobuf::Type* found_type = found_result.ValueOrDie();
358         is_map = IsMap(field, *found_type);
359 
360         if (!is_map) {
361           field_type = found_type;
362         } else {
363           // If this field is a map, we should use the type of its "Value" as
364           // the type of the child node.
365           field_type = GetMapValueType(*found_type, typeinfo);
366           kind = MAP;
367         }
368       }
369     }
370 
371     if (!is_map &&
372         field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED) {
373       kind = LIST;
374     }
375 
376     // If oneof_index() != 0, the child field is part of a "oneof", which means
377     // the child field is optional and we shouldn't populate its default
378     // primitive value.
379     if (field.oneof_index() != 0 && kind == PRIMITIVE) continue;
380 
381     // If the child field is of primitive type, sets its data to the default
382     // value of its type.
383     std::unique_ptr<Node> child(
384         new Node(preserve_proto_field_names_ ? field.name() : field.json_name(),
385                  field_type, kind,
386                  kind == PRIMITIVE ? CreateDefaultDataPieceForField(
387                                          field, typeinfo, use_ints_for_enums_)
388                                    : DataPiece::NullData(),
389                  true, path, suppress_empty_list_, preserve_proto_field_names_,
390                  use_ints_for_enums_, field_scrub_callback_));
391     new_children.push_back(child.release());
392   }
393   // Adds all leftover nodes in children_ to the beginning of new_child.
394   for (int i = 0; i < children_.size(); ++i) {
395     if (children_[i] == nullptr) {
396       continue;
397     }
398     new_children.insert(new_children.begin(), children_[i]);
399     children_[i] = nullptr;
400   }
401   children_.swap(new_children);
402 }
403 
MaybePopulateChildrenOfAny(Node * node)404 void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) {
405   // If this is an "Any" node with "@type" already given and no other children
406   // have been added, populates its children.
407   if (node != nullptr && node->is_any() && node->type() != nullptr &&
408       node->type()->name() != kAnyType && node->number_of_children() == 1) {
409     node->PopulateChildren(typeinfo_);
410   }
411 }
412 
FindEnumDefault(const google::protobuf::Field & field,const TypeInfo * typeinfo,bool use_ints_for_enums)413 DataPiece DefaultValueObjectWriter::FindEnumDefault(
414     const google::protobuf::Field& field, const TypeInfo* typeinfo,
415     bool use_ints_for_enums) {
416   if (!field.default_value().empty())
417     return DataPiece(field.default_value(), true);
418 
419   const google::protobuf::Enum* enum_type =
420       typeinfo->GetEnumByTypeUrl(field.type_url());
421   if (!enum_type) {
422     GOOGLE_LOG(WARNING) << "Could not find enum with type '" << field.type_url()
423                  << "'";
424     return DataPiece::NullData();
425   }
426   // We treat the first value as the default if none is specified.
427   return enum_type->enumvalue_size() > 0
428              ? (use_ints_for_enums
429                     ? DataPiece(enum_type->enumvalue(0).number())
430                     : DataPiece(enum_type->enumvalue(0).name(), true))
431              : DataPiece::NullData();
432 }
433 
CreateDefaultDataPieceForField(const google::protobuf::Field & field,const TypeInfo * typeinfo,bool use_ints_for_enums)434 DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
435     const google::protobuf::Field& field, const TypeInfo* typeinfo,
436     bool use_ints_for_enums) {
437   switch (field.kind()) {
438     case google::protobuf::Field::TYPE_DOUBLE: {
439       return DataPiece(ConvertTo<double>(
440           field.default_value(), &DataPiece::ToDouble, static_cast<double>(0)));
441     }
442     case google::protobuf::Field::TYPE_FLOAT: {
443       return DataPiece(ConvertTo<float>(
444           field.default_value(), &DataPiece::ToFloat, static_cast<float>(0)));
445     }
446     case google::protobuf::Field::TYPE_INT64:
447     case google::protobuf::Field::TYPE_SINT64:
448     case google::protobuf::Field::TYPE_SFIXED64: {
449       return DataPiece(ConvertTo<int64>(
450           field.default_value(), &DataPiece::ToInt64, static_cast<int64>(0)));
451     }
452     case google::protobuf::Field::TYPE_UINT64:
453     case google::protobuf::Field::TYPE_FIXED64: {
454       return DataPiece(ConvertTo<uint64>(
455           field.default_value(), &DataPiece::ToUint64, static_cast<uint64>(0)));
456     }
457     case google::protobuf::Field::TYPE_INT32:
458     case google::protobuf::Field::TYPE_SINT32:
459     case google::protobuf::Field::TYPE_SFIXED32: {
460       return DataPiece(ConvertTo<int32>(
461           field.default_value(), &DataPiece::ToInt32, static_cast<int32>(0)));
462     }
463     case google::protobuf::Field::TYPE_BOOL: {
464       return DataPiece(
465           ConvertTo<bool>(field.default_value(), &DataPiece::ToBool, false));
466     }
467     case google::protobuf::Field::TYPE_STRING: {
468       return DataPiece(field.default_value(), true);
469     }
470     case google::protobuf::Field::TYPE_BYTES: {
471       return DataPiece(field.default_value(), false, true);
472     }
473     case google::protobuf::Field::TYPE_UINT32:
474     case google::protobuf::Field::TYPE_FIXED32: {
475       return DataPiece(ConvertTo<uint32>(
476           field.default_value(), &DataPiece::ToUint32, static_cast<uint32>(0)));
477     }
478     case google::protobuf::Field::TYPE_ENUM: {
479       return FindEnumDefault(field, typeinfo, use_ints_for_enums);
480     }
481     default: {
482       return DataPiece::NullData();
483     }
484   }
485 }
486 
StartObject(StringPiece name)487 DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
488     StringPiece name) {
489   if (current_ == nullptr) {
490     std::vector<std::string> path;
491     root_.reset(CreateNewNode(std::string(name), &type_, OBJECT,
492                               DataPiece::NullData(), false, path,
493                               suppress_empty_list_, preserve_proto_field_names_,
494                               use_ints_for_enums_, field_scrub_callback_));
495     root_->PopulateChildren(typeinfo_);
496     current_ = root_.get();
497     return this;
498   }
499   MaybePopulateChildrenOfAny(current_);
500   Node* child = current_->FindChild(name);
501   if (current_->kind() == LIST || current_->kind() == MAP || child == nullptr) {
502     // If current_ is a list or a map node, we should create a new child and use
503     // the type of current_ as the type of the new child.
504     std::unique_ptr<Node> node(
505         CreateNewNode(std::string(name),
506                       ((current_->kind() == LIST || current_->kind() == MAP)
507                            ? current_->type()
508                            : nullptr),
509                       OBJECT, DataPiece::NullData(), false,
510                       child == nullptr ? current_->path() : child->path(),
511                       suppress_empty_list_, preserve_proto_field_names_,
512                       use_ints_for_enums_, field_scrub_callback_));
513     child = node.get();
514     current_->AddChild(node.release());
515   }
516 
517   child->set_is_placeholder(false);
518   if (child->kind() == OBJECT && child->number_of_children() == 0) {
519     child->PopulateChildren(typeinfo_);
520   }
521 
522   stack_.push(current_);
523   current_ = child;
524   return this;
525 }
526 
EndObject()527 DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() {
528   if (stack_.empty()) {
529     // The root object ends here. Writes out the tree.
530     WriteRoot();
531     return this;
532   }
533   current_ = stack_.top();
534   stack_.pop();
535   return this;
536 }
537 
StartList(StringPiece name)538 DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
539     StringPiece name) {
540   if (current_ == nullptr) {
541     std::vector<std::string> path;
542     root_.reset(CreateNewNode(std::string(name), &type_, LIST,
543                               DataPiece::NullData(), false, path,
544                               suppress_empty_list_, preserve_proto_field_names_,
545                               use_ints_for_enums_, field_scrub_callback_));
546     current_ = root_.get();
547     return this;
548   }
549   MaybePopulateChildrenOfAny(current_);
550   Node* child = current_->FindChild(name);
551   if (child == nullptr || child->kind() != LIST) {
552     std::unique_ptr<Node> node(CreateNewNode(
553         std::string(name), nullptr, LIST, DataPiece::NullData(), false,
554         child == nullptr ? current_->path() : child->path(),
555         suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_,
556         field_scrub_callback_));
557     child = node.get();
558     current_->AddChild(node.release());
559   }
560   child->set_is_placeholder(false);
561 
562   stack_.push(current_);
563   current_ = child;
564   return this;
565 }
566 
WriteRoot()567 void DefaultValueObjectWriter::WriteRoot() {
568   root_->WriteTo(ow_);
569   root_.reset(nullptr);
570   current_ = nullptr;
571 }
572 
EndList()573 DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() {
574   if (stack_.empty()) {
575     WriteRoot();
576     return this;
577   }
578   current_ = stack_.top();
579   stack_.pop();
580   return this;
581 }
582 
RenderDataPiece(StringPiece name,const DataPiece & data)583 void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
584                                                const DataPiece& data) {
585   MaybePopulateChildrenOfAny(current_);
586   if (current_->type() != nullptr && current_->type()->name() == kAnyType &&
587       name == "@type") {
588     util::StatusOr<std::string> data_string = data.ToString();
589     if (data_string.ok()) {
590       const std::string& string_value = data_string.ValueOrDie();
591       // If the type of current_ is "Any" and its "@type" field is being set
592       // here, sets the type of current_ to be the type specified by the
593       // "@type".
594       util::StatusOr<const google::protobuf::Type*> found_type =
595           typeinfo_->ResolveTypeUrl(string_value);
596       if (!found_type.ok()) {
597         GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.";
598       } else {
599         current_->set_type(found_type.ValueOrDie());
600       }
601       current_->set_is_any(true);
602       // If the "@type" field is placed after other fields, we should populate
603       // other children of primitive type now. Otherwise, we should wait until
604       // the first value field is rendered before we populate the children,
605       // because the "value" field of a Any message could be omitted.
606       if (current_->number_of_children() > 1 && current_->type() != nullptr) {
607         current_->PopulateChildren(typeinfo_);
608       }
609     }
610   }
611   Node* child = current_->FindChild(name);
612   if (child == nullptr || child->kind() != PRIMITIVE) {
613     // No children are found, creates a new child.
614     std::unique_ptr<Node> node(
615         CreateNewNode(std::string(name), nullptr, PRIMITIVE, data, false,
616                       child == nullptr ? current_->path() : child->path(),
617                       suppress_empty_list_, preserve_proto_field_names_,
618                       use_ints_for_enums_, field_scrub_callback_));
619     current_->AddChild(node.release());
620   } else {
621     child->set_data(data);
622     child->set_is_placeholder(false);
623   }
624 }
625 
626 }  // namespace converter
627 }  // namespace util
628 }  // namespace protobuf
629 }  // namespace google
630