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         Some(self.cmp(other))
69     }
70 }
71 
72 impl PartialEq<std::any::TypeId> for AnyValueId {
eq(&self, other: &std::any::TypeId) -> bool73     fn eq(&self, other: &std::any::TypeId) -> bool {
74         self.type_id == *other
75     }
76 }
77 
78 impl Ord for AnyValueId {
cmp(&self, other: &Self) -> std::cmp::Ordering79     fn cmp(&self, other: &Self) -> std::cmp::Ordering {
80         self.type_id.cmp(&other.type_id)
81     }
82 }
83 
84 impl std::hash::Hash for AnyValueId {
hash<H: std::hash::Hasher>(&self, state: &mut H)85     fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
86         self.type_id.hash(state);
87     }
88 }
89 
90 impl std::fmt::Debug for AnyValueId {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>91     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
92         #[cfg(not(debug_assertions))]
93         {
94             self.type_id.fmt(f)
95         }
96         #[cfg(debug_assertions)]
97         {
98             f.debug_struct(self.type_name).finish()
99         }
100     }
101 }
102 
103 impl<'a, A: ?Sized + 'static> From<&'a A> for AnyValueId {
from(_: &'a A) -> Self104     fn from(_: &'a A) -> Self {
105         Self::of::<A>()
106     }
107 }
108 
109 #[cfg(test)]
110 mod test {
111     #[test]
112     #[cfg(debug_assertions)]
debug_impl()113     fn debug_impl() {
114         use super::*;
115 
116         assert_eq!(format!("{:?}", AnyValue::new(5)), "AnyValue { inner: i32 }");
117     }
118 
119     #[test]
eq_to_type_id()120     fn eq_to_type_id() {
121         use super::*;
122 
123         let any_value_id = AnyValueId::of::<i32>();
124         let type_id = std::any::TypeId::of::<i32>();
125         assert_eq!(any_value_id, type_id);
126     }
127 }
128