//! This crate provides the `AnyMap` type, a safe and convenient store for one value of each type. #![warn(missing_docs, unused_results)] use std::any::TypeId; use std::marker::PhantomData; use raw::RawMap; use any::{UncheckedAnyExt, IntoBox}; pub use any::{Any, CloneAny}; macro_rules! impl_common_methods { ( field: $t:ident.$field:ident; new() => $new:expr; with_capacity($with_capacity_arg:ident) => $with_capacity:expr; ) => { impl $t { /// Create an empty collection. #[inline] pub fn new() -> $t { $t { $field: $new, } } /// Creates an empty collection with the given initial capacity. #[inline] pub fn with_capacity($with_capacity_arg: usize) -> $t { $t { $field: $with_capacity, } } /// Returns the number of elements the collection can hold without reallocating. #[inline] pub fn capacity(&self) -> usize { self.$field.capacity() } /// Reserves capacity for at least `additional` more elements to be inserted /// in the collection. The collection may reserve more space to avoid /// frequent reallocations. /// /// # Panics /// /// Panics if the new allocation size overflows `usize`. #[inline] pub fn reserve(&mut self, additional: usize) { self.$field.reserve(additional) } /// Shrinks the capacity of the collection as much as possible. It will drop /// down as much as possible while maintaining the internal rules /// and possibly leaving some space in accordance with the resize policy. #[inline] pub fn shrink_to_fit(&mut self) { self.$field.shrink_to_fit() } /// Returns the number of items in the collection. #[inline] pub fn len(&self) -> usize { self.$field.len() } /// Returns true if there are no items in the collection. #[inline] pub fn is_empty(&self) -> bool { self.$field.is_empty() } /// Removes all items from the collection. Keeps the allocated memory for reuse. #[inline] pub fn clear(&mut self) { self.$field.clear() } } impl Default for $t { #[inline] fn default() -> $t { $t::new() } } } } 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`) to add those bounds. /// /// ```rust /// # use anymap::AnyMap; /// let mut data = AnyMap::new(); /// assert_eq!(data.get(), None::<&i32>); /// data.insert(42i32); /// assert_eq!(data.get(), Some(&42i32)); /// data.remove::(); /// assert_eq!(data.get::(), None); /// /// #[derive(Clone, PartialEq, Debug)] /// struct Foo { /// str: String, /// } /// /// assert_eq!(data.get::(), None); /// data.insert(Foo { str: format!("foo") }); /// assert_eq!(data.get(), Some(&Foo { str: format!("foo") })); /// data.get_mut::().map(|foo| foo.str.push('t')); /// assert_eq!(&*data.get::().unwrap().str, "foot"); /// ``` /// /// Values containing non-static references are not permitted. #[derive(Debug)] pub struct Map { raw: RawMap, } // #[derive(Clone)] would want A to implement Clone, but in reality it’s only Box that can. impl Clone for Map where Box: Clone { #[inline] fn clone(&self) -> Map { 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`? `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; impl_common_methods! { field: Map.raw; new() => RawMap::new(); with_capacity(capacity) => RawMap::with_capacity(capacity); } impl Map { /// Returns a reference to the value stored in the collection for the type `T`, if it exists. #[inline] pub fn get>(&self) -> Option<&T> { self.raw.get(&TypeId::of::()) .map(|any| unsafe { any.downcast_ref_unchecked::() }) } /// Returns a mutable reference to the value stored in the collection for the type `T`, /// if it exists. #[inline] pub fn get_mut>(&mut self) -> Option<&mut T> { self.raw.get_mut(&TypeId::of::()) .map(|any| unsafe { any.downcast_mut_unchecked::() }) } /// 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. #[inline] pub fn insert>(&mut self, value: T) -> Option { unsafe { self.raw.insert(TypeId::of::(), value.into_box()) .map(|any| *any.downcast_unchecked::()) } } /// Removes the `T` value from the collection, /// returning it if there was one or `None` if there was not. #[inline] pub fn remove>(&mut self) -> Option { self.raw.remove(&TypeId::of::()) .map(|any| *unsafe { any.downcast_unchecked::() }) } /// Returns true if the collection contains a value of type `T`. #[inline] pub fn contains>(&self) -> bool { self.raw.contains_key(&TypeId::of::()) } /// Gets the entry for the given type in the collection for in-place manipulation #[inline] pub fn entry>(&mut self) -> Entry { match self.raw.entry(TypeId::of::()) { raw::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry { inner: e, type_: PhantomData, }), raw::Entry::Vacant(e) => Entry::Vacant(VacantEntry { inner: e, type_: PhantomData, }), } } } impl AsRef> for Map { #[inline] fn as_ref(&self) -> &RawMap { &self.raw } } impl AsMut> for Map { #[inline] fn as_mut(&mut self) -> &mut RawMap { &mut self.raw } } impl Into> for Map { #[inline] fn into(self) -> RawMap { self.raw } } /// 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, } /// 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, } /// 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, A, V>), /// A vacant Entry Vacant(VacantEntry<'a, A, V>), } impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox> 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. #[inline] pub fn or_insert(self, default: V) -> &'a mut V { match self { Entry::Occupied(inner) => inner.into_mut(), Entry::Vacant(inner) => inner.insert(default), } } /// Ensures a value is in the entry by inserting the result of the default function if empty, /// and returns a mutable reference to the value in the entry. #[inline] pub fn or_insert_with V>(self, default: F) -> &'a mut V { match self { Entry::Occupied(inner) => inner.into_mut(), Entry::Vacant(inner) => inner.insert(default()), } } } impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox> OccupiedEntry<'a, A, V> { /// Gets a reference to the value in the entry #[inline] pub fn get(&self) -> &V { unsafe { self.inner.get().downcast_ref_unchecked() } } /// Gets a mutable reference to the value in the entry #[inline] pub fn get_mut(&mut self) -> &mut V { unsafe { self.inner.get_mut().downcast_mut_unchecked() } } /// Converts the OccupiedEntry into a mutable reference to the value in the entry /// with a lifetime bound to the collection itself #[inline] pub fn into_mut(self) -> &'a mut V { unsafe { self.inner.into_mut().downcast_mut_unchecked() } } /// Sets the value of the entry, and returns the entry's old value #[inline] pub fn insert(&mut self, value: V) -> V { unsafe { *self.inner.insert(value.into_box()).downcast_unchecked() } } /// Takes the value out of the entry, and returns it #[inline] pub fn remove(self) -> V { unsafe { *self.inner.remove().downcast_unchecked() } } } impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox> VacantEntry<'a, A, V> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it #[inline] pub fn insert(self, value: V) -> &'a mut V { unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() } } } #[cfg(test)] mod tests { use {Map, AnyMap, Entry}; use any::{Any, CloneAny}; #[derive(Clone, Debug, PartialEq)] struct A(i32); #[derive(Clone, Debug, PartialEq)] struct B(i32); #[derive(Clone, Debug, PartialEq)] struct C(i32); #[derive(Clone, Debug, PartialEq)] struct D(i32); #[derive(Clone, Debug, PartialEq)] struct E(i32); #[derive(Clone, Debug, PartialEq)] struct F(i32); #[derive(Clone, Debug, PartialEq)] struct J(i32); macro_rules! test_entry { ($name:ident, $init:ty) => { #[test] fn $name() { let mut map = <$init>::new(); assert_eq!(map.insert(A(10)), None); assert_eq!(map.insert(B(20)), None); assert_eq!(map.insert(C(30)), None); assert_eq!(map.insert(D(40)), None); assert_eq!(map.insert(E(50)), None); assert_eq!(map.insert(F(60)), None); // Existing key (insert) match map.entry::() { Entry::Vacant(_) => unreachable!(), Entry::Occupied(mut view) => { assert_eq!(view.get(), &A(10)); assert_eq!(view.insert(A(100)), A(10)); } } assert_eq!(map.get::().unwrap(), &A(100)); assert_eq!(map.len(), 6); // Existing key (update) match map.entry::() { Entry::Vacant(_) => unreachable!(), Entry::Occupied(mut view) => { let v = view.get_mut(); let new_v = B(v.0 * 10); *v = new_v; } } assert_eq!(map.get::().unwrap(), &B(200)); assert_eq!(map.len(), 6); // Existing key (remove) match map.entry::() { Entry::Vacant(_) => unreachable!(), Entry::Occupied(view) => { assert_eq!(view.remove(), C(30)); } } assert_eq!(map.get::(), None); assert_eq!(map.len(), 5); // Inexistent key (insert) match map.entry::() { Entry::Occupied(_) => unreachable!(), Entry::Vacant(view) => { assert_eq!(*view.insert(J(1000)), J(1000)); } } assert_eq!(map.get::().unwrap(), &J(1000)); assert_eq!(map.len(), 6); // Entry.or_insert on existing key map.entry::().or_insert(B(71)).0 += 1; assert_eq!(map.get::().unwrap(), &B(201)); assert_eq!(map.len(), 6); // Entry.or_insert on nonexisting key map.entry::().or_insert(C(300)).0 += 1; assert_eq!(map.get::().unwrap(), &C(301)); assert_eq!(map.len(), 7); } } } test_entry!(test_entry_any, AnyMap); test_entry!(test_entry_cloneany, Map); #[test] fn test_default() { let map: AnyMap = Default::default(); assert_eq!(map.len(), 0); } #[test] fn test_clone() { let mut map: Map = Map::new(); let _ = map.insert(A(1)); let _ = map.insert(B(2)); let _ = map.insert(D(3)); let _ = map.insert(E(4)); let _ = map.insert(F(5)); let _ = map.insert(J(6)); let map2 = map.clone(); assert_eq!(map2.len(), 6); assert_eq!(map2.get::(), Some(&A(1))); assert_eq!(map2.get::(), Some(&B(2))); assert_eq!(map2.get::(), None); assert_eq!(map2.get::(), Some(&D(3))); assert_eq!(map2.get::(), Some(&E(4))); assert_eq!(map2.get::(), Some(&F(5))); assert_eq!(map2.get::(), Some(&J(6))); } #[test] fn test_varieties() { fn assert_send() { } fn assert_sync() { } fn assert_clone() { } fn assert_debug() { } assert_send::>(); assert_send::>(); assert_sync::>(); assert_sync::>(); assert_debug::>(); assert_debug::>(); assert_debug::>(); assert_debug::>(); assert_send::>(); assert_send::>(); assert_sync::>(); assert_sync::>(); assert_clone::>(); assert_clone::>(); assert_clone::>(); assert_clone::>(); assert_debug::>(); assert_debug::>(); assert_debug::>(); assert_debug::>(); } }