use std::any::Any;
#[derive(Clone, Copy, Debug)]
pub enum TypeInfo {
FullName,
ShortName,
NameFrom(isize),
NameTo(isize),
PartialName(isize, isize),
}
impl TypeInfo {
pub fn of<T: ?Sized>(&self) -> &'static str {
let type_name = std::any::type_name::<T>();
match self {
TypeInfo::FullName => type_name,
TypeInfo::ShortName => Self::partial(type_name, -1, None),
TypeInfo::NameFrom(start) => Self::partial(type_name, *start, None),
TypeInfo::NameTo(end) => Self::partial(type_name, 0, Some(*end)),
TypeInfo::PartialName(start, end) => Self::partial(type_name, *start, Some(*end)),
}
}
fn partial(type_name: &'static str, start: isize, end: Option<isize>) -> &'static str {
let maxlen = type_name.len();
let mut segments = Vec::new();
let mut segment_start = 0; let mut angle_brackets = 0; let mut previous_char = '\0';
for (idx, c) in type_name.char_indices() {
match c {
':' if angle_brackets == 0 => {
if previous_char == ':' {
if segment_start < idx - 1 {
segments.push((segment_start, idx - 1)); }
segment_start = idx + 1; }
}
'<' => angle_brackets += 1,
'>' => angle_brackets -= 1,
_ => {}
}
previous_char = c;
}
if segment_start < maxlen {
segments.push((segment_start, maxlen));
}
let start_pos = segments
.get(if start >= 0 {
start as usize
} else {
segments.len().saturating_sub(start.unsigned_abs())
})
.map_or(0, |&(s, _)| s);
let end_pos = segments
.get(if let Some(end) = end {
if end >= 0 {
end as usize
} else {
segments.len().saturating_sub(end.unsigned_abs())
}
} else {
segments.len() - 1
})
.map_or(maxlen, |&(_, e)| e);
if start_pos >= end_pos {
return "";
}
&type_name[start_pos..end_pos]
}
}
pub trait AnyInfo: Any {
fn type_name(&self) -> &'static str;
fn short_name(&self) -> &'static str;
fn as_any_ref(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
impl<T: Any> AnyInfo for T {
#[inline]
fn type_name(&self) -> &'static str {
TypeInfo::FullName.of::<T>()
}
#[inline]
fn short_name(&self) -> &'static str {
TypeInfo::ShortName.of::<T>()
}
#[inline]
fn as_any_ref(&self) -> &dyn Any {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
pub trait AnyCast: AnyInfo {
#[inline]
fn is<T>(&self) -> bool
where
T: AnyInfo,
{
self.as_any_ref().is::<T>()
}
#[inline]
#[must_use]
fn downcast_ref<T>(&self) -> Option<&T>
where
T: AnyInfo,
{
self.as_any_ref().downcast_ref()
}
#[inline]
#[must_use]
fn downcast_mut<T>(&mut self) -> Option<&mut T>
where
T: AnyInfo,
{
self.as_any_mut().downcast_mut()
}
}
impl<T: ?Sized + AnyInfo> AnyCast for T {}
pub mod action;
pub mod component;
pub mod extension;
pub mod theme;