More documentation tweaks to clarify and explain

This commit is contained in:
Chris Morgan 2022-01-25 19:18:34 +11:00
parent 764038fe6e
commit 2d5be08822
2 changed files with 25 additions and 8 deletions

View file

@ -14,7 +14,7 @@ What this means is that in an ``AnyMap`` you may store zero or one values for ev
This library uses a fair bit of unsafe code for several reasons: This library uses a fair bit of unsafe code for several reasons:
- To support Any and CloneAny, unsafe code is required (because of how the `downcast` methods are defined in `impl dyn Any` rather than being trait methods; I think this is kind of a historical detail of the structure of `std::any::Any`); if you wanted to ditch `Clone` support this unsafety could be removed. - To support `CloneAny`, unsafe code is required (because the downcast methods are defined on `dyn Any` rather than being trait methods); if you wanted to ditch `Clone` support this unsafety could be removed.
- In the interests of performance, skipping various checks that are unnecessary because of the invariants of the data structure (no need to check the type ID when its been statically ensured by being used as the hash map key). - In the interests of performance, skipping various checks that are unnecessary because of the invariants of the data structure (no need to check the type ID when its been statically ensured by being used as the hash map key).
@ -22,7 +22,7 @@ This library uses a fair bit of unsafe code for several reasons:
Its not possible to remove all unsafety from this library without also removing some of the functionality. Still, at the cost of the `CloneAny` functionality and the raw interface, you can definitely remove all unsafe code. Heres how you could do it: Its not possible to remove all unsafety from this library without also removing some of the functionality. Still, at the cost of the `CloneAny` functionality and the raw interface, you can definitely remove all unsafe code. Heres how you could do it:
- Remove the genericness of it all; - Remove the genericness of it all (choose `dyn Any`, `dyn Any + Send` or `dyn Any + Send + Sync` and stick with it);
- Merge `anymap::raw` into the normal interface, flattening it; - Merge `anymap::raw` into the normal interface, flattening it;
- Change things like `.map(|any| unsafe { any.downcast_unchecked() })` to `.and_then(|any| any.downcast())` (performance cost: one extra superfluous type ID comparison, indirect). - Change things like `.map(|any| unsafe { any.downcast_unchecked() })` to `.and_then(|any| any.downcast())` (performance cost: one extra superfluous type ID comparison, indirect).

View file

@ -1,4 +1,6 @@
//! 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)] #![warn(missing_docs, unused_results)]
@ -95,12 +97,27 @@ pub mod raw;
/// The type parameter `A` allows you to use a different value type; normally you will want it to /// 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 `std::any::Any`, but there are other choices:
/// ///
/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`. /// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with that, you
/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map<dyn Any + Send>`) to add those bounds. /// can only add types that implement `Clone` to the map.
/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map<dyn Any + Send>`) to add those auto
/// traits.
///
/// Cumulatively, there are thus six forms of map:
///
/// - <code>[Map]&lt;dyn [std::any::Any]&gt;</code>, also spelled [`AnyMap`] for convenience.
/// - <code>[Map]&lt;dyn [std::any::Any] + Send&gt;</code>
/// - <code>[Map]&lt;dyn [std::any::Any] + Send + Sync&gt;</code>
/// - <code>[Map]&lt;dyn [CloneAny]&gt;</code>
/// - <code>[Map]&lt;dyn [CloneAny] + Send&gt;</code>
/// - <code>[Map]&lt;dyn [CloneAny] + Send + Sync&gt;</code>
///
/// ## Example
///
/// (Here using the [`AnyMap`] convenience alias; the first line could use
/// <code>[anymap::Map][Map]::&lt;[std::any::Any]&gt;::new()</code> instead if desired.)
/// ///
/// ```rust /// ```rust
/// # use anymap::AnyMap; /// let mut data = anymap::AnyMap::new();
/// let mut data = AnyMap::new();
/// assert_eq!(data.get(), None::<&i32>); /// assert_eq!(data.get(), None::<&i32>);
/// data.insert(42i32); /// data.insert(42i32);
/// assert_eq!(data.get(), Some(&42i32)); /// assert_eq!(data.get(), Some(&42i32));
@ -135,7 +152,7 @@ impl<A: ?Sized + UncheckedAnyExt> Clone for Map<A> where Box<A>: Clone {
} }
} }
/// The most common type of `Map`: just using `Any`. /// The most common type of `Map`: just using `Any`; <code>[Map]&lt;dyn [Any]&gt;</code>.
/// ///
/// Why is this a separate type alias rather than a default value for `Map<A>`? `Map::new()` /// Why is this a separate type alias rather than a default value for `Map<A>`? `Map::new()`
/// doesnt seem to be happy to infer that it should go with the default value. /// doesnt seem to be happy to infer that it should go with the default value.