supply 0.2.0

Provider API for arbitrary number of lifetimes.
Documentation
//! [`supply`](crate) implements an API similar to that proposed in
//! [RFC 3192](https://rust-lang.github.io/rfcs/3192-dyno.html). It allows
//! accessing data based on type tags. Expanding on RFC 3192, `supply`
//! allows accessing data with an arbitrary number of lifetimes. Additionally,
//! `supply` allows for multiple values to be requested at once.
//! `supply` also builds on the [`Any`](core::any::Any) API to allow arbitrary number
//! of lifetimes in type erased trait objects. Combined almost any need for passing
//! data between type erased components should be easy to implement.
//!
//! It is recommended to use the prelude which has the common API elements.
//! ```
//! use supply::prelude::*;
//! ```
//!
//! Most users should start with implementing the [`Provider`] trait on one or more
//! types they want to expose extra information from. Then the `.request::<T>()` method
//! can be used to request a specific type of information from the provider. This
//! is the core API flow of `supply`. Below is an example with a couple of the more advanced
//! features for demonstration. See the [`provide`] module for a more detailed guide.
//!
//! For users looking for a more powerful [`Any`](core::any::Any), you should see the
//! [`anything`] module for a guide on using [`Anything`].
//!
//! ```
//! use supply::prelude::*;
//! use supply::tag::AddLt;
//!
//! struct Person<'a> {
//!     name: &'a str,
//!     age: u8,
//! }
//!
//! // Implementing Provider allows requesting data from a Person value.
//! impl<'r, 'a> Provider<'r> for Person<'a> {
//!     type Lifetimes = l!['a];
//!
//!     fn provide(&'r self, want: &mut dyn Want<Self::Lifetimes>) {
//!         // Provide the name and age fields.
//!         want.provide_tag::<&str>(self.name)
//!             .provide_value(self.age);
//!     }
//! }
//!
//! // Make an example person to request data from.
//! let name = String::from("bob");
//!
//! let provided_name;
//! {
//!     let person = Person {
//!         name: &name,
//!         age: 42,
//!     };
//!
//!     // Convert to a trait object to show Provider is object safe.
//!     let provider: &dyn ProviderDyn<l!['_]> = &person;
//!
//!     // Request the person's name.
//!     provided_name = provider.request::<&str>();
//!     assert_eq!(provided_name, Some("bob"));
//!
//!     // Request the person's age.
//!     let provided_age = provider.request::<u8>();
//!     assert_eq!(provided_age, Some(42));
//!
//!     // Request something Person doesn't provide.
//!     // We just don't get a value from the request.
//!     let provided_something = provider.request::<f32>();
//!     assert_eq!(provided_something, None);
//! };
//!
//! // Because the name was tagged as &'a str we can still access it here.
//! assert_eq!(provided_name, Some("bob"));
//! ```
//!
//! ## Alternatives
//!
//! ### `core`/`std`
//!
//! No surprise but the [`core::any`] module exists, and its very good if you just need
//! to work with `'static` types.
//!
//! Additionally, [`Error`][core::error::Error] has the unstable provide API (derived from RFC 3192).
//! However, this implementation of provide is limited to error types and has only the lifetime of
//! the source value available.
//!
//! #### Mapping to `supply`'s API
//!
//! <details>
//! <summary>Click to show</summary>
//!
//! | `core`/`std` API | `supply` API |
//! |------------------|--------------|
//! | [`TypeId`](core::any::TypeId) | [`TagTypeId`](crate::tag::TagTypeId) |
//! | [`TypeId::of()`](core::any::TypeId::of) | [`TagTypeId::of()`](crate::tag::TagTypeId::of) |
//! | | |
//! | [`Any`](core::any::Any) | [`Anything`](crate::anything::Anything) |
//! | [`Any::type_id()`](core::any::Any::type_id) | [`Anything::tag_id()`](crate::anything::Anything::tag_id) |
//! | [`Any::is()`](core::any::Any#method.is) [<sup>1</sup>](#core-1) | [`AnythingExt::is()`](crate::anything::AnythingExt::is) |
//! | [`Any::downcast_ref()`](core::any::Any#method.downcast_ref) [<sup>1</sup>](#core-1) | [`AnythingExt::downcast_ref()`](crate::anything::AnythingExt::downcast_ref) |
//! | [`Any::downcast_mut()`](core::any::Any#method.downcast_mut) [<sup>1</sup>](#core-1) | [`AnythingExt::downcast_mut()`](crate::anything::AnythingExt::downcast_mut) |
//! | | |
//! | [`Error::provide`](core::error::Error::provide) | [`Provider::provide`](crate::Provider::provide) |
//! | | |
//! | [`Request`](core::error::Request) | [`Want`](crate::want::Want) [<sup>2</sup>](#core-2) |
//! | [`Request::provide_ref()`](core::error::Request::provide_ref) </br> [`Request::provide_value()`](core::error::Request::provide_ref) | [`Want::provide_value()`](crate::want::Want#method.provide_value) |
//!
//! <sub>
//! <a name="core-1"></a> 1. In core/std, this function is implemented independently for
//! multiple types.
//! </br>
//! <a name="core-2"></a> 2. In supply, Want is a trait instead of a struct for more flexibility.
//! </sub>
//!
//! </details>
//!
//! ## `no_std` Support
//!
//! This crate is `#![no_std]` by default, it can be used anywhere Rust can.
//!
//! ## Minimum Supported Rust Version
//!
//! Requires Rust 1.79.0.
//!
//! This crate follows the ["Latest stable Rust" policy](https://gist.github.com/alexheretic/d1e98d8433b602e57f5d0a9637927e0c). The listed MSRV won't be changed unless needed.
//! However, updating the MSRV anywhere up to the latest stable at time of release
//! is allowed.

// #![forbid(unsafe_code)]

#![cfg_attr(all(not(test), not(feature = "std")), no_std)]

pub mod anything;
mod erased_wide;
pub mod lt_list;
pub mod provide;
pub mod request;
pub mod tag;
pub mod want;

/// Commonly needed types and traits.
pub mod prelude {
    pub use crate::anything::{AnyStatic, Anything, AnythingExt};
    pub use crate::lt_list::LtList;
    pub use crate::provide::{Provider, ProviderDyn, ProviderExt};
    pub use crate::tag::{TagTypeId, Tagged, WithLt};
    pub use crate::want::Want;
    pub use crate::{impl_tagged, l, tag_for};
}

#[doc(inline)]
pub use anything::Anything;
#[doc(inline)]
pub use lt_list::LtList;
#[doc(inline)]
pub use provide::Provider;
#[doc(inline)]
pub use request::Request;
#[doc(inline)]
pub use tag::Tagged;
#[doc(inline)]
pub use want::Want;