use core::fmt;
#[diagnostic::on_unimplemented(
message = "`{Self}` does not implement `TypePath` so cannot provide static type path information",
note = "consider annotating `{Self}` with `#[derive(Reflect)]` or `#[derive(TypePath)]`"
)]
pub trait TypePath: 'static {
fn type_path() -> &'static str;
fn short_type_path() -> &'static str;
fn type_ident() -> Option<&'static str> {
None
}
fn crate_name() -> Option<&'static str> {
None
}
fn module_path() -> Option<&'static str> {
None
}
}
#[diagnostic::on_unimplemented(
message = "`{Self}` does not implement `TypePath` so cannot provide dynamic type path information",
note = "consider annotating `{Self}` with `#[derive(Reflect)]` or `#[derive(TypePath)]`"
)]
pub trait DynamicTypePath {
fn reflect_type_path(&self) -> &str;
fn reflect_short_type_path(&self) -> &str;
fn reflect_type_ident(&self) -> Option<&str>;
fn reflect_crate_name(&self) -> Option<&str>;
fn reflect_module_path(&self) -> Option<&str>;
}
impl<T: TypePath> DynamicTypePath for T {
#[inline]
fn reflect_type_path(&self) -> &str {
Self::type_path()
}
#[inline]
fn reflect_short_type_path(&self) -> &str {
Self::short_type_path()
}
#[inline]
fn reflect_type_ident(&self) -> Option<&str> {
Self::type_ident()
}
#[inline]
fn reflect_crate_name(&self) -> Option<&str> {
Self::crate_name()
}
#[inline]
fn reflect_module_path(&self) -> Option<&str> {
Self::module_path()
}
}
#[derive(Clone, Copy)]
pub struct TypePathTable {
type_path: &'static str,
short_type_path: fn() -> &'static str,
type_ident: fn() -> Option<&'static str>,
crate_name: fn() -> Option<&'static str>,
module_path: fn() -> Option<&'static str>,
}
impl fmt::Debug for TypePathTable {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TypePathVtable")
.field("type_path", &self.type_path)
.field("short_type_path", &(self.short_type_path)())
.field("type_ident", &(self.type_ident)())
.field("crate_name", &(self.crate_name)())
.field("module_path", &(self.module_path)())
.finish()
}
}
impl TypePathTable {
pub fn of<T: TypePath + ?Sized>() -> Self {
Self {
type_path: T::type_path(),
short_type_path: T::short_type_path,
type_ident: T::type_ident,
crate_name: T::crate_name,
module_path: T::module_path,
}
}
pub fn path(&self) -> &'static str {
self.type_path
}
pub fn short_path(&self) -> &'static str {
(self.short_type_path)()
}
pub fn ident(&self) -> Option<&'static str> {
(self.type_ident)()
}
pub fn crate_name(&self) -> Option<&'static str> {
(self.crate_name)()
}
pub fn module_path(&self) -> Option<&'static str> {
(self.module_path)()
}
}