1// taken from https://github.com/hyperium/http/blob/master/src/extensions.rs.
23use crate::sync::{RwLockReadGuard, RwLockWriteGuard};
4use std::{
5 any::{Any, TypeId},
6 collections::HashMap,
7 fmt,
8 hash::{BuildHasherDefault, Hasher},
9};
1011#[allow(warnings)]
12type AnyMap = HashMap<TypeId, Box<dyn Any + Send + Sync>, BuildHasherDefault<IdHasher>>;
1314/// 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)]
18struct IdHasher(u64);
1920impl Hasher for IdHasher {
21fn write(&mut self, _: &[u8]) {
22unreachable!("TypeId calls write_u64");
23 }
2425#[inline]
26fn write_u64(&mut self, id: u64) {
27self.0 = id;
28 }
2930#[inline]
31fn finish(&self) -> u64 {
32self.0
33}
34}
3536/// An immutable, read-only reference to a Span's extensions.
37#[derive(Debug)]
38#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
39pub struct Extensions<'a> {
40 inner: RwLockReadGuard<'a, ExtensionsInner>,
41}
4243impl<'a> Extensions<'a> {
44#[cfg(feature = "registry")]
45pub(crate) fn new(inner: RwLockReadGuard<'a, ExtensionsInner>) -> Self {
46Self { inner }
47 }
4849/// Immutably borrows a type previously inserted into this `Extensions`.
50pub fn get<T: 'static>(&self) -> Option<&T> {
51self.inner.get::<T>()
52 }
53}
5455/// An mutable reference to a Span's extensions.
56#[derive(Debug)]
57#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
58pub struct ExtensionsMut<'a> {
59 inner: RwLockWriteGuard<'a, ExtensionsInner>,
60}
6162impl<'a> ExtensionsMut<'a> {
63#[cfg(feature = "registry")]
64pub(crate) fn new(inner: RwLockWriteGuard<'a, ExtensionsInner>) -> Self {
65Self { inner }
66 }
6768/// 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.
87pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) {
88assert!(self.replace(val).is_none())
89 }
9091/// Replaces an existing `T` into this extensions.
92 ///
93 /// If `T` is not present, `Option::None` will be returned.
94pub fn replace<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
95self.inner.insert(val)
96 }
9798/// Get a mutable reference to a type previously inserted on this `ExtensionsMut`.
99pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
100self.inner.get_mut::<T>()
101 }
102103/// Remove a type from this `Extensions`.
104 ///
105 /// If a extension of this type existed, it will be returned.
106pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
107self.inner.remove::<T>()
108 }
109}
110111/// 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)]
117pub(crate) struct ExtensionsInner {
118 map: AnyMap,
119}
120121impl ExtensionsInner {
122/// Create an empty `Extensions`.
123#[cfg(any(test, feature = "registry"))]
124 #[inline]
125 #[cfg(any(test, feature = "registry"))]
126pub(crate) fn new() -> ExtensionsInner {
127 ExtensionsInner {
128 map: AnyMap::default(),
129 }
130 }
131132/// Insert a type into this `Extensions`.
133 ///
134 /// If a extension of this type already existed, it will
135 /// be returned.
136pub(crate) fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
137self.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 }
149150/// Get a reference to a type previously inserted on this `Extensions`.
151pub(crate) fn get<T: 'static>(&self) -> Option<&T> {
152self.map
153 .get(&TypeId::of::<T>())
154 .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
155 }
156157/// Get a mutable reference to a type previously inserted on this `Extensions`.
158pub(crate) fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
159self.map
160 .get_mut(&TypeId::of::<T>())
161 .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut())
162 }
163164/// Remove a type from this `Extensions`.
165 ///
166 /// If a extension of this type existed, it will be returned.
167pub(crate) fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
168self.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 }
178179/// 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"))]
185pub(crate) fn clear(&mut self) {
186self.map.clear();
187 }
188}
189190impl fmt::Debug for ExtensionsInner {
191fn 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}
198199#[cfg(test)]
200mod tests {
201use super::*;
202203#[derive(Debug, PartialEq)]
204struct MyType(i32);
205206#[test]
207fn test_extensions() {
208let mut extensions = ExtensionsInner::new();
209210 extensions.insert(5i32);
211 extensions.insert(MyType(10));
212213assert_eq!(extensions.get(), Some(&5i32));
214assert_eq!(extensions.get_mut(), Some(&mut 5i32));
215216assert_eq!(extensions.remove::<i32>(), Some(5i32));
217assert!(extensions.get::<i32>().is_none());
218219assert_eq!(extensions.get::<bool>(), None);
220assert_eq!(extensions.get(), Some(&MyType(10)));
221 }
222223#[test]
224fn clear_retains_capacity() {
225let mut extensions = ExtensionsInner::new();
226 extensions.insert(5i32);
227 extensions.insert(MyType(10));
228 extensions.insert(true);
229230assert_eq!(extensions.map.len(), 3);
231let prev_capacity = extensions.map.capacity();
232 extensions.clear();
233234assert_eq!(
235 extensions.map.len(),
2360,
237"after clear(), extensions map should have length 0"
238);
239assert_eq!(
240 extensions.map.capacity(),
241 prev_capacity,
242"after clear(), extensions map should retain prior capacity"
243);
244 }
245246#[test]
247fn clear_drops_elements() {
248use std::sync::Arc;
249struct DropMePlease(Arc<()>);
250struct DropMeTooPlease(Arc<()>);
251252let mut extensions = ExtensionsInner::new();
253let val1 = DropMePlease(Arc::new(()));
254let val2 = DropMeTooPlease(Arc::new(()));
255256let val1_dropped = Arc::downgrade(&val1.0);
257let val2_dropped = Arc::downgrade(&val2.0);
258 extensions.insert(val1);
259 extensions.insert(val2);
260261assert!(val1_dropped.upgrade().is_some());
262assert!(val2_dropped.upgrade().is_some());
263264 extensions.clear();
265assert!(
266 val1_dropped.upgrade().is_none(),
267"after clear(), val1 should be dropped"
268);
269assert!(
270 val2_dropped.upgrade().is_none(),
271"after clear(), val2 should be dropped"
272);
273 }
274}