Skip to main content

injectium_core/
provider.rs

1use std::sync::Arc;
2
3use crate::container::Container;
4use crate::types::SyncBounds;
5
6/// A source that can provide values from a [`Container`].
7pub trait Provider: 'static {
8    /// The value produced by this provider.
9    type Output: SyncBounds;
10
11    /// Produces a value using the current container.
12    fn provide(&self, container: &Container) -> Self::Output;
13}
14
15impl<T: SyncBounds> Provider for Arc<T> {
16    type Output = Arc<T>;
17
18    fn provide(&self, _container: &Container) -> Self::Output {
19        Arc::clone(self)
20    }
21}
22
23/// An explicit provider that clones a stored value on each request.
24pub struct CloneProvider<T>(T);
25
26impl<T> CloneProvider<T> {
27    /// Wraps a cloneable value as an explicit clone-on-read provider.
28    #[must_use]
29    pub fn new(value: T) -> Self {
30        Self(value)
31    }
32}
33
34impl<T> Provider for CloneProvider<T>
35where
36    T: SyncBounds + Clone,
37{
38    type Output = T;
39
40    fn provide(&self, _container: &Container) -> Self::Output {
41        self.0.clone()
42    }
43}
44
45/// Wraps a cloneable value as an explicit clone-on-read provider.
46#[must_use]
47pub fn cloned<T>(value: T) -> CloneProvider<T>
48where
49    T: SyncBounds + Clone,
50{
51    CloneProvider::new(value)
52}
53
54/// An explicit provider that copies a stored value on each request.
55pub struct CopyProvider<T>(T);
56
57impl<T> CopyProvider<T> {
58    /// Wraps a copyable value as an explicit copy-on-read provider.
59    #[must_use]
60    pub fn new(value: T) -> Self {
61        Self(value)
62    }
63}
64
65impl<T> Provider for CopyProvider<T>
66where
67    T: SyncBounds + Copy,
68{
69    type Output = T;
70
71    fn provide(&self, _container: &Container) -> Self::Output {
72        self.0
73    }
74}
75
76/// Wraps a copyable value as an explicit copy-on-read provider.
77#[must_use]
78pub fn copied<T>(value: T) -> CopyProvider<T>
79where
80    T: SyncBounds + Copy,
81{
82    CopyProvider::new(value)
83}
84
85impl<T, F> Provider for F
86where
87    T: SyncBounds,
88    F: Fn(&Container) -> T + SyncBounds,
89{
90    type Output = T;
91
92    fn provide(&self, container: &Container) -> Self::Output {
93        self(container)
94    }
95}