default_value_objectwriter.cc 23 KB

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