supply 0.2.0

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

use supply::lt_structure;
use supply::prelude::*;
use supply::tag::{Mut, Ref, Tag};

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<'r> Provider<'r> for Demo {
    type Lifetimes = l!['r];

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

    fn provide_mut(&'r mut self, want: &mut dyn Want<Self::Lifetimes>) {
        // 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::<Ref<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 for<'r> ProviderDyn<'r> = &mut demo;

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

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

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

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

enum DynA {}

impl<'u> WithLt<l!['u]> for DynA {
    type Reified = dyn A + 'u;
}

impl Tagged for DynA {
    type Tag = Self;
}

impl Tag for DynA {
    type LifetimesTag = lt_structure!['_];
}

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

enum DynB {}

impl<'u> WithLt<l!['u]> for DynB {
    type Reified = dyn B + 'u;
}

impl Tagged for DynB {
    type Tag = Self;
}

impl Tag for DynB {
    type LifetimesTag = lt_structure!['_];
}