1 // taken from https://github.com/hyperium/http/blob/master/src/extensions.rs.
3 use crate::sync
::{RwLockReadGuard, RwLockWriteGuard}
;
8 hash
::{BuildHasherDefault, Hasher}
,
12 type AnyMap
= HashMap
<TypeId
, Box
<dyn Any
+ Send
+ Sync
>, BuildHasherDefault
<IdHasher
>>;
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)]
20 impl Hasher
for IdHasher
{
21 fn write(&mut self, _
: &[u8]) {
22 unreachable
!("TypeId calls write_u64");
26 fn write_u64(&mut self, id
: u64) {
31 fn finish(&self) -> u64 {
36 /// An immutable, read-only reference to a Span's extensions.
38 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
39 pub struct Extensions
<'a
> {
40 inner
: RwLockReadGuard
<'a
, ExtensionsInner
>,
43 impl<'a
> Extensions
<'a
> {
44 #[cfg(feature = "registry")]
45 pub(crate) fn new(inner
: RwLockReadGuard
<'a
, ExtensionsInner
>) -> Self {
49 /// Immutably borrows a type previously inserted into this `Extensions`.
50 pub fn get
<T
: '
static>(&self) -> Option
<&T
> {
55 /// An mutable reference to a Span's extensions.
57 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
58 pub struct ExtensionsMut
<'a
> {
59 inner
: RwLockWriteGuard
<'a
, ExtensionsInner
>,
62 impl<'a
> ExtensionsMut
<'a
> {
63 #[cfg(feature = "registry")]
64 pub(crate) fn new(inner
: RwLockWriteGuard
<'a
, ExtensionsInner
>) -> Self {
68 /// Insert a type into this `Extensions`.
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_.
80 /// Therefore, extensions should generally be newtypes, rather than common
81 /// types like [`String`](std::string::String), to avoid accidental
82 /// cross-`Layer` clobbering.
86 /// If `T` is already present in `Extensions`, then this method will panic.
87 pub fn insert
<T
: Send
+ Sync
+ '
static>(&mut self, val
: T
) {
88 assert
!(self.replace(val
).is_none())
91 /// Replaces an existing `T` into this extensions.
93 /// If `T` is not present, `Option::None` will be returned.
94 pub fn replace
<T
: Send
+ Sync
+ '
static>(&mut self, val
: T
) -> Option
<T
> {
95 self.inner
.insert(val
)
98 /// Get a mutable reference to a type previously inserted on this `ExtensionsMut`.
99 pub fn get_mut
<T
: '
static>(&mut self) -> Option
<&mut T
> {
100 self.inner
.get_mut
::<T
>()
103 /// Remove a type from this `Extensions`.
105 /// If a extension of this type existed, it will be returned.
106 pub fn remove
<T
: Send
+ Sync
+ '
static>(&mut self) -> Option
<T
> {
107 self.inner
.remove
::<T
>()
111 /// A type map of span extensions.
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.
117 pub(crate) struct ExtensionsInner
{
121 impl ExtensionsInner
{
122 /// Create an empty `Extensions`.
123 #[cfg(any(test, feature = "registry"))]
125 #[cfg(any(test, feature = "registry"))]
126 pub(crate) fn new() -> ExtensionsInner
{
128 map
: AnyMap
::default(),
132 /// Insert a type into this `Extensions`.
134 /// If a extension of this type already existed, it will
136 pub(crate) fn insert
<T
: Send
+ Sync
+ '
static>(&mut self, val
: T
) -> Option
<T
> {
138 .insert(TypeId
::of
::<T
>(), Box
::new(val
))
142 (boxed
as Box
<Any
+ '
static>)
150 /// Get a reference to a type previously inserted on this `Extensions`.
151 pub(crate) fn get
<T
: '
static>(&self) -> Option
<&T
> {
153 .get(&TypeId
::of
::<T
>())
154 .and_then(|boxed
| (&**boxed
as &(dyn Any
+ '
static)).downcast_ref())
157 /// Get a mutable reference to a type previously inserted on this `Extensions`.
158 pub(crate) fn get_mut
<T
: '
static>(&mut self) -> Option
<&mut T
> {
160 .get_mut(&TypeId
::of
::<T
>())
161 .and_then(|boxed
| (&mut **boxed
as &mut (dyn Any
+ '
static)).downcast_mut())
164 /// Remove a type from this `Extensions`.
166 /// If a extension of this type existed, it will be returned.
167 pub(crate) fn remove
<T
: Send
+ Sync
+ '
static>(&mut self) -> Option
<T
> {
168 self.map
.remove(&TypeId
::of
::<T
>()).and_then(|boxed
| {
171 (boxed
as Box
<Any
+ '
static>)
179 /// Clear the `ExtensionsInner` in-place, dropping any elements in the map but
180 /// retaining allocated capacity.
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"))]
185 pub(crate) fn clear(&mut self) {
190 impl fmt
::Debug
for ExtensionsInner
{
191 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())
203 #[derive(Debug, PartialEq)]
207 fn test_extensions() {
208 let mut extensions
= ExtensionsInner
::new();
210 extensions
.insert(5i32);
211 extensions
.insert(MyType(10));
213 assert_eq
!(extensions
.get(), Some(&5i32));
214 assert_eq
!(extensions
.get_mut(), Some(&mut 5i32));
216 assert_eq
!(extensions
.remove
::<i32>(), Some(5i32));
217 assert
!(extensions
.get
::<i32>().is_none());
219 assert_eq
!(extensions
.get
::<bool
>(), None
);
220 assert_eq
!(extensions
.get(), Some(&MyType(10)));
224 fn clear_retains_capacity() {
225 let mut extensions
= ExtensionsInner
::new();
226 extensions
.insert(5i32);
227 extensions
.insert(MyType(10));
228 extensions
.insert(true);
230 assert_eq
!(extensions
.map
.len(), 3);
231 let prev_capacity
= extensions
.map
.capacity();
235 extensions
.map
.len(),
237 "after clear(), extensions map should have length 0"
240 extensions
.map
.capacity(),
242 "after clear(), extensions map should retain prior capacity"
247 fn clear_drops_elements() {
249 struct DropMePlease(Arc
<()>);
250 struct DropMeTooPlease(Arc
<()>);
252 let mut extensions
= ExtensionsInner
::new();
253 let val1
= DropMePlease(Arc
::new(()));
254 let val2
= DropMeTooPlease(Arc
::new(()));
256 let val1_dropped
= Arc
::downgrade(&val1
.0
);
257 let val2_dropped
= Arc
::downgrade(&val2
.0
);
258 extensions
.insert(val1
);
259 extensions
.insert(val2
);
261 assert
!(val1_dropped
.upgrade().is_some());
262 assert
!(val2_dropped
.upgrade().is_some());
266 val1_dropped
.upgrade().is_none(),
267 "after clear(), val1 should be dropped"
270 val2_dropped
.upgrade().is_none(),
271 "after clear(), val2 should be dropped"