1 #[derive(Clone)] 2 pub(crate) struct AnyValue { 3 inner: std::sync::Arc<dyn std::any::Any + Send + Sync + 'static>, 4 // While we can extract `TypeId` from `inner`, the debug repr is of a number, so let's track 5 // the type_name in debug builds. 6 id: AnyValueId, 7 } 8 9 impl AnyValue { new<V: std::any::Any + Clone + Send + Sync + 'static>(inner: V) -> Self10 pub(crate) fn new<V: std::any::Any + Clone + Send + Sync + 'static>(inner: V) -> Self { 11 let id = AnyValueId::of::<V>(); 12 let inner = std::sync::Arc::new(inner); 13 Self { inner, id } 14 } 15 downcast_ref<T: std::any::Any + Clone + Send + Sync + 'static>( &self, ) -> Option<&T>16 pub(crate) fn downcast_ref<T: std::any::Any + Clone + Send + Sync + 'static>( 17 &self, 18 ) -> Option<&T> { 19 self.inner.downcast_ref::<T>() 20 } 21 downcast_into<T: std::any::Any + Clone + Send + Sync>(self) -> Result<T, Self>22 pub(crate) fn downcast_into<T: std::any::Any + Clone + Send + Sync>(self) -> Result<T, Self> { 23 let id = self.id; 24 let value = 25 ok!(std::sync::Arc::downcast::<T>(self.inner).map_err(|inner| Self { inner, id })); 26 let value = std::sync::Arc::try_unwrap(value).unwrap_or_else(|arc| (*arc).clone()); 27 Ok(value) 28 } 29 type_id(&self) -> AnyValueId30 pub(crate) fn type_id(&self) -> AnyValueId { 31 self.id 32 } 33 } 34 35 impl std::fmt::Debug for AnyValue { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 37 f.debug_struct("AnyValue").field("inner", &self.id).finish() 38 } 39 } 40 41 #[derive(Copy, Clone)] 42 pub struct AnyValueId { 43 type_id: std::any::TypeId, 44 #[cfg(debug_assertions)] 45 type_name: &'static str, 46 } 47 48 impl AnyValueId { of<A: ?Sized + 'static>() -> Self49 pub(crate) fn of<A: ?Sized + 'static>() -> Self { 50 Self { 51 type_id: std::any::TypeId::of::<A>(), 52 #[cfg(debug_assertions)] 53 type_name: std::any::type_name::<A>(), 54 } 55 } 56 } 57 58 impl PartialEq for AnyValueId { eq(&self, other: &Self) -> bool59 fn eq(&self, other: &Self) -> bool { 60 self.type_id == other.type_id 61 } 62 } 63 64 impl Eq for AnyValueId {} 65 66 impl PartialOrd for AnyValueId { partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering>67 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { 68 self.type_id.partial_cmp(&other.type_id) 69 } 70 } 71 72 impl Ord for AnyValueId { cmp(&self, other: &Self) -> std::cmp::Ordering73 fn cmp(&self, other: &Self) -> std::cmp::Ordering { 74 self.type_id.cmp(&other.type_id) 75 } 76 } 77 78 impl std::hash::Hash for AnyValueId { hash<H: std::hash::Hasher>(&self, state: &mut H)79 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { 80 self.type_id.hash(state); 81 } 82 } 83 84 impl std::fmt::Debug for AnyValueId { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 86 #[cfg(not(debug_assertions))] 87 { 88 self.type_id.fmt(f) 89 } 90 #[cfg(debug_assertions)] 91 { 92 f.debug_struct(self.type_name).finish() 93 } 94 } 95 } 96 97 impl<'a, A: ?Sized + 'static> From<&'a A> for AnyValueId { from(_: &'a A) -> Self98 fn from(_: &'a A) -> Self { 99 Self::of::<A>() 100 } 101 } 102 103 #[cfg(test)] 104 mod test { 105 #[test] 106 #[cfg(debug_assertions)] debug_impl()107 fn debug_impl() { 108 use super::*; 109 110 assert_eq!(format!("{:?}", AnyValue::new(5)), "AnyValue { inner: i32 }"); 111 } 112 } 113