X-Git-Url: https://git.chrismorgan.info/anymap/blobdiff_plain/764038fe6e3f5a28270a874bce2561924a316a20..2bcbd9c551d256e06e3e3044a2a99f79a7946449:/src/lib.rs diff --git a/src/lib.rs b/src/lib.rs index a53a2d8..d4f227a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,22 @@ -//! This crate provides the `AnyMap` type, a safe and convenient store for one value of each type. +//! This crate provides a safe and convenient store for one value of each type. +//! +//! Your starting point is [`Map`]. It has an example. #![warn(missing_docs, unused_results)] -use std::any::{Any, TypeId}; -use std::marker::PhantomData; +#![cfg_attr(not(feature = "std"), no_std)] + +use core::any::{Any, TypeId}; +use core::marker::PhantomData; + +#[cfg(not(any(feature = "std", feature = "hashbrown")))] +compile_error!("anymap: you must enable the 'std' feature or the 'hashbrown' feature"); + +#[cfg(not(feature = "std"))] +extern crate alloc; + +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; use raw::RawMap; use any::{UncheckedAnyExt, IntoBox}; @@ -58,6 +71,10 @@ macro_rules! impl_common_methods { self.$field.shrink_to_fit() } + // Additional stable methods (as of 1.60.0-nightly) that could be added: + // try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> (1.57.0) + // shrink_to(&mut self, min_capacity: usize) (1.56.0) + /// Returns the number of items in the collection. #[inline] pub fn len(&self) -> usize { @@ -93,14 +110,29 @@ pub mod raw; /// 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 `std::any::Any`, but there are other choices: +/// be `core::any::Any` (also known as `std::any::Any`), but there are other choices: +/// +/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with that, you +/// can only add types that implement `Clone` to the map. +/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map`) to add those auto +/// traits. +/// +/// Cumulatively, there are thus six forms of map: +/// +/// - [Map]<dyn [core::any::Any]>, also spelled [`AnyMap`] for convenience. +/// - [Map]<dyn [core::any::Any] + Send> +/// - [Map]<dyn [core::any::Any] + Send + Sync> +/// - [Map]<dyn [CloneAny]> +/// - [Map]<dyn [CloneAny] + Send> +/// - [Map]<dyn [CloneAny] + Send + Sync> /// -/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`. -/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map`) to add those bounds. +/// ## Example +/// +/// (Here using the [`AnyMap`] convenience alias; the first line could use +/// [anymap::Map][Map]::<[core::any::Any]>::new() instead if desired.) /// /// ```rust -/// # use anymap::AnyMap; -/// let mut data = AnyMap::new(); +/// let mut data = anymap::AnyMap::new(); /// assert_eq!(data.get(), None::<&i32>); /// data.insert(42i32); /// assert_eq!(data.get(), Some(&42i32)); @@ -135,7 +167,7 @@ impl Clone for Map where Box: Clone { } } -/// The most common type of `Map`: just using `Any`. +/// The most common type of `Map`: just using `Any`; [Map]<dyn [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. @@ -175,6 +207,8 @@ impl Map { } } + // rustc 1.60.0-nightly has another method try_insert that would be nice to add when stable. + /// Removes the `T` value from the collection, /// returning it if there was one or `None` if there was not. #[inline] @@ -205,6 +239,15 @@ impl Map { } } +impl Extend> for Map { + #[inline] + fn extend>>(&mut self, iter: T) { + for item in iter { + let _ = unsafe { self.raw.insert(item.type_id(), item) }; + } + } +} + impl AsRef> for Map { #[inline] fn as_ref(&self) -> &RawMap { @@ -219,10 +262,10 @@ impl AsMut> for Map { } } -impl Into> for Map { +impl From> for RawMap { #[inline] - fn into(self) -> RawMap { - self.raw + fn from(map: Map) -> RawMap { + map.raw } } @@ -427,7 +470,7 @@ mod tests { fn assert_send() { } fn assert_sync() { } fn assert_clone() { } - fn assert_debug() { } + fn assert_debug() { } assert_send::>(); assert_send::>(); assert_sync::>();