use std::any::{Any, TypeId}; use std::collections::HashMap; use std::fmt; use std::hash::{BuildHasherDefault, Hasher};
type AnyMap = HashMap<TypeId, Box<dyn Any + Send + Sync>, BuildHasherDefault<IdHasher>>;
// With TypeIds as keys, there's no need to hash them. They are already hashes // themselves, coming from the compiler. The IdHasher just holds the u64 of // the TypeId, and then returns it, instead of doing any bit fiddling. #[derive(Default)] struct IdHasher(u64);
/// A type map of protocol extensions. /// /// `Extensions` can be used by `Request` and `Response` to store /// extra data derived from the underlying protocol. #[derive(Default)] pubstruct Extensions { // If extensions are never used, no need to carry around an empty HashMap. // That's 3 words. Instead, this is only 1 word.
map: Option<Box<AnyMap>>,
}
/// Insert a type into this `Extensions`. /// /// If a extension of this type already existed, it will /// be returned. /// /// # Example /// /// ``` /// # use http::Extensions; /// let mut ext = Extensions::new(); /// assert!(ext.insert(5i32).is_none()); /// assert!(ext.insert(4u8).is_none()); /// assert_eq!(ext.insert(9i32), Some(5i32)); /// ``` pubfn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> { self.map
.get_or_insert_with(|| Box::new(HashMap::default()))
.insert(TypeId::of::<T>(), Box::new(val))
.and_then(|boxed| {
(boxed asBox<dyn Any + 'static>)
.downcast()
.ok()
.map(|boxed| *boxed)
})
}
/// Get a reference to a type previously inserted on this `Extensions`. /// /// # Example /// /// ``` /// # use http::Extensions; /// let mut ext = Extensions::new(); /// assert!(ext.get::<i32>().is_none()); /// ext.insert(5i32); /// /// assert_eq!(ext.get::<i32>(), Some(&5i32)); /// ``` pubfn get<T: Send + Sync + 'static>(&self) -> Option<&T> { self.map
.as_ref()
.and_then(|map| map.get(&TypeId::of::<T>()))
.and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
}
/// Get a mutable reference to a type previously inserted on this `Extensions`. /// /// # Example /// /// ``` /// # use http::Extensions; /// let mut ext = Extensions::new(); /// ext.insert(String::from("Hello")); /// ext.get_mut::<String>().unwrap().push_str(" World"); /// /// assert_eq!(ext.get::<String>().unwrap(), "Hello World"); /// ``` pubfn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> { self.map
.as_mut()
.and_then(|map| map.get_mut(&TypeId::of::<T>()))
.and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut())
}
/// Remove a type from this `Extensions`. /// /// If a extension of this type existed, it will be returned. /// /// # Example /// /// ``` /// # use http::Extensions; /// let mut ext = Extensions::new(); /// ext.insert(5i32); /// assert_eq!(ext.remove::<i32>(), Some(5i32)); /// assert!(ext.get::<i32>().is_none()); /// ``` pubfn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> { self.map
.as_mut()
.and_then(|map| map.remove(&TypeId::of::<T>()))
.and_then(|boxed| {
(boxed asBox<dyn Any + 'static>)
.downcast()
.ok()
.map(|boxed| *boxed)
})
}
/// Clear the `Extensions` of all inserted extensions. /// /// # Example /// /// ``` /// # use http::Extensions; /// let mut ext = Extensions::new(); /// ext.insert(5i32); /// ext.clear(); /// /// assert!(ext.get::<i32>().is_none()); /// ``` #[inline] pubfn clear(&mutself) { iflet Some(refmut map) = self.map {
map.clear();
}
}
/// Check whether the extension set is empty or not. /// /// # Example /// /// ``` /// # use http::Extensions; /// let mut ext = Extensions::new(); /// assert!(ext.is_empty()); /// ext.insert(5i32); /// assert!(!ext.is_empty()); /// ``` #[inline] pubfn is_empty(&self) -> bool { self.map
.as_ref()
.map_or(true, |map| map.is_empty())
}
/// Get the numer of extensions available. /// /// # Example /// /// ``` /// # use http::Extensions; /// let mut ext = Extensions::new(); /// assert_eq!(ext.len(), 0); /// ext.insert(5i32); /// assert_eq!(ext.len(), 1); /// ``` #[inline] pubfn len(&self) -> usize { self.map
.as_ref()
.map_or(0, |map| map.len())
}
/// Extends `self` with another `Extensions`. /// /// If an instance of a specific type exists in both, the one in `self` is overwritten with the /// one from `other`. /// /// # Example /// /// ``` /// # use http::Extensions; /// let mut ext_a = Extensions::new(); /// ext_a.insert(8u8); /// ext_a.insert(16u16); /// /// let mut ext_b = Extensions::new(); /// ext_b.insert(4u8); /// ext_b.insert("hello"); /// /// ext_a.extend(ext_b); /// assert_eq!(ext_a.len(), 3); /// assert_eq!(ext_a.get::<u8>(), Some(&4u8)); /// assert_eq!(ext_a.get::<u16>(), Some(&16u16)); /// assert_eq!(ext_a.get::<&'static str>().copied(), Some("hello")); /// ``` pubfn extend(&mutself, other: Self) { iflet Some(other) = other.map { iflet Some(map) = &mutself.map {
map.extend(*other);
} else { self.map = Some(other);
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.