volans_core/
extensions.rs1use 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 #[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}