- secure: nR+DJRUQ9v03nNZMpMu1tGKLKBAqdQsTIAr8ffdl+DUEh3b2jvQ+vLLNFLPjsloqhoOXo7cWO7qVpiE4ZOq2lNDURQjdiZGFjh/Y5+xKy2BqFdV7qQ1JoBzsMyx28tQTYz0mtBsACiCYKKb+ddNX5hpwrsjp8cS7htZktA5kbiU=
script:
- if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features nightly; else ! cargo test --features nightly; fi
- - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'clone nightly'; else ! cargo test --features 'clone nightly'; fi
- - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'concurrent nightly'; else ! cargo test --features 'concurrent nightly'; fi
- - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'clone concurrent nightly'; else ! cargo test --features 'clone concurrent nightly'; fi
- - cargo test --features clone
- - cargo test --features concurrent
- - cargo test --features 'clone concurrent'
- cargo test
- cargo doc
after_script:
license = "MIT/Apache-2.0"
[features]
-clone = []
-concurrent = []
nightly = []
Cargo all the way: it is `anymap` on crates.io.
-There are a couple of optional features on the `anymap` crate:
-
-- `clone`: if enabled, your `AnyMap` will require contained types to implement `Clone` and will itself satisfy `Clone`.
-
-- `concurrent`: if enabled, your `AnyMap` will require contained types to satisfy `Send` and `Sync` and will itself satisfy `Send` and `Sync`.
-
-These can be combined if desired.
-
For users of the nightly instead of the beta of rustc there are a couple of things behind the `nightly` feature like a `drain` method on the `RawAnyMap` and a more efficient hashing technique which makes lookup in the map a tad faster.
Author
--- /dev/null
+//! The different types of `Any` for use in a map.
+//!
+//! This stuff is all based on `std::any`, but goes a little further, with `CloneAny` being a
+//! cloneable `Any` and with the `Send` and `Sync` bounds possible on both `Any` and `CloneAny`.
+
+use std::mem;
+use std::fmt;
+use std::any::Any as StdAny;
+
+#[doc(hidden)]
+pub trait CloneToAny {
+ /// Clone `self` into a new `Box<CloneAny>` object.
+ fn clone_to_any(&self) -> Box<CloneAny>;
+
+ /// Clone `self` into a new `Box<CloneAny + Send>` object.
+ fn clone_to_any_send(&self) -> Box<CloneAny + Send> where Self: Send;
+
+ /// Clone `self` into a new `Box<CloneAny + Sync>` object.
+ fn clone_to_any_sync(&self) -> Box<CloneAny + Sync> where Self: Sync;
+
+ /// Clone `self` into a new `Box<CloneAny + Send + Sync>` object.
+ fn clone_to_any_send_sync(&self) -> Box<CloneAny + Send + Sync> where Self: Send + Sync;
+}
+
+impl<T: Any + Clone> CloneToAny for T {
+ fn clone_to_any(&self) -> Box<CloneAny> {
+ Box::new(self.clone())
+ }
+
+ fn clone_to_any_send(&self) -> Box<CloneAny + Send> where Self: Send {
+ Box::new(self.clone())
+ }
+
+ fn clone_to_any_sync(&self) -> Box<CloneAny + Sync> where Self: Sync {
+ Box::new(self.clone())
+ }
+
+ fn clone_to_any_send_sync(&self) -> Box<CloneAny + Send + Sync> where Self: Send + Sync {
+ Box::new(self.clone())
+ }
+}
+
+macro_rules! define {
+ (CloneAny) => {
+ /// A type to emulate dynamic typing.
+ ///
+ /// Every type with no non-`'static` references implements `Any`.
+ define!(CloneAny remainder);
+ };
+ (Any) => {
+ /// A type to emulate dynamic typing with cloning.
+ ///
+ /// Every type with no non-`'static` references that implements `Clone` implements `Any`.
+ define!(Any remainder);
+ };
+ ($t:ident remainder) => {
+ /// See the [`std::any` documentation](https://doc.rust-lang.org/std/any/index.html) for
+ /// more details on `Any` in general.
+ ///
+ /// This trait is not `std::any::Any` but rather a type extending that for this library’s
+ /// purposes so that it can be combined with marker traits like
+ /// <code><a class=trait title=core::marker::Send
+ /// href=http://doc.rust-lang.org/std/marker/trait.Send.html>Send</a></code> and
+ /// <code><a class=trait title=core::marker::Sync
+ /// href=http://doc.rust-lang.org/std/marker/trait.Sync.html>Sync</a></code>.
+ ///
+ define!($t trait);
+ };
+ (CloneAny trait) => {
+ /// See also [`Any`](trait.Any.html) for a version without the `Clone` requirement.
+ pub trait CloneAny: Any + CloneToAny { }
+ impl<T: StdAny + Clone> CloneAny for T { }
+ };
+ (Any trait) => {
+ /// See also [`CloneAny`](trait.CloneAny.html) for a cloneable version of this trait.
+ pub trait Any: StdAny { }
+ impl<T: StdAny> Any for T { }
+ };
+}
+
+macro_rules! impl_clone {
+ ($t:ty, $method:ident) => {
+ impl Clone for Box<$t> {
+ fn clone(&self) -> Box<$t> {
+ (**self).$method()
+ }
+ }
+ }
+}
+
+#[cfg(feature = "nightly")]
+use std::raw::TraitObject;
+
+#[cfg(not(feature = "nightly"))]
+#[repr(C)]
+#[allow(raw_pointer_derive)]
+#[derive(Copy, Clone)]
+struct TraitObject {
+ pub data: *mut (),
+ pub vtable: *mut (),
+}
+
+#[allow(missing_docs)] // Bogus warning (it’s not public outside the crate), ☹
+pub trait UncheckedAnyExt: Any {
+ unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T;
+ unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T;
+ unsafe fn downcast_unchecked<T: Any>(self: Box<Self>) -> Box<T>;
+}
+
+#[doc(hidden)]
+/// A trait for the conversion of an object into a boxed trait object.
+pub trait IntoBox<A: ?Sized + UncheckedAnyExt>: Any {
+ /// Convert self into the appropriate boxed form.
+ fn into_box(self) -> Box<A>;
+}
+
+macro_rules! implement {
+ ($base:ident, $(+ $bounds:ident)*) => {
+ impl<'a> fmt::Debug for &'a ($base $(+ $bounds)*) {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.pad(stringify!(&($base $(+ $bounds)*)))
+ }
+ }
+
+ impl<'a> fmt::Debug for Box<$base $(+ $bounds)*> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.pad(stringify!(Box<$base $(+ $bounds)*>))
+ }
+ }
+
+ impl UncheckedAnyExt for $base $(+ $bounds)* {
+ unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
+ mem::transmute(mem::transmute::<_, TraitObject>(self).data)
+ }
+
+ unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
+ mem::transmute(mem::transmute::<_, TraitObject>(self).data)
+ }
+
+ unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> Box<T> {
+ mem::transmute(mem::transmute::<_, TraitObject>(self).data)
+ }
+ }
+
+ impl<T: $base $(+ $bounds)*> IntoBox<$base $(+ $bounds)*> for T {
+ fn into_box(self) -> Box<$base $(+ $bounds)*> {
+ Box::new(self)
+ }
+ }
+ }
+}
+
+define!(Any);
+implement!(Any,);
+implement!(Any, + Send);
+implement!(Any, + Sync);
+implement!(Any, + Send + Sync);
+implement!(CloneAny,);
+implement!(CloneAny, + Send);
+implement!(CloneAny, + Sync);
+implement!(CloneAny, + Send + Sync);
+
+define!(CloneAny);
+impl_clone!(CloneAny, clone_to_any);
+impl_clone!((CloneAny + Send), clone_to_any_send);
+impl_clone!((CloneAny + Sync), clone_to_any_sync);
+impl_clone!((CloneAny + Send + Sync), clone_to_any_send_sync);
use std::any::TypeId;
use std::marker::PhantomData;
-use raw::{RawAnyMap, Any};
-use unchecked_any::UncheckedAnyExt;
+use raw::RawMap;
+use any::{UncheckedAnyExt, IntoBox, Any};
macro_rules! impl_common_methods {
(
new() => $new:expr;
with_capacity($with_capacity_arg:ident) => $with_capacity:expr;
) => {
- impl $t {
+ impl<A: ?Sized + UncheckedAnyExt> $t<A> {
/// Create an empty collection.
#[inline]
- pub fn new() -> $t {
+ pub fn new() -> $t<A> {
$t {
$field: $new,
}
/// Creates an empty collection with the given initial capacity.
#[inline]
- pub fn with_capacity($with_capacity_arg: usize) -> $t {
+ pub fn with_capacity($with_capacity_arg: usize) -> $t<A> {
$t {
$field: $with_capacity,
}
}
}
-mod unchecked_any;
+pub mod any;
pub mod raw;
/// A collection containing zero or one values for any given type and allowing convenient,
/// type-safe access to those values.
///
+/// The type parameter `A` allows you to use a different value type; normally you will want it to
+/// be `anymap::any::Any`, but there are other choices:
+///
+/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`.
+/// - You can add on `+ Send` and/or `+ Sync` (e.g. `Map<Any + Send>`) to add those bounds.
+///
/// ```rust
/// # use anymap::AnyMap;
/// let mut data = AnyMap::new();
///
/// Values containing non-static references are not permitted.
#[derive(Debug)]
-#[cfg_attr(feature = "clone", derive(Clone))]
-pub struct AnyMap {
- raw: RawAnyMap,
+pub struct Map<A: ?Sized + UncheckedAnyExt = Any> {
+ raw: RawMap<A>,
+}
+
+// #[derive(Clone)] would want A to implement Clone, but in reality it’s only Box<A> that can.
+impl<A: ?Sized + UncheckedAnyExt> Clone for Map<A> where Box<A>: Clone {
+ fn clone(&self) -> Map<A> {
+ Map {
+ raw: self.raw.clone(),
+ }
+ }
}
+/// The most common type of `Map`: just using `Any`.
+///
+/// Why is this a separate type alias rather than a default value for `Map<A>`? `Map::new()`
+/// doesn’t seem to be happy to infer that it should go with the default value.
+/// It’s a bit sad, really. Ah well, I guess this approach will do.
+pub type AnyMap = Map<Any>;
+
impl_common_methods! {
- field: AnyMap.raw;
- new() => RawAnyMap::new();
- with_capacity(capacity) => RawAnyMap::with_capacity(capacity);
+ field: Map.raw;
+ new() => RawMap::new();
+ with_capacity(capacity) => RawMap::with_capacity(capacity);
}
-impl AnyMap {
+impl<A: ?Sized + UncheckedAnyExt> Map<A> {
/// Returns a reference to the value stored in the collection for the type `T`, if it exists.
- pub fn get<T: Any>(&self) -> Option<&T> {
+ pub fn get<T: IntoBox<A>>(&self) -> Option<&T> {
self.raw.get(&TypeId::of::<T>())
.map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
}
/// Returns a mutable reference to the value stored in the collection for the type `T`,
/// if it exists.
- pub fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
+ pub fn get_mut<T: IntoBox<A>>(&mut self) -> Option<&mut T> {
self.raw.get_mut(&TypeId::of::<T>())
.map(|any| unsafe { any.downcast_mut_unchecked::<T>() })
}
/// Sets the value stored in the collection for the type `T`.
/// If the collection already had a value of type `T`, that value is returned.
/// Otherwise, `None` is returned.
- pub fn insert<T: Any>(&mut self, value: T) -> Option<T> {
+ pub fn insert<T: IntoBox<A>>(&mut self, value: T) -> Option<T> {
unsafe {
- self.raw.insert(TypeId::of::<T>(), Box::new(value))
+ self.raw.insert(TypeId::of::<T>(), value.into_box())
.map(|any| *any.downcast_unchecked::<T>())
}
}
/// Removes the `T` value from the collection,
/// returning it if there was one or `None` if there was not.
- pub fn remove<T: Any>(&mut self) -> Option<T> {
+ pub fn remove<T: IntoBox<A>>(&mut self) -> Option<T> {
self.raw.remove(&TypeId::of::<T>())
.map(|any| *unsafe { any.downcast_unchecked::<T>() })
}
/// Returns true if the collection contains a value of type `T`.
#[inline]
- pub fn contains<T: Any>(&self) -> bool {
+ pub fn contains<T: IntoBox<A>>(&self) -> bool {
self.raw.contains_key(&TypeId::of::<T>())
}
/// Gets the entry for the given type in the collection for in-place manipulation
- pub fn entry<T: Any>(&mut self) -> Entry<T> {
+ pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<A, T> {
match self.raw.entry(TypeId::of::<T>()) {
raw::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
inner: e,
}
}
-impl AsRef<RawAnyMap> for AnyMap {
- fn as_ref(&self) -> &RawAnyMap {
+impl<A: ?Sized + UncheckedAnyExt> AsRef<RawMap<A>> for Map<A> {
+ fn as_ref(&self) -> &RawMap<A> {
&self.raw
}
}
-impl AsMut<RawAnyMap> for AnyMap {
- fn as_mut(&mut self) -> &mut RawAnyMap {
+impl<A: ?Sized + UncheckedAnyExt> AsMut<RawMap<A>> for Map<A> {
+ fn as_mut(&mut self) -> &mut RawMap<A> {
&mut self.raw
}
}
-impl Into<RawAnyMap> for AnyMap {
- fn into(self) -> RawAnyMap {
+impl<A: ?Sized + UncheckedAnyExt> Into<RawMap<A>> for Map<A> {
+ fn into(self) -> RawMap<A> {
self.raw
}
}
-/// A view into a single occupied location in an `AnyMap`.
-pub struct OccupiedEntry<'a, V: 'a> {
- inner: raw::OccupiedEntry<'a>,
+/// A view into a single occupied location in an `Map`.
+pub struct OccupiedEntry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
+ inner: raw::OccupiedEntry<'a, A>,
type_: PhantomData<V>,
}
-/// A view into a single empty location in an `AnyMap`.
-pub struct VacantEntry<'a, V: 'a> {
- inner: raw::VacantEntry<'a>,
+/// A view into a single empty location in an `Map`.
+pub struct VacantEntry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
+ inner: raw::VacantEntry<'a, A>,
type_: PhantomData<V>,
}
-/// A view into a single location in an `AnyMap`, which may be vacant or occupied.
-pub enum Entry<'a, V: 'a> {
+/// A view into a single location in an `Map`, which may be vacant or occupied.
+pub enum Entry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
/// An occupied Entry
- Occupied(OccupiedEntry<'a, V>),
+ Occupied(OccupiedEntry<'a, A, V>),
/// A vacant Entry
- Vacant(VacantEntry<'a, V>),
+ Vacant(VacantEntry<'a, A, V>),
}
-impl<'a, V: Any + Clone> Entry<'a, V> {
+impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A> + Clone> Entry<'a, A, V> {
/// Ensures a value is in the entry by inserting the default if empty, and returns
/// a mutable reference to the value in the entry.
pub fn or_insert(self, default: V) -> &'a mut V {
}
}
-impl<'a, V: Any> OccupiedEntry<'a, V> {
+impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> OccupiedEntry<'a, A, V> {
/// Gets a reference to the value in the entry
pub fn get(&self) -> &V {
unsafe { self.inner.get().downcast_ref_unchecked() }
/// Sets the value of the entry, and returns the entry's old value
pub fn insert(&mut self, value: V) -> V {
- unsafe { *self.inner.insert(Box::new(value)).downcast_unchecked() }
+ unsafe { *self.inner.insert(value.into_box()).downcast_unchecked() }
}
/// Takes the value out of the entry, and returns it
}
}
-impl<'a, V: Any> VacantEntry<'a, V> {
+impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> VacantEntry<'a, A, V> {
/// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it
pub fn insert(self, value: V) -> &'a mut V {
- unsafe { self.inner.insert(Box::new(value)).downcast_mut_unchecked() }
+ unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() }
}
}
#[cfg(test)]
mod tests {
- use {AnyMap, Entry};
+ use {Map, AnyMap, Entry};
+ use any::{Any, CloneAny};
#[derive(Clone, Debug, PartialEq)] struct A(i32);
#[derive(Clone, Debug, PartialEq)] struct B(i32);
assert_eq!(map.len(), 7);
}
- #[cfg(feature = "clone")]
#[test]
fn test_clone() {
- let mut map = AnyMap::new();
+ let mut map: Map<CloneAny> = Map::new();
let _ = map.insert(A(1));
let _ = map.insert(B(2));
let _ = map.insert(D(3));
assert_eq!(map2.get::<J>(), Some(&J(6)));
}
- #[cfg(feature = "concurrent")]
#[test]
- fn test_concurrent() {
- fn assert_concurrent<T: Send + Sync>() { }
- assert_concurrent::<AnyMap>();
+ fn test_varieties() {
+ fn assert_send<T: Send>() { }
+ fn assert_sync<T: Sync>() { }
+ fn assert_clone<T: Clone>() { }
+ assert_send::<Map<Any + Send>>();
+ assert_send::<Map<Any + Send + Sync>>();
+ assert_sync::<Map<Any + Sync>>();
+ assert_sync::<Map<Any + Send + Sync>>();
+ assert_send::<Map<CloneAny + Send>>();
+ assert_send::<Map<CloneAny + Send + Sync>>();
+ assert_sync::<Map<CloneAny + Sync>>();
+ assert_sync::<Map<CloneAny + Send + Sync>>();
+ assert_clone::<Map<CloneAny + Send>>();
+ assert_clone::<Map<CloneAny + Send + Sync>>();
+ assert_clone::<Map<CloneAny + Sync>>();
+ assert_clone::<Map<CloneAny + Send + Sync>>();
}
}
-//! The raw form of an AnyMap, allowing untyped access.
+//! The raw form of a `Map`, allowing untyped access.
//!
-//! All relevant details are in the `RawAnyMap` struct.
+//! All relevant details are in the `RawMap` struct.
use std::any::TypeId;
use std::borrow::Borrow;
#[cfg(feature = "nightly")]
use std::ptr;
-pub use self::any::Any;
-
-mod any;
+use any::{Any, UncheckedAnyExt};
#[cfg(feature = "nightly")]
struct TypeIdHasher {
value: u64,
}
-#[cfg_attr(feature = "clone", derive(Clone))]
+#[derive(Clone)]
#[cfg(feature = "nightly")]
struct TypeIdState;
}
-/// The raw, underlying form of an AnyMap.
+/// The raw, underlying form of a `Map`.
///
/// At its essence, this is a wrapper around `HashMap<TypeId, Box<Any>>`, with the portions that
/// would be memory-unsafe removed or marked unsafe. Normal people are expected to use the safe
-/// `AnyMap` interface instead, but there is the occasional use for this such as iteration over the
-/// contents of an `AnyMap`. However, because you will then be dealing with `Any` trait objects, it
+/// `Map` interface instead, but there is the occasional use for this such as iteration over the
+/// contents of an `Map`. However, because you will then be dealing with `Any` trait objects, it
/// doesn’t tend to be so very useful. Still, if you need it, it’s here.
#[derive(Debug)]
-#[cfg_attr(feature = "clone", derive(Clone))]
-pub struct RawAnyMap {
+pub struct RawMap<A: ?Sized + UncheckedAnyExt = Any> {
#[cfg(feature = "nightly")]
- inner: HashMap<TypeId, Box<Any>, TypeIdState>,
+ inner: HashMap<TypeId, Box<A>, TypeIdState>,
#[cfg(not(feature = "nightly"))]
- inner: HashMap<TypeId, Box<Any>>,
+ inner: HashMap<TypeId, Box<A>>,
}
-impl Default for RawAnyMap {
- fn default() -> RawAnyMap {
- RawAnyMap::new()
+// #[derive(Clone)] would want A to implement Clone, but in reality it’s only Box<A> that can.
+impl<A: ?Sized + UncheckedAnyExt> Clone for RawMap<A> where Box<A>: Clone {
+ fn clone(&self) -> RawMap<A> {
+ RawMap {
+ inner: self.inner.clone(),
+ }
+ }
+}
+
+impl<A: ?Sized + UncheckedAnyExt> Default for RawMap<A> {
+ fn default() -> RawMap<A> {
+ RawMap::new()
}
}
#[cfg(feature = "nightly")]
impl_common_methods! {
- field: RawAnyMap.inner;
+ field: RawMap.inner;
new() => HashMap::with_hash_state(TypeIdState);
with_capacity(capacity) => HashMap::with_capacity_and_hash_state(capacity, TypeIdState);
}
#[cfg(not(feature = "nightly"))]
impl_common_methods! {
- field: RawAnyMap.inner;
+ field: RawMap.inner;
new() => HashMap::new();
with_capacity(capacity) => HashMap::with_capacity(capacity);
}
-/// RawAnyMap iterator.
+/// RawMap iterator.
#[derive(Clone)]
-pub struct Iter<'a> {
- inner: hash_map::Iter<'a, TypeId, Box<Any>>,
+pub struct Iter<'a, A: ?Sized + UncheckedAnyExt> {
+ inner: hash_map::Iter<'a, TypeId, Box<A>>,
}
-impl<'a> Iterator for Iter<'a> {
- type Item = &'a Any;
- #[inline] fn next(&mut self) -> Option<&'a Any> { self.inner.next().map(|x| &**x.1) }
+impl<'a, A: ?Sized + UncheckedAnyExt> Iterator for Iter<'a, A> {
+ type Item = &'a A;
+ #[inline] fn next(&mut self) -> Option<&'a A> { self.inner.next().map(|x| &**x.1) }
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
-impl<'a> ExactSizeIterator for Iter<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> ExactSizeIterator for Iter<'a, A> {
#[inline] fn len(&self) -> usize { self.inner.len() }
}
-/// RawAnyMap mutable iterator.
-pub struct IterMut<'a> {
- inner: hash_map::IterMut<'a, TypeId, Box<Any>>,
+/// RawMap mutable iterator.
+pub struct IterMut<'a, A: ?Sized + UncheckedAnyExt> {
+ inner: hash_map::IterMut<'a, TypeId, Box<A>>,
}
-impl<'a> Iterator for IterMut<'a> {
- type Item = &'a mut Any;
- #[inline] fn next(&mut self) -> Option<&'a mut Any> { self.inner.next().map(|x| &mut **x.1) }
+impl<'a, A: ?Sized + UncheckedAnyExt> Iterator for IterMut<'a, A> {
+ type Item = &'a mut A;
+ #[inline] fn next(&mut self) -> Option<&'a mut A> { self.inner.next().map(|x| &mut **x.1) }
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
-impl<'a> ExactSizeIterator for IterMut<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> ExactSizeIterator for IterMut<'a, A> {
#[inline] fn len(&self) -> usize { self.inner.len() }
}
-/// RawAnyMap move iterator.
-pub struct IntoIter {
- inner: hash_map::IntoIter<TypeId, Box<Any>>,
+/// RawMap move iterator.
+pub struct IntoIter<A: ?Sized + UncheckedAnyExt> {
+ inner: hash_map::IntoIter<TypeId, Box<A>>,
}
-impl Iterator for IntoIter {
- type Item = Box<Any>;
- #[inline] fn next(&mut self) -> Option<Box<Any>> { self.inner.next().map(|x| x.1) }
+impl<A: ?Sized + UncheckedAnyExt> Iterator for IntoIter<A> {
+ type Item = Box<A>;
+ #[inline] fn next(&mut self) -> Option<Box<A>> { self.inner.next().map(|x| x.1) }
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
-impl ExactSizeIterator for IntoIter {
+impl<A: ?Sized + UncheckedAnyExt> ExactSizeIterator for IntoIter<A> {
#[inline] fn len(&self) -> usize { self.inner.len() }
}
-/// RawAnyMap drain iterator.
+/// RawMap drain iterator.
#[cfg(feature = "nightly")]
-pub struct Drain<'a> {
- inner: hash_map::Drain<'a, TypeId, Box<Any>>,
+pub struct Drain<'a, A: ?Sized + UncheckedAnyExt> {
+ inner: hash_map::Drain<'a, TypeId, Box<A>>,
}
#[cfg(feature = "nightly")]
-impl<'a> Iterator for Drain<'a> {
- type Item = Box<Any>;
- #[inline] fn next(&mut self) -> Option<Box<Any>> { self.inner.next().map(|x| x.1) }
+impl<'a, A: ?Sized + UncheckedAnyExt> Iterator for Drain<'a, A> {
+ type Item = Box<A>;
+ #[inline] fn next(&mut self) -> Option<Box<A>> { self.inner.next().map(|x| x.1) }
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
#[cfg(feature = "nightly")]
-impl<'a> ExactSizeIterator for Drain<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> ExactSizeIterator for Drain<'a, A> {
#[inline] fn len(&self) -> usize { self.inner.len() }
}
-impl RawAnyMap {
+impl<A: ?Sized + UncheckedAnyExt> RawMap<A> {
/// An iterator visiting all entries in arbitrary order.
///
/// Iterator element type is `&Any`.
#[inline]
- pub fn iter(&self) -> Iter {
+ pub fn iter(&self) -> Iter<A> {
Iter {
inner: self.inner.iter(),
}
///
/// Iterator element type is `&mut Any`.
#[inline]
- pub fn iter_mut(&mut self) -> IterMut {
+ pub fn iter_mut(&mut self) -> IterMut<A> {
IterMut {
inner: self.inner.iter_mut(),
}
}
- /// Creates a consuming iterator, that is, one that moves each item
- /// out of the map in arbitrary order. The map cannot be used after
- /// calling this.
- ///
- /// Iterator element type is `Box<Any>`.
- #[inline]
- pub fn into_iter(self) -> IntoIter {
- IntoIter {
- inner: self.inner.into_iter(),
- }
- }
-
/// Clears the map, returning all items as an iterator.
///
/// Iterator element type is `Box<Any>`.
/// Keeps the allocated memory for reuse.
#[inline]
#[cfg(feature = "nightly")]
- pub fn drain(&mut self) -> Drain {
+ pub fn drain(&mut self) -> Drain<A> {
Drain {
inner: self.inner.drain(),
}
}
/// Gets the entry for the given type in the collection for in-place manipulation.
- pub fn entry(&mut self, key: TypeId) -> Entry {
+ pub fn entry(&mut self, key: TypeId) -> Entry<A> {
match self.inner.entry(key) {
hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
inner: e,
///
/// The key may be any borrowed form of the map's key type, but `Hash` and `Eq` on the borrowed
/// form *must* match those for the key type.
- pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&Any>
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&A>
where TypeId: Borrow<Q>, Q: Hash + Eq {
self.inner.get(k).map(|x| &**x)
}
///
/// The key may be any borrowed form of the map's key type, but `Hash` and `Eq` on the borrowed
/// form *must* match those for the key type.
- pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut Any>
+ pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut A>
where TypeId: Borrow<Q>, Q: Hash + Eq {
self.inner.get_mut(k).map(|x| &mut **x)
}
///
/// It is the caller’s responsibility to ensure that the key corresponds with the type ID of
/// the value. If they do not, memory safety may be violated.
- pub unsafe fn insert(&mut self, key: TypeId, value: Box<Any>) -> Option<Box<Any>> {
+ pub unsafe fn insert(&mut self, key: TypeId, value: Box<A>) -> Option<Box<A>> {
self.inner.insert(key, value)
}
///
/// The key may be any borrowed form of the map's key type, but `Hash` and `Eq` on the borrowed
/// form *must* match those for the key type.
- pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<Box<Any>>
+ pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<Box<A>>
where TypeId: Borrow<Q>, Q: Hash + Eq {
self.inner.remove(k)
}
}
-impl<Q> Index<Q> for RawAnyMap where TypeId: Borrow<Q>, Q: Eq + Hash {
- type Output = Any;
+impl<A: ?Sized + UncheckedAnyExt, Q> Index<Q> for RawMap<A> where TypeId: Borrow<Q>, Q: Eq + Hash {
+ type Output = A;
- fn index<'a>(&'a self, index: Q) -> &'a Any {
+ fn index<'a>(&'a self, index: Q) -> &'a A {
self.get(&index).expect("no entry found for key")
}
}
-impl<Q> IndexMut<Q> for RawAnyMap where TypeId: Borrow<Q>, Q: Eq + Hash {
- fn index_mut<'a>(&'a mut self, index: Q) -> &'a mut Any {
+impl<A: ?Sized + UncheckedAnyExt, Q> IndexMut<Q> for RawMap<A> where TypeId: Borrow<Q>, Q: Eq + Hash {
+ fn index_mut<'a>(&'a mut self, index: Q) -> &'a mut A {
self.get_mut(&index).expect("no entry found for key")
}
}
-impl IntoIterator for RawAnyMap {
- type Item = Box<Any>;
- type IntoIter = IntoIter;
+impl<A: ?Sized + UncheckedAnyExt> IntoIterator for RawMap<A> {
+ type Item = Box<A>;
+ type IntoIter = IntoIter<A>;
- fn into_iter(self) -> IntoIter {
- self.into_iter()
+ fn into_iter(self) -> IntoIter<A> {
+ IntoIter {
+ inner: self.inner.into_iter(),
+ }
}
}
-/// A view into a single occupied location in a `RawAnyMap`.
-pub struct OccupiedEntry<'a> {
- inner: hash_map::OccupiedEntry<'a, TypeId, Box<Any>>,
+/// A view into a single occupied location in a `RawMap`.
+pub struct OccupiedEntry<'a, A: ?Sized + UncheckedAnyExt> {
+ inner: hash_map::OccupiedEntry<'a, TypeId, Box<A>>,
}
-/// A view into a single empty location in a `RawAnyMap`.
-pub struct VacantEntry<'a> {
- inner: hash_map::VacantEntry<'a, TypeId, Box<Any>>,
+/// A view into a single empty location in a `RawMap`.
+pub struct VacantEntry<'a, A: ?Sized + UncheckedAnyExt> {
+ inner: hash_map::VacantEntry<'a, TypeId, Box<A>>,
}
-/// A view into a single location in an AnyMap, which may be vacant or occupied.
-pub enum Entry<'a> {
+/// A view into a single location in a `RawMap`, which may be vacant or occupied.
+pub enum Entry<'a, A: ?Sized + UncheckedAnyExt> {
/// An occupied Entry
- Occupied(OccupiedEntry<'a>),
+ Occupied(OccupiedEntry<'a, A>),
/// A vacant Entry
- Vacant(VacantEntry<'a>),
+ Vacant(VacantEntry<'a, A>),
}
-impl<'a> Entry<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> Entry<'a, A> {
/// Ensures a value is in the entry by inserting the default if empty, and returns
/// a mutable reference to the value in the entry.
///
/// It is the caller’s responsibility to ensure that the key of the entry corresponds with
/// the type ID of `value`. If they do not, memory safety may be violated.
- pub unsafe fn or_insert(self, default: Box<Any>) -> &'a mut Any {
+ pub unsafe fn or_insert(self, default: Box<A>) -> &'a mut A {
match self {
Entry::Occupied(inner) => inner.into_mut(),
Entry::Vacant(inner) => inner.insert(default),
///
/// It is the caller’s responsibility to ensure that the key of the entry corresponds with
/// the type ID of `value`. If they do not, memory safety may be violated.
- pub unsafe fn or_insert_with<F: FnOnce() -> Box<Any>>(self, default: F) -> &'a mut Any {
+ pub unsafe fn or_insert_with<F: FnOnce() -> Box<A>>(self, default: F) -> &'a mut A {
match self {
Entry::Occupied(inner) => inner.into_mut(),
Entry::Vacant(inner) => inner.insert(default()),
}
}
-impl<'a> OccupiedEntry<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> OccupiedEntry<'a, A> {
/// Gets a reference to the value in the entry.
- pub fn get(&self) -> &Any {
+ pub fn get(&self) -> &A {
&**self.inner.get()
}
/// Gets a mutable reference to the value in the entry.
- pub fn get_mut(&mut self) -> &mut Any {
+ pub fn get_mut(&mut self) -> &mut A {
&mut **self.inner.get_mut()
}
/// Converts the OccupiedEntry into a mutable reference to the value in the entry
/// with a lifetime bound to the collection itself.
- pub fn into_mut(self) -> &'a mut Any {
+ pub fn into_mut(self) -> &'a mut A {
&mut **self.inner.into_mut()
}
///
/// It is the caller’s responsibility to ensure that the key of the entry corresponds with
/// the type ID of `value`. If they do not, memory safety may be violated.
- pub unsafe fn insert(&mut self, value: Box<Any>) -> Box<Any> {
+ pub unsafe fn insert(&mut self, value: Box<A>) -> Box<A> {
self.inner.insert(value)
}
/// Takes the value out of the entry, and returns it.
- pub fn remove(self) -> Box<Any> {
+ pub fn remove(self) -> Box<A> {
self.inner.remove()
}
}
-impl<'a> VacantEntry<'a> {
+impl<'a, A: ?Sized + UncheckedAnyExt> VacantEntry<'a, A> {
/// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it
///
/// It is the caller’s responsibility to ensure that the key of the entry corresponds with
/// the type ID of `value`. If they do not, memory safety may be violated.
- pub unsafe fn insert(self, value: Box<Any>) -> &'a mut Any {
+ pub unsafe fn insert(self, value: Box<A>) -> &'a mut A {
&mut **self.inner.insert(value)
}
}
+++ /dev/null
-use std::fmt;
-use std::any::Any as StdAny;
-
-#[cfg(feature = "clone")]
-#[doc(hidden)]
-pub trait CloneToAny {
- /// Clone `self` into a new `Box<Any>` object.
- fn clone_to_any(&self) -> Box<Any>;
-}
-
-#[cfg(feature = "clone")]
-impl<T: Any + Clone> CloneToAny for T {
- fn clone_to_any(&self) -> Box<Any> {
- Box::new(self.clone())
- }
-}
-
-macro_rules! define_any {
- (#[$m:meta] $t:item $i:item) => {
- /// A type to emulate dynamic typing.
- ///
- /// Every suitable type with no non-`'static` references implements `Any`. See the
- /// [`std::any` documentation](https://doc.rust-lang.org/std/any/index.html) for more
- /// details on `Any` in general.
- ///
- /// This trait is not `std::any::Any` but rather a type extending that for this library’s
- /// purposes; most specifically, there are a couple of Cargo features that can be enabled
- /// which will alter the constraints of what comprises a suitable type:
- ///
- /// <table>
- /// <thead>
- /// <tr>
- /// <th title="The name of the Cargo feature to enable">Feature name</th>
- /// <th title="If a type doesn’t satisfy these bounds, it won’t implement Any">Additional bounds</th>
- /// <th title="Were these docs built with this feature enabled?">Enabled in these docs?</th>
- /// </tr>
- /// </thead>
- /// <tbody>
- /// <tr>
- /// <th><code>clone</code></th>
- /// <td><code><a class=trait title=core::clone::Clone
- /// href=http://doc.rust-lang.org/std/clone/trait.Clone.html
- /// >Clone</a></code></td>
- #[cfg_attr(feature = "clone", doc = " <td>Yes</td>")]
- #[cfg_attr(not(feature = "clone"), doc = " <td>No</td>")]
- /// </tr>
- /// <tr>
- /// <th><code>concurrent</code></th>
- /// <td><code><a class=trait title=core::marker::Send
- /// href=http://doc.rust-lang.org/std/marker/trait.Send.html
- /// >Send</a> + <a class=trait title=core::marker::Sync
- /// href=http://doc.rust-lang.org/std/marker/trait.Sync.html
- /// >Sync</a></code></td>
- #[cfg_attr(feature = "concurrent", doc = " <td>Yes</td>")]
- #[cfg_attr(not(feature = "concurrent"), doc = " <td>No</td>")]
- /// </tr>
- /// </tbody>
- /// </table>
- #[$m] $t
- #[$m] $i
- }
-}
-
-define_any! {
- #[cfg(all(not(feature = "clone"), not(feature = "concurrent")))]
- pub trait Any: StdAny { }
- impl<T: StdAny> Any for T { }
-}
-
-define_any! {
- #[cfg(all(feature = "clone", not(feature = "concurrent")))]
- pub trait Any: StdAny + CloneToAny { }
- impl<T: StdAny + Clone> Any for T { }
-}
-
-define_any! {
- #[cfg(all(not(feature = "clone"), feature = "concurrent"))]
- pub trait Any: StdAny + Send + Sync { }
- impl<T: StdAny + Send + Sync> Any for T { }
-}
-
-define_any! {
- #[cfg(all(feature = "clone", feature = "concurrent"))]
- pub trait Any: StdAny + CloneToAny + Send + Sync { }
- impl<T: StdAny + Clone + Send + Sync> Any for T { }
-}
-
-#[cfg(feature = "clone")]
-impl Clone for Box<Any> {
- fn clone(&self) -> Box<Any> {
- (**self).clone_to_any()
- }
-}
-
-impl<'a> fmt::Debug for &'a Any {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.pad("&Any")
- }
-}
-
-impl<'a> fmt::Debug for Box<Any> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.pad("Box<Any>")
- }
-}
+++ /dev/null
-use raw::Any;
-use std::mem;
-#[cfg(feature = "nightly")]
-use std::raw::TraitObject;
-
-#[cfg(not(feature = "nightly"))]
-#[repr(C)]
-#[allow(raw_pointer_derive)]
-#[derive(Copy, Clone)]
-struct TraitObject {
- pub data: *mut (),
- pub vtable: *mut (),
-}
-
-#[allow(missing_docs)] // Bogus warning (it’s not public outside the crate), ☹
-pub trait UncheckedAnyExt {
- unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T;
- unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T;
- unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> Box<T>;
-}
-
-impl UncheckedAnyExt for Any {
- unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
- mem::transmute(mem::transmute::<_, TraitObject>(self).data)
- }
-
- unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
- mem::transmute(mem::transmute::<_, TraitObject>(self).data)
- }
-
- unsafe fn downcast_unchecked<T: 'static>(self: Box<Any>) -> Box<T> {
- mem::transmute(mem::transmute::<_, TraitObject>(self).data)
- }
-}