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
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
use crate::{
    InjectResult, Injector, RequestInfo, Service, ServiceFactory, Svc,
    TypedProvider,
};
use std::marker::PhantomData;

/// A service provider that only creates a single instance of the service.
/// The service is created only during its first request. Any subsequent
/// requests return service pointers to the same service.
pub struct SingletonProvider<D, R, F>
where
    R: Service,
    F: ServiceFactory<D, Result = R>,
{
    factory: F,
    result: Option<Svc<R>>,
    marker: PhantomData<fn(D) -> R>,
}

impl<D, R, F> SingletonProvider<D, R, F>
where
    R: Service,
    F: ServiceFactory<D, Result = R>,
{
    /// Creates a new [`SingletonProvider`] using a service factory.
    #[must_use]
    pub fn new(func: F) -> Self {
        SingletonProvider {
            factory: func,
            result: None,
            marker: PhantomData,
        }
    }
}

impl<D, R, F> TypedProvider for SingletonProvider<D, R, F>
where
    D: Service,
    R: Service,
    F: ServiceFactory<D, Result = R>,
{
    type Result = R;

    fn provide_typed(
        &mut self,
        injector: &Injector,
        request_info: &RequestInfo,
    ) -> InjectResult<Svc<Self::Result>> {
        if let Some(ref service) = self.result {
            return Ok(service.clone());
        }

        let result = self.factory.invoke(injector, request_info)?;
        let result = Svc::new(result);
        self.result = Some(result.clone());
        Ok(result)
    }
}

/// Defines a conversion into a singleton provider. This trait is automatically
/// implemented for all service factories.
pub trait IntoSingleton<D, R, F>
where
    R: Service,
    F: ServiceFactory<D, Result = R>,
{
    /// Creates a singleton provider. Singleton providers create their values
    /// only once (when first requested) and reuse that value for each future
    /// request.
    ///
    /// ## Example
    ///
    /// ```
    /// use runtime_injector::{Injector, IntoSingleton, Svc};
    ///
    /// #[derive(Default)]
    /// struct Foo;
    ///
    /// let mut builder = Injector::builder();
    /// builder.provide(Foo::default.singleton());
    ///
    /// let injector = builder.build();
    /// let foo1: Svc<Foo> = injector.get().unwrap();
    /// let foo2: Svc<Foo> = injector.get().unwrap();
    ///
    /// assert!(Svc::ptr_eq(&foo1, &foo2));
    /// ```
    #[must_use]
    fn singleton(self) -> SingletonProvider<D, R, F>;
}

impl<D, R, F> IntoSingleton<D, R, F> for F
where
    R: Service,
    F: ServiceFactory<D, Result = R>,
{
    fn singleton(self) -> SingletonProvider<D, R, F> {
        SingletonProvider::new(self)
    }
}

impl<D, R, F> From<F> for SingletonProvider<D, R, F>
where
    R: Service,
    F: ServiceFactory<D, Result = R>,
{
    fn from(func: F) -> Self {
        func.singleton()
    }
}