supply 0.3.1

Provider API for arbitrary number of lifetimes.
Documentation
use std::fmt::{Debug, Display};

use supply::prelude::*;
use supply::provide::ProvideTag;

trait Error: Debug + for<'r> ProviderDyn<'r> {}

impl<T: Debug + for<'r> ProviderDyn<'r>> Error for T {}

#[derive(Debug)]
struct MyError {
    count: i32,
}

impl Display for MyError {
    fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        todo!()
    }
}

impl<'r> Provider<'r> for MyError {
    type Lifetimes = l!['r];

    // From core::error::Error:
    //
    // fn provide<'a>(&'a self, request: &mut Request<'a>) { ... }
    fn provide(&'r self, want: &mut dyn Want<Self::Lifetimes>) {
        want.provide_value(self.count);
    }

    // Something the std Error can't do.
    fn provide_mut(&'r mut self, want: &mut dyn Want<Self::Lifetimes>) {
        want.provide_value(&mut self.count);
    }
}

fn log<E: ?Sized + Error>(e: &mut E) -> String {
    if let Some(count) = e.request_mut::<&mut i32>() {
        *count += 1;
    }

    if let Some(count) = e.request::<i32>() {
        return format!("count: {count}");
    }

    format!("{e:?}")
}

#[test]
fn custom_error() {
    let mut my = MyError { count: 42 };

    let e: &mut dyn Error = &mut my;

    assert_eq!(log(e), "count: 43");
    assert_eq!(log(e), "count: 44");

    let mut x = 123;

    let e: &mut dyn Error = ProvideTag::<_, i32>::from_mut(&mut x);

    assert_eq!(log(e), "ProvideTag(124)");
    assert_eq!(log(e), "ProvideTag(125)");
}

struct Error2 {
    a: i32,
    b: i32,
}

// supply replaces the would_be_satisfied functions with the try_for_id and WantFor
impl<'r> Provider<'r> for Error2 {
    type Lifetimes = l![];

    fn provide(&'r self, want: &mut dyn Want<Self::Lifetimes>) {
        // Check that the want will accept a value of i32 before doing out "expensive" operation.
        if let Some(want) = want.try_for::<i32>() {
            want.fulfill(self.a + self.b);
        }
    }
}

#[test]
fn error_2() {
    let e = Error2 { a: 1, b: 4 };

    assert_eq!(e.request::<i32>().unwrap(), 5);
    assert!(e.request::<bool>().is_none());
}