supply 0.3.1

Provider API for arbitrary number of lifetimes.
Documentation
//! Request for values from a provider.
//!
//! These are an extension of wants that know how to
//! generate an output value to give to the caller.
//! All types that implement [`Tagged`](crate::tag::Tagged) also implement [`Request`].
//! This allows requesting single values using `<type>::request(provider)`.
//!
//! This module provides up to six multi-value requests. Additionally
//! if this limit is not enough, then the `Req` types can be nested inside
//! each other.

pub mod requests;

use ty_tag::lifetime_list::{LifetimeList, L0, L1};
use ty_tag::ReifySized;

use crate::want::WantOne;
use crate::{Provider, Want};

/// Adds extra methods to use requests with providers.
pub trait ProviderExt<'r>: Provider<'r> {
    /// Request value(s) from the provider.
    fn request<R>(&'r self) -> R::Output
    where
        R: Request<Self::Lifetimes>,
    {
        let mut want = R::Want::default();
        self.provide(&mut want);
        R::into_output(want)
    }

    /// Request value(s) from the provider.
    ///
    /// This method may return different values to `request` since it has access to a `&mut self`.
    fn request_mut<R>(&'r mut self) -> R::Output
    where
        R: Request<Self::Lifetimes>,
    {
        let mut want = R::Want::default();
        self.provide_mut(&mut want);
        R::into_output(want)
    }
}

impl<'r, T: ?Sized + Provider<'r>> ProviderExt<'r> for T {}

/// A request for values from a [`Provider`].
///
/// All [`ReifySized`] implementers implement this trait.
pub trait Request<L: LifetimeList> {
    /// The want that will be passed to the provider.
    ///
    /// The `Default::default()` impl should be an empty want.
    type Want: Want<L> + Default;

    /// The output value of the request.
    type Output;

    /// Convert the want into an output.
    fn into_output(want: Self::Want) -> Self::Output;
}

// The following two impls are split to bypass the orphan rule.
// Which would otherwise prevent external crates from implementing Request.

// All tagged types automatically become requests.
// The request is for one value of the tag's reified type.
impl<T: ReifySized<L0>> Request<L0> for T {
    type Want = WantOne<L0, T::UsedTag>;

    type Output = Option<T::Reified>;

    fn into_output(want: Self::Want) -> Self::Output {
        want.into_inner()
    }
}

impl<'lt, Tail: LifetimeList, T: ReifySized<L1<'lt, Tail>>> Request<L1<'lt, Tail>> for T {
    type Want = WantOne<L1<'lt, Tail>, T::UsedTag>;

    type Output = Option<T::Reified>;

    fn into_output(want: Self::Want) -> Self::Output {
        want.into_inner()
    }
}