1 // taken from https://github.com/hyperium/http/blob/master/src/extensions.rs.
2 
3 use crate::sync::{RwLockReadGuard, RwLockWriteGuard};
4 use std::{
5     any::{Any, TypeId},
6     collections::HashMap,
7     fmt,
8     hash::{BuildHasherDefault, Hasher},
9 };
10 
11 #[allow(warnings)]
12 type AnyMap = HashMap<TypeId, Box<dyn Any + Send + Sync>, BuildHasherDefault<IdHasher>>;
13 
14 /// With TypeIds as keys, there's no need to hash them. They are already hashes
15 /// themselves, coming from the compiler. The IdHasher holds the u64 of
16 /// the TypeId, and then returns it, instead of doing any bit fiddling.
17 #[derive(Default, Debug)]
18 struct IdHasher(u64);
19 
20 impl Hasher for IdHasher {
write(&mut self, _: &[u8])21     fn write(&mut self, _: &[u8]) {
22         unreachable!("TypeId calls write_u64");
23     }
24 
25     #[inline]
write_u64(&mut self, id: u64)26     fn write_u64(&mut self, id: u64) {
27         self.0 = id;
28     }
29 
30     #[inline]
finish(&self) -> u6431     fn finish(&self) -> u64 {
32         self.0
33     }
34 }
35 
36 /// An immutable, read-only reference to a Span's extensions.
37 #[derive(Debug)]
38 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
39 pub struct Extensions<'a> {
40     inner: RwLockReadGuard<'a, ExtensionsInner>,
41 }
42 
43 impl<'a> Extensions<'a> {
44     #[cfg(feature = "registry")]
new(inner: RwLockReadGuard<'a, ExtensionsInner>) -> Self45     pub(crate) fn new(inner: RwLockReadGuard<'a, ExtensionsInner>) -> Self {
46         Self { inner }
47     }
48 
49     /// Immutably borrows a type previously inserted into this `Extensions`.
get<T: 'static>(&self) -> Option<&T>50     pub fn get<T: 'static>(&self) -> Option<&T> {
51         self.inner.get::<T>()
52     }
53 }
54 
55 /// An mutable reference to a Span's extensions.
56 #[derive(Debug)]
57 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
58 pub struct ExtensionsMut<'a> {
59     inner: RwLockWriteGuard<'a, ExtensionsInner>,
60 }
61 
62 impl<'a> ExtensionsMut<'a> {
63     #[cfg(feature = "registry")]
new(inner: RwLockWriteGuard<'a, ExtensionsInner>) -> Self64     pub(crate) fn new(inner: RwLockWriteGuard<'a, ExtensionsInner>) -> Self {
65         Self { inner }
66     }
67 
68     /// Insert a type into this `Extensions`.
69     ///
70     /// Note that extensions are _not_
71     /// `Layer`-specific—they are _span_-specific. This means that
72     /// other layers can access and mutate extensions that
73     /// a different Layer recorded. For example, an application might
74     /// have a layer that records execution timings, alongside a layer
75     /// that reports spans and events to a distributed
76     /// tracing system that requires timestamps for spans.
77     /// Ideally, if one layer records a timestamp _x_, the other layer
78     /// should be able to reuse timestamp _x_.
79     ///
80     /// Therefore, extensions should generally be newtypes, rather than common
81     /// types like [`String`](std::string::String), to avoid accidental
82     /// cross-`Layer` clobbering.
83     ///
84     /// ## Panics
85     ///
86     /// If `T` is already present in `Extensions`, then this method will panic.
insert<T: Send + Sync + 'static>(&mut self, val: T)87     pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) {
88         assert!(self.replace(val).is_none())
89     }
90 
91     /// Replaces an existing `T` into this extensions.
92     ///
93     /// If `T` is not present, `Option::None` will be returned.
replace<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T>94     pub fn replace<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
95         self.inner.insert(val)
96     }
97 
98     /// Get a mutable reference to a type previously inserted on this `ExtensionsMut`.
get_mut<T: 'static>(&mut self) -> Option<&mut T>99     pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
100         self.inner.get_mut::<T>()
101     }
102 
103     /// Remove a type from this `Extensions`.
104     ///
105     /// If a extension of this type existed, it will be returned.
remove<T: Send + Sync + 'static>(&mut self) -> Option<T>106     pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
107         self.inner.remove::<T>()
108     }
109 }
110 
111 /// A type map of span extensions.
112 ///
113 /// [ExtensionsInner] is used by `SpanData` to store and
114 /// span-specific data. A given `Layer` can read and write
115 /// data that it is interested in recording and emitting.
116 #[derive(Default)]
117 pub(crate) struct ExtensionsInner {
118     map: AnyMap,
119 }
120 
121 impl ExtensionsInner {
122     /// Create an empty `Extensions`.
123     #[cfg(any(test, feature = "registry"))]
124     #[inline]
125     #[cfg(any(test, feature = "registry"))]
new() -> ExtensionsInner126     pub(crate) fn new() -> ExtensionsInner {
127         ExtensionsInner {
128             map: AnyMap::default(),
129         }
130     }
131 
132     /// Insert a type into this `Extensions`.
133     ///
134     /// If a extension of this type already existed, it will
135     /// be returned.
insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T>136     pub(crate) fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
137         self.map
138             .insert(TypeId::of::<T>(), Box::new(val))
139             .and_then(|boxed| {
140                 #[allow(warnings)]
141                 {
142                     (boxed as Box<Any + 'static>)
143                         .downcast()
144                         .ok()
145                         .map(|boxed| *boxed)
146                 }
147             })
148     }
149 
150     /// Get a reference to a type previously inserted on this `Extensions`.
get<T: 'static>(&self) -> Option<&T>151     pub(crate) fn get<T: 'static>(&self) -> Option<&T> {
152         self.map
153             .get(&TypeId::of::<T>())
154             .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
155     }
156 
157     /// Get a mutable reference to a type previously inserted on this `Extensions`.
get_mut<T: 'static>(&mut self) -> Option<&mut T>158     pub(crate) fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
159         self.map
160             .get_mut(&TypeId::of::<T>())
161             .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut())
162     }
163 
164     /// Remove a type from this `Extensions`.
165     ///
166     /// If a extension of this type existed, it will be returned.
remove<T: Send + Sync + 'static>(&mut self) -> Option<T>167     pub(crate) fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
168         self.map.remove(&TypeId::of::<T>()).and_then(|boxed| {
169             #[allow(warnings)]
170             {
171                 (boxed as Box<Any + 'static>)
172                     .downcast()
173                     .ok()
174                     .map(|boxed| *boxed)
175             }
176         })
177     }
178 
179     /// Clear the `ExtensionsInner` in-place, dropping any elements in the map but
180     /// retaining allocated capacity.
181     ///
182     /// This permits the hash map allocation to be pooled by the registry so
183     /// that future spans will not need to allocate new hashmaps.
184     #[cfg(any(test, feature = "registry"))]
clear(&mut self)185     pub(crate) fn clear(&mut self) {
186         self.map.clear();
187     }
188 }
189 
190 impl fmt::Debug for ExtensionsInner {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result191     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192         f.debug_struct("Extensions")
193             .field("len", &self.map.len())
194             .field("capacity", &self.map.capacity())
195             .finish()
196     }
197 }
198 
199 #[cfg(test)]
200 mod tests {
201     use super::*;
202 
203     #[derive(Debug, PartialEq)]
204     struct MyType(i32);
205 
206     #[test]
test_extensions()207     fn test_extensions() {
208         let mut extensions = ExtensionsInner::new();
209 
210         extensions.insert(5i32);
211         extensions.insert(MyType(10));
212 
213         assert_eq!(extensions.get(), Some(&5i32));
214         assert_eq!(extensions.get_mut(), Some(&mut 5i32));
215 
216         assert_eq!(extensions.remove::<i32>(), Some(5i32));
217         assert!(extensions.get::<i32>().is_none());
218 
219         assert_eq!(extensions.get::<bool>(), None);
220         assert_eq!(extensions.get(), Some(&MyType(10)));
221     }
222 
223     #[test]
clear_retains_capacity()224     fn clear_retains_capacity() {
225         let mut extensions = ExtensionsInner::new();
226         extensions.insert(5i32);
227         extensions.insert(MyType(10));
228         extensions.insert(true);
229 
230         assert_eq!(extensions.map.len(), 3);
231         let prev_capacity = extensions.map.capacity();
232         extensions.clear();
233 
234         assert_eq!(
235             extensions.map.len(),
236             0,
237             "after clear(), extensions map should have length 0"
238         );
239         assert_eq!(
240             extensions.map.capacity(),
241             prev_capacity,
242             "after clear(), extensions map should retain prior capacity"
243         );
244     }
245 
246     #[test]
clear_drops_elements()247     fn clear_drops_elements() {
248         use std::sync::Arc;
249         struct DropMePlease(Arc<()>);
250         struct DropMeTooPlease(Arc<()>);
251 
252         let mut extensions = ExtensionsInner::new();
253         let val1 = DropMePlease(Arc::new(()));
254         let val2 = DropMeTooPlease(Arc::new(()));
255 
256         let val1_dropped = Arc::downgrade(&val1.0);
257         let val2_dropped = Arc::downgrade(&val2.0);
258         extensions.insert(val1);
259         extensions.insert(val2);
260 
261         assert!(val1_dropped.upgrade().is_some());
262         assert!(val2_dropped.upgrade().is_some());
263 
264         extensions.clear();
265         assert!(
266             val1_dropped.upgrade().is_none(),
267             "after clear(), val1 should be dropped"
268         );
269         assert!(
270             val2_dropped.upgrade().is_none(),
271             "after clear(), val2 should be dropped"
272         );
273     }
274 }
275