Skip to main content

volans_core/
extensions.rs

1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::fmt;
4use std::hash::{BuildHasherDefault, Hasher};
5
6type AnyMap = HashMap<TypeId, Box<dyn AnyClone + Send + Sync>, BuildHasherDefault<IdHasher>>;
7
8#[derive(Default)]
9struct IdHasher(u64);
10
11impl Hasher for IdHasher {
12    fn write(&mut self, _: &[u8]) {
13        unreachable!("TypeId calls write_u64");
14    }
15
16    #[inline]
17    fn write_u64(&mut self, id: u64) {
18        self.0 = id;
19    }
20
21    #[inline]
22    fn finish(&self) -> u64 {
23        self.0
24    }
25}
26
27#[derive(Clone, Default)]
28pub struct Extensions {
29    map: Option<Box<AnyMap>>,
30}
31
32impl Extensions {
33    /// Create an empty `Extensions`.
34    #[inline]
35    pub fn new() -> Extensions {
36        Extensions { map: None }
37    }
38
39    pub fn insert<T: Clone + Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
40        self.map
41            .get_or_insert_with(Box::default)
42            .insert(TypeId::of::<T>(), Box::new(val))
43            .and_then(|boxed| boxed.into_any().downcast().ok().map(|boxed| *boxed))
44    }
45
46    pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
47        self.map
48            .as_ref()
49            .and_then(|map| map.get(&TypeId::of::<T>()))
50            .and_then(|boxed| (**boxed).as_any().downcast_ref())
51    }
52
53    pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
54        self.map
55            .as_mut()
56            .and_then(|map| map.get_mut(&TypeId::of::<T>()))
57            .and_then(|boxed| (**boxed).as_any_mut().downcast_mut())
58    }
59
60    pub fn get_or_insert<T: Clone + Send + Sync + 'static>(&mut self, value: T) -> &mut T {
61        self.get_or_insert_with(|| value)
62    }
63
64    pub fn get_or_insert_with<T: Clone + Send + Sync + 'static, F: FnOnce() -> T>(
65        &mut self,
66        f: F,
67    ) -> &mut T {
68        let out = self
69            .map
70            .get_or_insert_with(Box::default)
71            .entry(TypeId::of::<T>())
72            .or_insert_with(|| Box::new(f()));
73        (**out).as_any_mut().downcast_mut().unwrap()
74    }
75
76    pub fn get_or_insert_default<T: Default + Clone + Send + Sync + 'static>(&mut self) -> &mut T {
77        self.get_or_insert_with(T::default)
78    }
79
80    pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
81        self.map
82            .as_mut()
83            .and_then(|map| map.remove(&TypeId::of::<T>()))
84            .and_then(|boxed| boxed.into_any().downcast().ok().map(|boxed| *boxed))
85    }
86
87    #[inline]
88    pub fn clear(&mut self) {
89        if let Some(ref mut map) = self.map {
90            map.clear();
91        }
92    }
93
94    #[inline]
95    pub fn is_empty(&self) -> bool {
96        self.map.as_ref().map_or(true, |map| map.is_empty())
97    }
98
99    #[inline]
100    pub fn len(&self) -> usize {
101        self.map.as_ref().map_or(0, |map| map.len())
102    }
103
104    pub fn extend(&mut self, other: Self) {
105        if let Some(other) = other.map {
106            if let Some(map) = &mut self.map {
107                map.extend(*other);
108            } else {
109                self.map = Some(other);
110            }
111        }
112    }
113}
114
115impl fmt::Debug for Extensions {
116    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117        f.debug_struct("Extensions").finish()
118    }
119}
120
121trait AnyClone: Any {
122    fn clone_box(&self) -> Box<dyn AnyClone + Send + Sync>;
123    fn as_any(&self) -> &dyn Any;
124    fn as_any_mut(&mut self) -> &mut dyn Any;
125    fn into_any(self: Box<Self>) -> Box<dyn Any>;
126}
127
128impl<T: Clone + Send + Sync + 'static> AnyClone for T {
129    fn clone_box(&self) -> Box<dyn AnyClone + Send + Sync> {
130        Box::new(self.clone())
131    }
132
133    fn as_any(&self) -> &dyn Any {
134        self
135    }
136
137    fn as_any_mut(&mut self) -> &mut dyn Any {
138        self
139    }
140
141    fn into_any(self: Box<Self>) -> Box<dyn Any> {
142        self
143    }
144}
145
146impl Clone for Box<dyn AnyClone + Send + Sync> {
147    fn clone(&self) -> Self {
148        (**self).clone_box()
149    }
150}