supply 0.1.0

Provider API for arbitrary number of lifetimes.
Documentation
//! Example of using supply to access a value as different trait objects.

use supply::lt_list::LtTagOf;
use supply::request::RequestExt;
use supply::tag::{Tag, Tagged};
use supply::{Lt0, Lt1, LtList, Provider, ProviderDyn, Want, WithLt};

struct Demo {
    value: u8,
}

impl A for Demo {
    fn do_a(&self) -> u8 {
        self.value
    }
}

impl B for Demo {
    fn do_b(&mut self, value: u8) {
        self.value = value;
    }
}

impl Provider for Demo {
    type Lifetimes = Lt0;

    fn provide<'r>(&'r self, want: &mut dyn Want<'r>) {
        want.provide_tag::<&DynA>(self);
    }

    fn provide_mut<'r>(&'r mut self, want: &mut dyn Want<'r>) {
        // This doesn't work because self would be borrowed twice.
        // This is fine for provide above.
        //
        // want.provide_tag::<&DynA>(self)
        //     .provide_tag::<&mut DynB>(self);

        // This way works because the borrow checker knows that if self is used then
        // nothing after this can be run (because provide_with returns None).
        let Some(this) = want.provide_with::<&DynA, _, _>(self, |this| this) else {
            return;
        };

        // The last one can be normal.
        want.provide_tag::<&mut DynB>(this);
    }
}

#[test]
fn example() {
    let mut demo = Demo { value: 0 };

    // Erase the type so the following doesn't know it's a Demo.
    let p: &mut dyn ProviderDyn<Lt0> = &mut demo;

    // Access demo as a &dyn A to call do_a.
    assert_eq!(<&DynA>::request(p).unwrap().do_a(), 0);

    // Access demo as a &mut dyn B to call do_b.
    <&mut DynB>::request_mut(p).unwrap().do_b(5);

    // Access demo as a &dyn A to call do_a again.
    assert_eq!(<&DynA>::request(p).unwrap().do_a(), 5);
}

trait A {
    fn do_a(&self) -> u8;
}

enum DynA {}

impl<'u, L: LtList<Head = Lt1<'u>>> WithLt<L> for DynA {
    type Reified = dyn A + 'u;
}

impl Tagged for DynA {
    type Tag = Self;
}

impl Tag for DynA {
    type LifetimesTag = LtTagOf<Lt1<'static>>;
}

trait B {
    fn do_b(&mut self, value: u8);
}

enum DynB {}

impl<'u, L: LtList<Head = Lt1<'u>>> WithLt<L> for DynB {
    type Reified = dyn B + 'u;
}

impl Tagged for DynB {
    type Tag = Self;
}

impl Tag for DynB {
    type LifetimesTag = LtTagOf<Lt1<'static>>;
}