| // Copyright 2019 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_LIB_FIDL_CODEC_WIRE_TYPES_H_ |
| #define SRC_LIB_FIDL_CODEC_WIRE_TYPES_H_ |
| |
| #include <lib/fit/function.h> |
| #include <zircon/types.h> |
| |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| #include <rapidjson/document.h> |
| |
| #include "src/lib/fidl_codec/memory_helpers.h" |
| #include "src/lib/fidl_codec/message_decoder.h" |
| #include "src/lib/fidl_codec/wire_object.h" |
| |
| namespace fidl_codec { |
| |
| class LibraryLoader; |
| class StructType; |
| class TypeVisitor; |
| |
| // A FIDL type. Provides methods for generating instances of this type. |
| class Type { |
| friend class InterfaceMethodParameter; |
| friend class Library; |
| |
| public: |
| Type() = default; |
| virtual ~Type() = default; |
| |
| // Returns a detailed representation of the type. |
| std::string ToString(bool expand = false) const; |
| |
| virtual const StructType* AsStructType() const { return nullptr; } |
| |
| // Returns true if the type is a ArrayType. |
| virtual bool IsArray() const { return false; } |
| |
| // Returns a readable representation of the type. |
| virtual std::string Name() const = 0; |
| |
| // Returns the size of this type when embedded in another object. |
| virtual size_t InlineSize() const = 0; |
| |
| // Whether this is a nullable type. |
| virtual bool Nullable() const { return false; } |
| |
| // For vectors and arrays, give the type of the components (members). |
| virtual const Type* GetComponentType() const { return nullptr; } |
| |
| // Decodes the type's inline part. It generates a Value and, eventually, |
| // registers the field for further decoding (secondary objects). |
| virtual std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const = 0; |
| |
| // Pretty prints the value for this type. This is used to print numerical values. |
| virtual void PrettyPrint(const Value* value, PrettyPrinter& printer) const; |
| |
| // Use a visitor on this value; |
| virtual void Visit(TypeVisitor* visitor) const = 0; |
| |
| // Gets a Type object representing the |type_name|. |type| is a string that |
| // represents a scalar type (e.g., "float64", "uint32"). |
| static std::unique_ptr<Type> ScalarTypeFromName(const std::string& type_name); |
| |
| // Gets a Type object representing the |type|. |type| is a JSON object with a |
| // "subtype" field that represents a scalar type (e.g., "float64", "uint32") |
| static std::unique_ptr<Type> TypeFromPrimitive(const rapidjson::Value& type); |
| |
| // Gets a Type object representing the |type|. |type| is a JSON object a |
| // field "kind" that states the type. "kind" is an identifier |
| // (e.g.,"foo.bar/Baz"). |loader| is the set of libraries to use to lookup |
| // that identifier. |
| static std::unique_ptr<Type> TypeFromIdentifier(LibraryLoader* loader, |
| const rapidjson::Value& type); |
| |
| // Gets a Type object representing the |type|. |type| is a JSON object a |
| // field "kind" that states the type (e.g., "array", "vector", "foo.bar/Baz"). |
| // |loader| is the set of libraries to use to find types that need to be given |
| // by identifier (e.g., "foo.bar/Baz"). |
| static std::unique_ptr<Type> GetType(LibraryLoader* loader, const rapidjson::Value& type); |
| |
| Type& operator=(const Type& other) = default; |
| Type(const Type& other) = default; |
| }; |
| |
| // An instance of this class is created when the system can't determine the real |
| // class (e.g., in cases of corrupted metadata). |
| class InvalidType : public Type { |
| public: |
| InvalidType() = default; |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| }; |
| |
| class BoolType : public Type { |
| public: |
| BoolType() = default; |
| |
| std::string Name() const override { return "bool"; } |
| |
| size_t InlineSize() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| }; |
| |
| // A generic type that can be used for any integer numeric value that corresponds to a |
| // C++ integral value. |
| template <typename T> |
| class IntegralType : public Type { |
| static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, |
| "IntegralType can only be used for integers"); |
| |
| public: |
| IntegralType() = default; |
| |
| size_t InlineSize() const override { return sizeof(T); } |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override { |
| auto got = decoder->GetAddress(offset, sizeof(T)); |
| if (got == nullptr) { |
| return std::make_unique<InvalidValue>(); |
| } |
| T value = *reinterpret_cast<const T*>(got); |
| if (value < 0) { |
| // Sign-extend to 64 bits so the cast to uint64_t is a no-op. |
| int64_t tmp = value; |
| // Cast to uint64 before the negation to avoid a int64 overflow (-min_int64 can't be |
| // represented with a int64). |
| return std::make_unique<IntegerValue>(-static_cast<uint64_t>(tmp), true); |
| } |
| return std::make_unique<IntegerValue>(value, false); |
| } |
| }; |
| |
| class Int8Type : public IntegralType<int8_t> { |
| public: |
| enum class Kind { kDecimal }; |
| |
| explicit Int8Type(Kind kind = Kind::kDecimal) : kind_(kind) {} |
| |
| std::string Name() const override; |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| Kind kind_; |
| }; |
| |
| class Int16Type : public IntegralType<int16_t> { |
| public: |
| enum class Kind { kDecimal }; |
| |
| explicit Int16Type(Kind kind = Kind::kDecimal) : kind_(kind) {} |
| |
| std::string Name() const override; |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| Kind kind_; |
| }; |
| |
| class Int32Type : public IntegralType<int32_t> { |
| public: |
| enum class Kind { kDecimal }; |
| |
| explicit Int32Type(Kind kind = Kind::kDecimal) : kind_(kind) {} |
| |
| std::string Name() const override; |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| Kind kind_; |
| }; |
| |
| class Int64Type : public IntegralType<int64_t> { |
| public: |
| enum class Kind { kDecimal, kTime }; |
| |
| explicit Int64Type(Kind kind = Kind::kDecimal) : kind_(kind) {} |
| |
| std::string Name() const override; |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| Kind kind_; |
| }; |
| |
| class Uint8Type : public IntegralType<uint8_t> { |
| public: |
| enum class Kind { kDecimal, kHexaDecimal }; |
| |
| explicit Uint8Type(Kind kind = Kind::kDecimal) : kind_(kind) {} |
| |
| std::string Name() const override; |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| Kind kind_; |
| }; |
| |
| class Uint16Type : public IntegralType<uint16_t> { |
| public: |
| enum class Kind { kDecimal, kHexaDecimal }; |
| |
| explicit Uint16Type(Kind kind = Kind::kDecimal) : kind_(kind) {} |
| |
| std::string Name() const override; |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| Kind kind_; |
| }; |
| |
| class Uint32Type : public IntegralType<uint32_t> { |
| public: |
| enum class Kind { kDecimal, kHexaDecimal }; |
| |
| explicit Uint32Type(Kind kind = Kind::kDecimal) : kind_(kind) {} |
| |
| std::string Name() const override; |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| Kind kind_; |
| }; |
| |
| class Uint64Type : public IntegralType<uint64_t> { |
| public: |
| enum class Kind { kDecimal, kHexaDecimal }; |
| |
| explicit Uint64Type(Kind kind = Kind::kDecimal) : kind_(kind) {} |
| |
| std::string Name() const override; |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| Kind kind_; |
| }; |
| |
| // A generic type that can be used for any numeric value that corresponds to a |
| // C++ arithmetic value. |
| template <typename T> |
| class NumericType : public Type { |
| static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, |
| "NumericType can only be used for numerics"); |
| |
| public: |
| size_t InlineSize() const override { return sizeof(T); } |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override { |
| auto got = decoder->GetAddress(offset, sizeof(T)); |
| if (got == nullptr) { |
| return std::make_unique<InvalidValue>(); |
| } |
| return std::make_unique<DoubleValue>(*reinterpret_cast<const T*>(got)); |
| } |
| |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override { |
| double result; |
| if (!value->GetDoubleValue(&result)) { |
| printer << Red << "invalid" << ResetColor; |
| } else { |
| printer << Blue << std::to_string(result) << ResetColor; |
| } |
| } |
| }; |
| |
| class Float32Type : public NumericType<float> { |
| public: |
| Float32Type() = default; |
| std::string Name() const override; |
| void Visit(TypeVisitor* visitor) const override; |
| }; |
| |
| class Float64Type : public NumericType<double> { |
| public: |
| Float64Type() = default; |
| std::string Name() const override; |
| void Visit(TypeVisitor* visitor) const override; |
| }; |
| |
| class StringType : public Type { |
| public: |
| StringType() = default; |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| bool Nullable() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| }; |
| |
| class HandleType : public Type { |
| public: |
| HandleType() = default; |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| }; |
| |
| class EnumType : public Type { |
| public: |
| explicit EnumType(const Enum& enum_definition) : enum_definition_(enum_definition) {} |
| |
| const Enum& enum_definition() const { return enum_definition_; } |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| const Enum& enum_definition_; |
| }; |
| |
| class BitsType : public Type { |
| public: |
| explicit BitsType(const Bits& bits_definition) : bits_definition_(bits_definition) {} |
| |
| const Bits& bits_definition() const { return bits_definition_; } |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void PrettyPrint(const Value* value, PrettyPrinter& printer) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| const Bits& bits_definition_; |
| }; |
| |
| class UnionType : public Type { |
| public: |
| UnionType(const Union& union_definition, bool nullable) |
| : union_definition_(union_definition), nullable_(nullable) {} |
| |
| const Union& union_definition() const { return union_definition_; } |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| bool Nullable() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| const Union& union_definition_; |
| const bool nullable_; |
| }; |
| |
| class StructType : public Type { |
| public: |
| StructType(const Struct& struct_definition, bool nullable) |
| : struct_definition_(struct_definition), nullable_(nullable) {} |
| |
| const Struct& struct_definition() const { return struct_definition_; } |
| |
| const StructType* AsStructType() const override { return this; } |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| bool Nullable() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| const Struct& struct_definition_; |
| const bool nullable_; |
| }; |
| |
| class ElementSequenceType : public Type { |
| public: |
| explicit ElementSequenceType(std::unique_ptr<Type> component_type) |
| : component_type_(std::move(component_type)) { |
| FXL_DCHECK(component_type_.get() != nullptr); |
| } |
| |
| const Type* component_type() const { return component_type_.get(); } |
| |
| const Type* GetComponentType() const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| |
| protected: |
| std::unique_ptr<Type> component_type_; |
| }; |
| |
| class ArrayType : public ElementSequenceType { |
| public: |
| ArrayType(std::unique_ptr<Type> component_type, uint32_t count) |
| : ElementSequenceType(std::move(component_type)), count_(count) {} |
| |
| uint32_t count() const { return count_; } |
| |
| bool IsArray() const override; |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| uint32_t count_; |
| }; |
| |
| class VectorType : public ElementSequenceType { |
| public: |
| explicit VectorType(std::unique_ptr<Type> component_type) |
| : ElementSequenceType(std::move(component_type)) {} |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| bool Nullable() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| }; |
| |
| class TableType : public Type { |
| public: |
| explicit TableType(const Table& table_definition) : table_definition_(table_definition) {} |
| |
| const Table& table_definition() const { return table_definition_; } |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| |
| private: |
| const Table& table_definition_; |
| }; |
| |
| class FidlMessageType : public Type { |
| public: |
| FidlMessageType() = default; |
| |
| std::string Name() const override; |
| |
| size_t InlineSize() const override; |
| |
| std::unique_ptr<Value> Decode(MessageDecoder* decoder, uint64_t offset) const override; |
| |
| void Visit(TypeVisitor* visitor) const override; |
| }; |
| |
| } // namespace fidl_codec |
| |
| #endif // SRC_LIB_FIDL_CODEC_WIRE_TYPES_H_ |