use std::any::{type_name, Any as StdAny, TypeId}; use std::fmt; pub type Variant = dyn Any; pub type Dynamic = Box; pub trait Any: StdAny { fn type_id(&self) -> TypeId; fn type_name(&self) -> String; fn into_dynamic(&self) -> Dynamic; /// This type may only be implemented by `rhai`. #[doc(hidden)] fn _closed(&self) -> _Private; } impl Any for T where T: Clone + StdAny + ?Sized, { #[inline] fn type_id(&self) -> TypeId { TypeId::of::() } fn type_name(&self) -> String { type_name::().to_string() } #[inline] fn into_dynamic(&self) -> Dynamic { Box::new(self.clone()) } fn _closed(&self) -> _Private { _Private } } impl Variant { //#[inline] // fn into_dynamic(&self) -> Box { // Any::into_dynamic(self) // } #[inline] pub fn is(&self) -> bool { let t = TypeId::of::(); let boxed = ::type_id(self); t == boxed } #[inline] pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { unsafe { Some(&*(self as *const Variant as *const T)) } } else { None } } #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { unsafe { Some(&mut *(self as *mut Variant as *mut T)) } } else { None } } } impl Clone for Dynamic { fn clone(&self) -> Self { Any::into_dynamic(self.as_ref()) } } impl fmt::Debug for Variant { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("?") } } pub trait AnyExt: Sized { fn downcast(self) -> Result, Self>; } impl AnyExt for Dynamic { fn downcast(self) -> Result, Self> { if self.is::() { unsafe { let raw: *mut Variant = Box::into_raw(self); Ok(Box::from_raw(raw as *mut T)) } } else { Err(self) } } } /// Private type which ensures that `rhai::Any` can only /// be implemented by this crate. #[doc(hidden)] pub struct _Private;