blob: 217bbe532b2aa7300f3bdf57f4edd7ea46323f9a [file] [log] [blame]
// 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_