#![doc = include_str!("../README.md")]
mod type_name;
pub use type_name::type_name;
pub use type_name::type_name_of_val;
#[doc(hidden)]
#[macro_export]
macro_rules! __with_cache {
($expr:expr) => {{
use std::cell::OnceCell;
thread_local!(static CACHE: OnceCell<&'static str> = OnceCell::new());
CACHE.with(|cell| *cell.get_or_init(|| {
let result = $expr;
Box::leak(result.into_boxed_str())
}))
}};
}
#[macro_export]
macro_rules! of_var {
($ident:ident) => {{
let _ = &$ident;
stringify!($ident)
}};
}
#[macro_export]
macro_rules! of_function {
($ident:ident) => {{
let _ = &$ident;
stringify!($ident)
}};
($ident:ident ::<..>) => {{
#[allow(unused)] use $ident;
stringify!($ident)
}};
($ident:ident ::<$($arg:ty),*>) => {{
let _ = &$ident::<$($arg),*>;
$crate::__with_cache!(
format!(
"{}::<{}>",
stringify!($ident),
vec![$($crate::type_name::<$arg>()),*].join(", ")))
}};
}
#[macro_export]
macro_rules! of_type {
(Self) => {{
$crate::type_name::<Self>()
}};
($ty:ident) => {{
stringify!($ty)
}};
($ty:ty) => {{
$crate::type_name::<$ty>()
}};
}
#[macro_export]
macro_rules! of_field {
(Self:: $field:ident) => {{
let _ = |obj: Self| { let _ = &obj.$field; };
$crate::__with_cache!(
format!("{}::{}", $crate::type_name::<Self>(), stringify!($field)))
}};
($ty:ident :: $field:ident) => {{
let _ = |obj: $ty| { let _ = &obj.$field; };
concat!(stringify!($ty), "::", stringify!($field))
}};
(<$ty:ty> :: $field:ident) => {{
let _ = |obj: $ty| { let _ = &obj.$field; };
$crate::__with_cache!(
format!("<{}>::{}", $crate::type_name::<$ty>(), stringify!($field)))
}};
}
#[macro_export]
macro_rules! of_method {
(Self:: $method:ident) => {{
let _ = &Self::$method;
$crate::__with_cache!(
format!("{}::{}", $crate::type_name::<Self>(), stringify!($method)))
}};
($ty:ident :: $method:ident) => {{
let _ = &$ty::$method;
concat!(stringify!($ty), "::", stringify!($method))
}};
($ty:ident :: $method:ident ::<$($arg:ty),*>) => {{
let _ = &$ty::$method::<$($arg),*>;
$crate::__with_cache!(
format!(
"{}::{}::<{}>",
$crate::type_name::<$ty>(),
stringify!($method),
vec![$($crate::type_name::<$arg>()),*].join(", ")))
}};
(<$ty:ty> :: $method:ident) => {{
let _ = &<$ty>::$method;
$crate::__with_cache!(
format!("<{}>::{}", $crate::type_name::<$ty>(), stringify!($method)))
}};
(<$ty:ty> :: $method:ident ::<$($arg:ty),*>) => {{
let _ = &<$ty>::$method::<$($arg),*>;
$crate::__with_cache!(
format!(
"<{}>::{}::<{}>",
$crate::type_name::<$ty>(),
stringify!($method),
vec![$($crate::type_name::<$arg>()),*].join(", ")))
}};
}
#[macro_export]
macro_rules! of_variant {
(Self:: $variant:ident) => {{
let _ = |obj: Self| match obj { Self::$variant => {}, _ => {} };
$crate::__with_cache!(
format!("{}::{}", $crate::type_name::<Self>(), stringify!($variant)))
}};
(Self:: $variant:ident (..)) => {{
let _ = |obj: Self| match obj { Self::$variant(..) => {}, _ => {} };
$crate::__with_cache!(
format!("{}::{}", $crate::type_name::<Self>(), stringify!($variant)))
}};
(Self:: $variant:ident {..}) => {{
let _ = |obj: Self| match obj { Self::$variant { .. } => {}, _ => {} };
$crate::__with_cache!(
format!("{}::{}", $crate::type_name::<Self>(), stringify!($variant)))
}};
($ty:ident :: $variant:ident) => {{
let _ = |obj: $ty| match obj { $ty::$variant => {}, _ => {} };
concat!(stringify!($ty), "::", stringify!($variant))
}};
($ty:ident :: $variant:ident (..)) => {{
let _ = |obj: $ty| match obj { $ty::$variant(..) => {}, _ => {} };
concat!(stringify!($ty), "::", stringify!($variant))
}};
($ty:ident :: $variant:ident {..}) => {{
let _ = |obj: $ty| match obj { $ty::$variant { .. } => {}, _ => {} };
concat!(stringify!($ty), "::", stringify!($variant))
}};
(<$ty:ty> :: $variant:ident) => {{
let _ = |obj: $ty| match obj { <$ty>::$variant => {}, _ => {} };
$crate::__with_cache!(
format!("<{}>::{}", $crate::type_name::<$ty>(), stringify!($variant)))
}};
(<$ty:ty> :: $variant:ident (..)) => {{
let _ = |obj: $ty| match obj { <$ty>::$variant(..) => {}, _ => {} };
$crate::__with_cache!(
format!("<{}>::{}", $crate::type_name::<$ty>(), stringify!($variant)))
}};
(<$ty:ty> :: $variant:ident {..}) => {{
let _ = |obj: $ty| match obj { <$ty>::$variant { .. } => {}, _ => {} };
$crate::__with_cache!(
format!("<{}>::{}", $crate::type_name::<$ty>(), stringify!($variant)))
}};
}
#[test] fn test_self() {
struct MyStruct {
my_field: u32,
}
impl MyStruct {
fn my_method<T>(&self) {}
fn test(&self) {
assert_eq!(of_type!(Self), "MyStruct");
assert_eq!(of_field!(Self::my_field), "MyStruct::my_field");
assert_eq!(of_method!(Self::my_method::<u32>), "MyStruct::my_method::<u32>");
}
}
let my_struct = MyStruct { my_field: 42 };
my_struct.test();
}