use crate::{
ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo,
TypePath, TypePathTable,
};
use std::any::{Any, TypeId};
use std::fmt::Debug;
#[diagnostic::on_unimplemented(
message = "`{Self}` can not provide type information through reflection",
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
)]
pub trait Typed: Reflect + TypePath {
fn type_info() -> &'static TypeInfo;
}
#[derive(Debug, Clone)]
pub enum TypeInfo {
Struct(StructInfo),
TupleStruct(TupleStructInfo),
Tuple(TupleInfo),
List(ListInfo),
Array(ArrayInfo),
Map(MapInfo),
Enum(EnumInfo),
Value(ValueInfo),
}
impl TypeInfo {
pub fn type_id(&self) -> TypeId {
match self {
Self::Struct(info) => info.type_id(),
Self::TupleStruct(info) => info.type_id(),
Self::Tuple(info) => info.type_id(),
Self::List(info) => info.type_id(),
Self::Array(info) => info.type_id(),
Self::Map(info) => info.type_id(),
Self::Enum(info) => info.type_id(),
Self::Value(info) => info.type_id(),
}
}
pub fn type_path_table(&self) -> &TypePathTable {
match self {
Self::Struct(info) => info.type_path_table(),
Self::TupleStruct(info) => info.type_path_table(),
Self::Tuple(info) => info.type_path_table(),
Self::List(info) => info.type_path_table(),
Self::Array(info) => info.type_path_table(),
Self::Map(info) => info.type_path_table(),
Self::Enum(info) => info.type_path_table(),
Self::Value(info) => info.type_path_table(),
}
}
pub fn type_path(&self) -> &'static str {
self.type_path_table().path()
}
pub fn is<T: Any>(&self) -> bool {
TypeId::of::<T>() == self.type_id()
}
#[cfg(feature = "documentation")]
pub fn docs(&self) -> Option<&str> {
match self {
Self::Struct(info) => info.docs(),
Self::TupleStruct(info) => info.docs(),
Self::Tuple(info) => info.docs(),
Self::List(info) => info.docs(),
Self::Array(info) => info.docs(),
Self::Map(info) => info.docs(),
Self::Enum(info) => info.docs(),
Self::Value(info) => info.docs(),
}
}
}
#[derive(Debug, Clone)]
pub struct ValueInfo {
type_path: TypePathTable,
type_id: TypeId,
#[cfg(feature = "documentation")]
docs: Option<&'static str>,
}
impl ValueInfo {
pub fn new<T: Reflect + TypePath + ?Sized>() -> Self {
Self {
type_path: TypePathTable::of::<T>(),
type_id: TypeId::of::<T>(),
#[cfg(feature = "documentation")]
docs: None,
}
}
#[cfg(feature = "documentation")]
pub fn with_docs(self, doc: Option<&'static str>) -> Self {
Self { docs: doc, ..self }
}
pub fn type_path_table(&self) -> &TypePathTable {
&self.type_path
}
pub fn type_path(&self) -> &'static str {
self.type_path_table().path()
}
pub fn type_id(&self) -> TypeId {
self.type_id
}
pub fn is<T: Any>(&self) -> bool {
TypeId::of::<T>() == self.type_id
}
#[cfg(feature = "documentation")]
pub fn docs(&self) -> Option<&'static str> {
self.docs
}
}