use core::any::type_name;
use core::ptr::{addr_of, addr_of_mut};
pub trait Named {
fn name(&self) -> &str;
}
#[inline]
#[must_use]
pub fn type_eq<T: ?Sized, U: ?Sized>() -> bool {
type_name::<T>() == type_name::<U>()
}
pub trait MatchName {
fn match_name<T>(&self, name: &str) -> Option<&T>;
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T>;
}
impl MatchName for () {
fn match_name<T>(&self, _name: &str) -> Option<&T> {
None
}
fn match_name_mut<T>(&mut self, _name: &str) -> Option<&mut T> {
None
}
}
impl<Head, Tail> MatchName for (Head, Tail)
where
Head: Named,
Tail: MatchName,
{
fn match_name<T>(&self, name: &str) -> Option<&T> {
if type_eq::<Head, T>() && name == self.0.name() {
unsafe { addr_of!(self.0).cast::<T>().as_ref() }
} else {
self.1.match_name::<T>(name)
}
}
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T> {
if type_eq::<Head, T>() && name == self.0.name() {
unsafe { (addr_of_mut!(self.0).cast::<T>()).as_mut() }
} else {
self.1.match_name_mut::<T>(name)
}
}
}