| // 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. |
| |
| #ifndef SRC_DEVELOPER_SHELL_COMMON_RESULT_H_ |
| #define SRC_DEVELOPER_SHELL_COMMON_RESULT_H_ |
| |
| #include <lib/fidl/llcpp/vector_view.h> |
| |
| #include <cstdint> |
| #include <map> |
| #include <memory> |
| #include <ostream> |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| #include "fuchsia/shell/llcpp/fidl.h" |
| |
| namespace shell::common { |
| |
| // Base class for all the types. |
| class ResultType { |
| public: |
| ResultType() = default; |
| virtual ~ResultType() = default; |
| |
| // Dumps the type. |
| virtual void Dump(std::ostream& os, const char* separator) const {} |
| }; |
| |
| class ResultTypeUint64 : public ResultType { |
| public: |
| ResultTypeUint64() = default; |
| |
| void Dump(std::ostream& os, const char* separator) const override { os << separator << "uint64"; } |
| }; |
| |
| class ResultTypeString : public ResultType { |
| public: |
| ResultTypeString() = default; |
| |
| void Dump(std::ostream& os, const char* separator) const override { os << separator << "string"; } |
| }; |
| |
| // Defines a field for a result object schema. |
| class ResultSchemaField { |
| public: |
| ResultSchemaField(uint64_t node_id, const fidl::StringView& name, |
| std::unique_ptr<ResultType> type) |
| : node_id_(node_id), name_(name.data(), name.size()), type_(std::move(type)) {} |
| |
| uint64_t node_id() const { return node_id_; } |
| const std::string& name() const { return name_; } |
| const ResultType* type() const { return type_.get(); } |
| |
| private: |
| const uint64_t node_id_; |
| const std::string name_; |
| std::unique_ptr<ResultType> type_; |
| }; |
| |
| // Defines an object shema for a result. |
| class ResultSchema { |
| public: |
| ResultSchema() = default; |
| |
| void AddField(uint64_t node_id, const fidl::StringView& name, std::unique_ptr<ResultType> type) { |
| fields_.emplace_back(std::make_shared<ResultSchemaField>(node_id, name, std::move(type))); |
| } |
| |
| std::shared_ptr<ResultSchemaField> SearchField(uint64_t field_id) const { |
| for (const auto& field : fields_) { |
| if (field->node_id() == field_id) { |
| return field; |
| } |
| } |
| return nullptr; |
| } |
| |
| private: |
| std::vector<std::shared_ptr<ResultSchemaField>> fields_; |
| }; |
| |
| // Defines an object type for a result. |
| class ResultTypeObject : public ResultType { |
| public: |
| ResultTypeObject(std::shared_ptr<ResultSchema> schema) : schema_(schema) {} |
| |
| private: |
| std::shared_ptr<ResultSchema> schema_; |
| }; |
| |
| // Base class for a result. |
| class ResultNode { |
| public: |
| ResultNode() = default; |
| virtual ~ResultNode() = default; |
| |
| // Dumps the result. |
| virtual void Dump(std::ostream& os) const = 0; |
| }; |
| |
| // Defines an integer literal result. |
| class ResultNodeIntegerLiteral : public ResultNode { |
| public: |
| ResultNodeIntegerLiteral(const fidl::VectorView<uint64_t>& absolute_value, bool negative) |
| : negative_(negative) { |
| for (auto value : absolute_value) { |
| absolute_value_.push_back(value); |
| } |
| } |
| |
| void Dump(std::ostream& os) const override { |
| if (negative_) { |
| os << '-'; |
| } |
| if (absolute_value_.empty()) { |
| os << '0'; |
| } else if (absolute_value_.size() == 1) { |
| os << absolute_value_[0]; |
| } else { |
| os << "???"; |
| } |
| } |
| |
| private: |
| std::vector<uint64_t> absolute_value_; |
| const bool negative_; |
| }; |
| |
| // Define a string literal result. |
| class ResultNodeStringLiteral : public ResultNode { |
| public: |
| ResultNodeStringLiteral(const fidl::StringView& string) : string_(string.data(), string.size()) {} |
| |
| void Dump(std::ostream& os) const override { os << '"' << string_ << '"'; } |
| |
| private: |
| const std::string string_; |
| }; |
| |
| // Defines a field for an object result. |
| class ResultNodeObjectField { |
| public: |
| ResultNodeObjectField(std::shared_ptr<ResultSchemaField> field, std::unique_ptr<ResultNode> value) |
| : field_(field), value_(std::move(value)) {} |
| |
| void Dump(std::ostream& os) const { |
| os << field_->name() << ": "; |
| |
| if (field_->type() != nullptr) { |
| field_->type()->Dump(os, ""); |
| os << "("; |
| value_->Dump(os); |
| os << ")"; |
| } else { |
| value_->Dump(os); |
| } |
| } |
| |
| private: |
| std::shared_ptr<ResultSchemaField> field_; |
| std::unique_ptr<ResultNode> value_; |
| }; |
| |
| // Defines an object result. |
| class ResultNodeObject : public ResultNode { |
| public: |
| ResultNodeObject(std::shared_ptr<ResultSchema> schema) : schema_(schema) {} |
| |
| void AddField(std::shared_ptr<ResultSchemaField> field, std::unique_ptr<ResultNode> value) { |
| fields_.emplace_back(std::make_unique<ResultNodeObjectField>(field, std::move(value))); |
| } |
| |
| void Dump(std::ostream& os) const override { |
| os << '{'; |
| const char* separator = ""; |
| for (const auto& field : fields_) { |
| os << separator; |
| field->Dump(os); |
| separator = ", "; |
| } |
| os << '}'; |
| } |
| |
| private: |
| std::shared_ptr<ResultSchema> schema_; |
| std::vector<std::unique_ptr<ResultNodeObjectField>> fields_; |
| }; |
| |
| // Helper for a result deserialization from a vector of nodes. |
| class DeserializeResult { |
| public: |
| DeserializeResult() = default; |
| |
| // Deserializes a result from a vector of nodes. |
| std::unique_ptr<ResultNode> Deserialize( |
| const fidl::VectorView<llcpp::fuchsia::shell::Node>& nodes); |
| |
| // Deserializes a node (value). |
| std::unique_ptr<ResultNode> DeserializeNode( |
| const fidl::VectorView<llcpp::fuchsia::shell::Node>& nodes, uint64_t node_id); |
| |
| // Deserializes an object schema. |
| std::shared_ptr<ResultSchema> DeserializeSchema( |
| const fidl::VectorView<llcpp::fuchsia::shell::Node>& nodes, uint64_t node_id); |
| |
| // Deserializes a type. |
| std::unique_ptr<ResultType> DeserializeType( |
| const fidl::VectorView<llcpp::fuchsia::shell::Node>& nodes, |
| const llcpp::fuchsia::shell::ShellType& shell_type); |
| |
| private: |
| // All the schema which have already been deserialized. |
| std::map<uint64_t, std::shared_ptr<ResultSchema>> schemas_; |
| }; |
| |
| } // namespace shell::common |
| |
| #endif // SRC_DEVELOPER_SHELL_COMMON_RESULT_H_ |