1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use std::{marker::PhantomData, sync::Arc};

use crate::{Catalog, InjectionError};

/////////////////////////////////////////////////////////////////////////////////////////
// DependencySpec
/////////////////////////////////////////////////////////////////////////////////////////

/// Specifies a particular way of resolving a dependency using the [`Catalog`]
pub trait DependencySpec {
    type ReturnType;
    fn get(cat: &Catalog) -> Result<Self::ReturnType, InjectionError>;
}

/////////////////////////////////////////////////////////////////////////////////////////
// OneOf
/////////////////////////////////////////////////////////////////////////////////////////

/// Builds a single instance of type implementing specific interface. Will return an error
/// if no implementations or multiple implementations were found.
pub struct OneOf<Iface>
where
    Iface: 'static + ?Sized + Send + Sync,
{
    _dummy: PhantomData<Iface>,
}

impl<Iface> DependencySpec for OneOf<Iface>
where
    Iface: 'static + ?Sized + Send + Sync,
{
    type ReturnType = Arc<Iface>;

    default fn get(cat: &Catalog) -> Result<Self::ReturnType, InjectionError> {
        let mut builders = cat.builders_for::<Iface>();
        if let Some(first) = builders.next() {
            if builders.next().is_some() {
                Err(InjectionError::ambiguous::<Iface>())
            } else {
                first.get(cat)
            }
        } else {
            Err(InjectionError::unregistered::<Iface>())
        }
    }
}

impl DependencySpec for OneOf<Catalog> {
    fn get(cat: &Catalog) -> Result<Self::ReturnType, InjectionError> {
        Ok(Arc::new(cat.clone()))
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
// AllOf
/////////////////////////////////////////////////////////////////////////////////////////

/// Builds all instances that implement a specific interface, returning a [`Vec`].
pub struct AllOf<Iface>
where
    Iface: 'static + ?Sized,
{
    _dummy: PhantomData<Iface>,
}

impl<Iface> DependencySpec for AllOf<Iface>
where
    Iface: 'static + ?Sized,
{
    type ReturnType = Vec<Arc<Iface>>;

    fn get(cat: &Catalog) -> Result<Self::ReturnType, InjectionError> {
        cat.builders_for::<Iface>().map(|b| b.get(cat)).collect()
    }
}