|  | // Copyright 2020 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "src/developer/shell/common/result.h" | 
|  |  | 
|  | #include <lib/syslog/cpp/macros.h> | 
|  |  | 
|  | #include <ostream> | 
|  |  | 
|  | #include "fuchsia/shell/llcpp/fidl.h" | 
|  |  | 
|  | namespace shell::common { | 
|  |  | 
|  | std::unique_ptr<ResultNode> DeserializeResult::Deserialize( | 
|  | const fidl::VectorView<llcpp::fuchsia::shell::Node>& nodes) { | 
|  | FX_DCHECK(!nodes.empty()); | 
|  | return DeserializeNode(nodes, nodes.count()); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<ResultNode> DeserializeResult::DeserializeNode( | 
|  | const fidl::VectorView<llcpp::fuchsia::shell::Node>& nodes, uint64_t node_id) { | 
|  | FX_DCHECK(node_id <= nodes.count()); | 
|  | const llcpp::fuchsia::shell::Node& node = nodes[node_id - 1]; | 
|  | if (node.is_integer_literal()) { | 
|  | return std::make_unique<ResultNodeIntegerLiteral>(node.integer_literal().absolute_value, | 
|  | node.integer_literal().negative); | 
|  | } | 
|  | if (node.is_string_literal()) { | 
|  | return std::make_unique<ResultNodeStringLiteral>(node.string_literal()); | 
|  | } | 
|  | if (node.is_object()) { | 
|  | auto schema = DeserializeSchema(nodes, node.object().object_schema.node_id); | 
|  | if (schema != nullptr) { | 
|  | auto result = std::make_unique<ResultNodeObject>(schema); | 
|  | for (const auto& field_id : node.object().fields) { | 
|  | FX_DCHECK(field_id.file_id == 1U); | 
|  | FX_DCHECK(field_id.node_id <= nodes.count()); | 
|  | const llcpp::fuchsia::shell::Node& field_node = nodes[field_id.node_id - 1]; | 
|  | FX_DCHECK(field_node.is_object_field()); | 
|  | FX_DCHECK(field_node.object_field().object_field_schema.file_id == 1U); | 
|  | auto field_schema = | 
|  | schema->SearchField(field_node.object_field().object_field_schema.node_id); | 
|  | FX_DCHECK(field_schema != nullptr); | 
|  | auto field_value = DeserializeNode(nodes, field_node.object_field().value.node_id); | 
|  | if (field_value != nullptr) { | 
|  | result->AddField(field_schema, std::move(field_value)); | 
|  | } | 
|  | } | 
|  | return result; | 
|  | } | 
|  | } | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | std::shared_ptr<ResultSchema> DeserializeResult::DeserializeSchema( | 
|  | const fidl::VectorView<llcpp::fuchsia::shell::Node>& nodes, uint64_t node_id) { | 
|  | if (node_id == 0) { | 
|  | return nullptr; | 
|  | } | 
|  | auto schema = schemas_.find(node_id); | 
|  | if (schema != schemas_.end()) { | 
|  | return schema->second; | 
|  | } | 
|  | FX_DCHECK(node_id <= nodes.count()); | 
|  | const llcpp::fuchsia::shell::Node& schema_node = nodes[node_id - 1]; | 
|  | if (!schema_node.is_object_schema()) { | 
|  | return nullptr; | 
|  | } | 
|  | auto result = std::make_shared<ResultSchema>(); | 
|  | schemas_.emplace(std::pair(node_id, result)); | 
|  | for (const auto& field : schema_node.object_schema().fields) { | 
|  | FX_DCHECK(field.file_id == 1U); | 
|  | uint64_t field_id = field.node_id; | 
|  | FX_DCHECK(field_id <= nodes.count()); | 
|  | const llcpp::fuchsia::shell::Node& schema_field_node = nodes[field_id - 1]; | 
|  | if (schema_field_node.is_field_schema()) { | 
|  | result->AddField(field_id, schema_field_node.field_schema().name, | 
|  | DeserializeType(nodes, schema_field_node.field_schema().type)); | 
|  | } | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<ResultType> DeserializeResult::DeserializeType( | 
|  | const fidl::VectorView<llcpp::fuchsia::shell::Node>& nodes, | 
|  | const llcpp::fuchsia::shell::ShellType& shell_type) { | 
|  | if (shell_type.is_builtin_type()) { | 
|  | switch (shell_type.builtin_type()) { | 
|  | case llcpp::fuchsia::shell::BuiltinType::UINT64: | 
|  | return std::make_unique<ResultTypeUint64>(); | 
|  | case llcpp::fuchsia::shell::BuiltinType::STRING: | 
|  | return std::make_unique<ResultTypeString>(); | 
|  | default: | 
|  | return nullptr; | 
|  | } | 
|  | } | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | }  // namespace shell::common |