| // 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 TOOLS_FIDL_FIDLC_INCLUDE_FIDL_FLAT_TYPES_H_ |
| #define TOOLS_FIDL_FIDLC_INCLUDE_FIDL_FLAT_TYPES_H_ |
| |
| #include "name.h" |
| #include "object.h" |
| #include "values.h" |
| |
| namespace fidl { |
| namespace flat { |
| |
| struct TypeDecl; |
| |
| struct Type : public Object { |
| virtual ~Type() {} |
| |
| enum struct Kind { |
| kArray, |
| kVector, |
| kString, |
| kHandle, |
| kRequestHandle, |
| kPrimitive, |
| kIdentifier, |
| }; |
| |
| explicit Type(const Name& name, Kind kind, types::Nullability nullability) |
| : name(name), kind(kind), nullability(nullability) {} |
| |
| const Name name; |
| const Kind kind; |
| const types::Nullability nullability; |
| |
| // Returns the nominal resourceness of the type per the FTP-057 definition. |
| // For IdentifierType, can only be called after the Decl has been compiled. |
| types::Resourceness Resourceness() const; |
| |
| // Comparison helper object. |
| class Comparison { |
| public: |
| Comparison() = default; |
| template <class T> |
| Comparison Compare(const T& a, const T& b) const { |
| if (result_ != 0) |
| return Comparison(result_); |
| if (a < b) |
| return Comparison(-1); |
| if (b < a) |
| return Comparison(1); |
| return Comparison(0); |
| } |
| |
| bool IsLessThan() const { return result_ < 0; } |
| |
| private: |
| Comparison(int result) : result_(result) {} |
| |
| const int result_ = 0; |
| }; |
| |
| bool operator<(const Type& other) const { |
| if (kind != other.kind) |
| return kind < other.kind; |
| return Compare(other).IsLessThan(); |
| } |
| |
| // Compare this object against 'other'. |
| // It's guaranteed that this->kind == other.kind. |
| // Return <0 if *this < other, ==0 if *this == other, and >0 if *this > other. |
| // Derived types should override this, but also call this implementation. |
| virtual Comparison Compare(const Type& other) const { |
| assert(kind == other.kind); |
| return Comparison().Compare(nullability, other.nullability); |
| } |
| }; |
| |
| struct ArrayType final : public Type { |
| ArrayType(const Name& name, const Type* element_type, const Size* element_count) |
| : Type(name, Kind::kArray, types::Nullability::kNonnullable), |
| element_type(element_type), |
| element_count(element_count) {} |
| |
| const Type* element_type; |
| const Size* element_count; |
| |
| std::any AcceptAny(VisitorAny* visitor) const override; |
| |
| Comparison Compare(const Type& other) const override { |
| const auto& o = static_cast<const ArrayType&>(other); |
| return Type::Compare(o) |
| .Compare(element_count->value, o.element_count->value) |
| .Compare(*element_type, *o.element_type); |
| } |
| }; |
| |
| struct VectorType final : public Type { |
| VectorType(const Name& name, const Type* element_type, const Size* element_count, |
| types::Nullability nullability) |
| : Type(name, Kind::kVector, nullability), |
| element_type(element_type), |
| element_count(element_count) {} |
| |
| const Type* element_type; |
| const Size* element_count; |
| |
| std::any AcceptAny(VisitorAny* visitor) const override; |
| |
| Comparison Compare(const Type& other) const override { |
| const auto& o = static_cast<const VectorType&>(other); |
| return Type::Compare(o) |
| .Compare(element_count->value, o.element_count->value) |
| .Compare(*element_type, *o.element_type); |
| } |
| }; |
| |
| struct StringType final : public Type { |
| StringType(const Name& name, const Size* max_size, types::Nullability nullability) |
| : Type(name, Kind::kString, nullability), max_size(max_size) {} |
| |
| const Size* max_size; |
| |
| std::any AcceptAny(VisitorAny* visitor) const override; |
| |
| Comparison Compare(const Type& other) const override { |
| const auto& o = static_cast<const StringType&>(other); |
| return Type::Compare(o).Compare(max_size->value, o.max_size->value); |
| } |
| }; |
| |
| struct HandleType final : public Type { |
| HandleType(const Name& name, uint32_t obj_type, types::HandleSubtype subtype, |
| const Constant* rights, types::Nullability nullability) |
| : Type(name, Kind::kHandle, nullability), |
| obj_type(obj_type), |
| subtype(subtype), |
| rights(rights) {} |
| |
| const uint32_t obj_type; |
| const types::HandleSubtype subtype; |
| const Constant* rights; |
| |
| std::any AcceptAny(VisitorAny* visitor) const override; |
| |
| Comparison Compare(const Type& other) const override { |
| const auto& other_handle_type = *static_cast<const HandleType*>(&other); |
| auto rights_val = |
| static_cast<const flat::NumericConstantValue<types::Rights>&>(rights->Value()); |
| auto other_rights_val = static_cast<const flat::NumericConstantValue<types::Rights>&>( |
| other_handle_type.rights->Value()); |
| return Type::Compare(other_handle_type) |
| .Compare(subtype, other_handle_type.subtype) |
| .Compare(rights_val, other_rights_val); |
| } |
| }; |
| |
| struct PrimitiveType final : public Type { |
| explicit PrimitiveType(const Name& name, types::PrimitiveSubtype subtype) |
| : Type(name, Kind::kPrimitive, types::Nullability::kNonnullable), subtype(subtype) {} |
| |
| types::PrimitiveSubtype subtype; |
| |
| std::any AcceptAny(VisitorAny* visitor) const override; |
| |
| Comparison Compare(const Type& other) const override { |
| const auto& o = static_cast<const PrimitiveType&>(other); |
| return Type::Compare(o).Compare(subtype, o.subtype); |
| } |
| |
| private: |
| static uint32_t SubtypeSize(types::PrimitiveSubtype subtype); |
| }; |
| |
| struct IdentifierType final : public Type { |
| IdentifierType(const Name& name, types::Nullability nullability, const TypeDecl* type_decl) |
| : Type(name, Kind::kIdentifier, nullability), type_decl(type_decl) {} |
| |
| const TypeDecl* type_decl; |
| |
| std::any AcceptAny(VisitorAny* visitor) const override; |
| |
| Comparison Compare(const Type& other) const override { |
| const auto& o = static_cast<const IdentifierType&>(other); |
| return Type::Compare(o).Compare(name, o.name); |
| } |
| }; |
| |
| // TODO(fxbug.dev/43803) Add required and optional rights. |
| struct RequestHandleType final : public Type { |
| RequestHandleType(const Name& name, const IdentifierType* protocol_type, |
| types::Nullability nullability) |
| : Type(name, Kind::kRequestHandle, nullability), protocol_type(protocol_type) {} |
| |
| const IdentifierType* protocol_type; |
| |
| std::any AcceptAny(VisitorAny* visitor) const override; |
| |
| Comparison Compare(const Type& other) const override { |
| const auto& o = static_cast<const RequestHandleType&>(other); |
| return Type::Compare(o).Compare(*protocol_type, *o.protocol_type); |
| } |
| }; |
| |
| } // namespace flat |
| } // namespace fidl |
| |
| #endif // TOOLS_FIDL_FIDLC_INCLUDE_FIDL_FLAT_TYPES_H_ |