mcpkit_rs/model/extension.rs
1//! A container for those extra data could be carried on request or notification.
2//!
3//! This file is copied and modified from crate [http](https://github.com/hyperium/http).
4//!
5//! - Original code license: <https://github.com/hyperium/http/blob/master/LICENSE-MIT>
6//! - Original code: <https://github.com/hyperium/http/blob/master/src/extensions.rs>
7use std::{
8 any::{Any, TypeId},
9 collections::HashMap,
10 fmt,
11 hash::{BuildHasherDefault, Hasher},
12};
13
14type AnyMap = HashMap<TypeId, Box<dyn AnyClone + Send + Sync>, BuildHasherDefault<IdHasher>>;
15
16// With TypeIds as keys, there's no need to hash them. They are already hashes
17// themselves, coming from the compiler. The IdHasher just holds the u64 of
18// the TypeId, and then returns it, instead of doing any bit fiddling.
19#[derive(Default)]
20struct IdHasher(u64);
21
22impl Hasher for IdHasher {
23 fn write(&mut self, _: &[u8]) {
24 unreachable!("TypeId calls write_u64");
25 }
26
27 #[inline]
28 fn write_u64(&mut self, id: u64) {
29 self.0 = id;
30 }
31
32 #[inline]
33 fn finish(&self) -> u64 {
34 self.0
35 }
36}
37
38/// A type map of protocol extensions.
39///
40/// `Extensions` can be used by `Request` `Notification` and `Response` to store
41/// extra data derived from the underlying protocol.
42#[derive(Clone, Default)]
43pub struct Extensions {
44 // If extensions are never used, no need to carry around an empty HashMap.
45 // That's 3 words. Instead, this is only 1 word.
46 map: Option<Box<AnyMap>>,
47}
48
49impl Extensions {
50 /// Create an empty `Extensions`.
51 #[inline]
52 pub const fn new() -> Extensions {
53 Extensions { map: None }
54 }
55
56 /// Insert a type into this `Extensions`.
57 ///
58 /// If a extension of this type already existed, it will
59 /// be returned and replaced with the new one.
60 ///
61 /// # Example
62 ///
63 /// ```
64 /// # use mcpkit_rs::model::Extensions;
65 /// let mut ext = Extensions::new();
66 /// assert!(ext.insert(5i32).is_none());
67 /// assert!(ext.insert(4u8).is_none());
68 /// assert_eq!(ext.insert(9i32), Some(5i32));
69 /// ```
70 pub fn insert<T: Clone + Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
71 self.map
72 .get_or_insert_with(Box::default)
73 .insert(TypeId::of::<T>(), Box::new(val))
74 .and_then(|boxed| boxed.into_any().downcast().ok().map(|boxed| *boxed))
75 }
76
77 /// Get a reference to a type previously inserted on this `Extensions`.
78 ///
79 /// # Example
80 ///
81 /// ```
82 /// # use mcpkit_rs::model::Extensions;
83 /// let mut ext = Extensions::new();
84 /// assert!(ext.get::<i32>().is_none());
85 /// ext.insert(5i32);
86 ///
87 /// assert_eq!(ext.get::<i32>(), Some(&5i32));
88 /// ```
89 pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
90 self.map
91 .as_ref()
92 .and_then(|map| map.get(&TypeId::of::<T>()))
93 .and_then(|boxed| (**boxed).as_any().downcast_ref())
94 }
95
96 /// Get a mutable reference to a type previously inserted on this `Extensions`.
97 ///
98 /// # Example
99 ///
100 /// ```
101 /// # use mcpkit_rs::model::Extensions;
102 /// let mut ext = Extensions::new();
103 /// ext.insert(String::from("Hello"));
104 /// ext.get_mut::<String>().unwrap().push_str(" World");
105 ///
106 /// assert_eq!(ext.get::<String>().unwrap(), "Hello World");
107 /// ```
108 pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
109 self.map
110 .as_mut()
111 .and_then(|map| map.get_mut(&TypeId::of::<T>()))
112 .and_then(|boxed| (**boxed).as_any_mut().downcast_mut())
113 }
114
115 /// Get a mutable reference to a type, inserting `value` if not already present on this
116 /// `Extensions`.
117 ///
118 /// # Example
119 ///
120 /// ```
121 /// # use mcpkit_rs::model::Extensions;
122 /// let mut ext = Extensions::new();
123 /// *ext.get_or_insert(1i32) += 2;
124 ///
125 /// assert_eq!(*ext.get::<i32>().unwrap(), 3);
126 /// ```
127 pub fn get_or_insert<T: Clone + Send + Sync + 'static>(&mut self, value: T) -> &mut T {
128 self.get_or_insert_with(|| value)
129 }
130
131 /// Get a mutable reference to a type, inserting the value created by `f` if not already present
132 /// on this `Extensions`.
133 ///
134 /// # Example
135 ///
136 /// ```
137 /// # use mcpkit_rs::model::Extensions;
138 /// let mut ext = Extensions::new();
139 /// *ext.get_or_insert_with(|| 1i32) += 2;
140 ///
141 /// assert_eq!(*ext.get::<i32>().unwrap(), 3);
142 /// ```
143 pub fn get_or_insert_with<T: Clone + Send + Sync + 'static, F: FnOnce() -> T>(
144 &mut self,
145 f: F,
146 ) -> &mut T {
147 let out = self
148 .map
149 .get_or_insert_with(Box::default)
150 .entry(TypeId::of::<T>())
151 .or_insert_with(|| Box::new(f()));
152 (**out).as_any_mut().downcast_mut().unwrap()
153 }
154
155 /// Get a mutable reference to a type, inserting the type's default value if not already present
156 /// on this `Extensions`.
157 ///
158 /// # Example
159 ///
160 /// ```
161 /// # use mcpkit_rs::model::Extensions;
162 /// let mut ext = Extensions::new();
163 /// *ext.get_or_insert_default::<i32>() += 2;
164 ///
165 /// assert_eq!(*ext.get::<i32>().unwrap(), 2);
166 /// ```
167 pub fn get_or_insert_default<T: Default + Clone + Send + Sync + 'static>(&mut self) -> &mut T {
168 self.get_or_insert_with(T::default)
169 }
170
171 /// Remove a type from this `Extensions`.
172 ///
173 /// If a extension of this type existed, it will be returned.
174 ///
175 /// # Example
176 ///
177 /// ```
178 /// # use mcpkit_rs::model::Extensions;
179 /// let mut ext = Extensions::new();
180 /// ext.insert(5i32);
181 /// assert_eq!(ext.remove::<i32>(), Some(5i32));
182 /// assert!(ext.get::<i32>().is_none());
183 /// ```
184 pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
185 self.map
186 .as_mut()
187 .and_then(|map| map.remove(&TypeId::of::<T>()))
188 .and_then(|boxed| boxed.into_any().downcast().ok().map(|boxed| *boxed))
189 }
190
191 /// Clear the `Extensions` of all inserted extensions.
192 ///
193 /// # Example
194 ///
195 /// ```
196 /// # use mcpkit_rs::model::Extensions;
197 /// let mut ext = Extensions::new();
198 /// ext.insert(5i32);
199 /// ext.clear();
200 ///
201 /// assert!(ext.get::<i32>().is_none());
202 /// ```
203 #[inline]
204 pub fn clear(&mut self) {
205 if let Some(ref mut map) = self.map {
206 map.clear();
207 }
208 }
209
210 /// Check whether the extension set is empty or not.
211 ///
212 /// # Example
213 ///
214 /// ```
215 /// # use mcpkit_rs::model::Extensions;
216 /// let mut ext = Extensions::new();
217 /// assert!(ext.is_empty());
218 /// ext.insert(5i32);
219 /// assert!(!ext.is_empty());
220 /// ```
221 #[inline]
222 pub fn is_empty(&self) -> bool {
223 self.map.as_ref().is_none_or(|map| map.is_empty())
224 }
225
226 /// Get the number of extensions available.
227 ///
228 /// # Example
229 ///
230 /// ```
231 /// # use mcpkit_rs::model::Extensions;
232 /// let mut ext = Extensions::new();
233 /// assert_eq!(ext.len(), 0);
234 /// ext.insert(5i32);
235 /// assert_eq!(ext.len(), 1);
236 /// ```
237 #[inline]
238 pub fn len(&self) -> usize {
239 self.map.as_ref().map_or(0, |map| map.len())
240 }
241
242 /// Extends `self` with another `Extensions`.
243 ///
244 /// If an instance of a specific type exists in both, the one in `self` is overwritten with the
245 /// one from `other`.
246 ///
247 /// # Example
248 ///
249 /// ```
250 /// # use mcpkit_rs::model::Extensions;
251 /// let mut ext_a = Extensions::new();
252 /// ext_a.insert(8u8);
253 /// ext_a.insert(16u16);
254 ///
255 /// let mut ext_b = Extensions::new();
256 /// ext_b.insert(4u8);
257 /// ext_b.insert("hello");
258 ///
259 /// ext_a.extend(ext_b);
260 /// assert_eq!(ext_a.len(), 3);
261 /// assert_eq!(ext_a.get::<u8>(), Some(&4u8));
262 /// assert_eq!(ext_a.get::<u16>(), Some(&16u16));
263 /// assert_eq!(ext_a.get::<&'static str>().copied(), Some("hello"));
264 /// ```
265 pub fn extend(&mut self, other: Self) {
266 if let Some(other) = other.map {
267 if let Some(map) = &mut self.map {
268 map.extend(*other);
269 } else {
270 self.map = Some(other);
271 }
272 }
273 }
274}
275
276impl fmt::Debug for Extensions {
277 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
278 f.debug_struct("Extensions").finish()
279 }
280}
281
282trait AnyClone: Any {
283 fn clone_box(&self) -> Box<dyn AnyClone + Send + Sync>;
284 fn as_any(&self) -> &dyn Any;
285 fn as_any_mut(&mut self) -> &mut dyn Any;
286 fn into_any(self: Box<Self>) -> Box<dyn Any>;
287}
288
289impl<T: Clone + Send + Sync + 'static> AnyClone for T {
290 fn clone_box(&self) -> Box<dyn AnyClone + Send + Sync> {
291 Box::new(self.clone())
292 }
293
294 fn as_any(&self) -> &dyn Any {
295 self
296 }
297
298 fn as_any_mut(&mut self) -> &mut dyn Any {
299 self
300 }
301
302 fn into_any(self: Box<Self>) -> Box<dyn Any> {
303 self
304 }
305}
306
307impl Clone for Box<dyn AnyClone + Send + Sync> {
308 fn clone(&self) -> Self {
309 (**self).clone_box()
310 }
311}
312
313#[test]
314fn test_extensions() {
315 #[derive(Clone, Debug, PartialEq)]
316 struct MyType(i32);
317
318 let mut extensions = Extensions::new();
319
320 extensions.insert(5i32);
321 extensions.insert(MyType(10));
322
323 assert_eq!(extensions.get(), Some(&5i32));
324 assert_eq!(extensions.get_mut(), Some(&mut 5i32));
325
326 let ext2 = extensions.clone();
327
328 assert_eq!(extensions.remove::<i32>(), Some(5i32));
329 assert!(extensions.get::<i32>().is_none());
330
331 // clone still has it
332 assert_eq!(ext2.get(), Some(&5i32));
333 assert_eq!(ext2.get(), Some(&MyType(10)));
334
335 assert_eq!(extensions.get::<bool>(), None);
336 assert_eq!(extensions.get(), Some(&MyType(10)));
337}