supply 0.1.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.
//!
//! ```
//! use supply::{Provider, ProviderDyn, Want, LtList, Lt1, tag::AddLt, RequestExt as _};
//!
//! struct Person<'a> {
//!     name: &'a str,
//!     age: u8,
//! }
//!
//! // Implementing Provider allows requesting data from a Person value.
//! impl<'a> Provider for Person<'a> {
//!     type Lifetimes = Lt1<'a>;
//!
//!     fn provide<'r>(&'r self, want: &mut dyn Want<'r, Lt1<'a>>) {
//!         // Provide the name and age fields.
//!         want.provide_tag::<AddLt<&AddLt<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<Lt1> = &person;
//!
//!     // Request the person's name.
//!     provided_name = <AddLt<&AddLt<str>>>::request(provider);
//!     assert_eq!(provided_name, Some("bob"));
//!
//!     // Request the person's age.
//!     let provided_age = u8::request(provider);
//!     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 = f32::request(provider);
//!     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"));
//! ```
//!
//! ## `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)]

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

#[doc(inline)]
pub use lt_list::{Lt0, Lt1, Lt2, LtList};
#[doc(inline)]
pub use request::{request_from, request_from_mut, RequestExt};
#[doc(inline)]
pub use tag::{Anything, AnythingExt, TagOf, WithLt};
#[doc(inline)]
pub use want::Want;

/// Helper for using [`Provider`] as a trait object.
///
/// Normally using [`Provider`] as a trait object would require
/// always naming the lifetime associated type with `Lifetimes = ...`.
/// This helper makes it just a generic.
pub trait ProviderDyn<L: LtList>: Provider<Lifetimes = L> + provider_dyn_seal::Sealed<L> {}

impl<L: LtList, T: ?Sized + Provider<Lifetimes = L>> ProviderDyn<L> for T {}

mod provider_dyn_seal {
    use super::*;

    pub trait Sealed<L: LtList> {}

    impl<L: LtList, T: ?Sized + Provider<Lifetimes = L>> Sealed<L> for T {}
}

/// Provider of values.
///
/// Provided values may contain lifetimes from `L` and the `'r` lifetime.
pub trait Provider {
    /// Lifetimes the provider wants to use.
    ///
    /// A lifetime cannot be used in [`Self::provide`] or [`Self::provide_mut`]
    /// unless it is named in this associated type.
    type Lifetimes: LtList;

    /// Provide values given a `&T`.
    ///
    /// Values are provided to the passed in [`Want`].
    fn provide<'r>(&'r self, want: &mut dyn Want<'r, Self::Lifetimes>) {
        _ = want;
    }

    /// Provide values given a `&mut T`.
    ///
    /// Values are provided to the passed in [`Want`].
    fn provide_mut<'r>(&'r mut self, want: &mut dyn Want<'r, Self::Lifetimes>) {
        self.provide(want);
    }
}