Skip to main content

ruest/di/
inject.rs

1use std::marker::PhantomData;
2use std::sync::Arc;
3
4use super::Container;
5use super::DiError;
6
7/// Wrapper type for automatic dependency injection in controllers and services.
8///
9/// ```ignore
10/// pub struct UserController {
11///     service: Inject<UserService>,
12/// }
13/// ```
14#[derive(Debug)]
15pub struct Inject<T> {
16    inner: Arc<T>,
17}
18
19impl<T: Send + Sync + 'static> Inject<T> {
20    /// Resolve `T` from the given container.
21    pub fn resolve(container: &Container) -> Result<Self, DiError> {
22        let inner = container.get::<T>()?;
23        Ok(Self { inner })
24    }
25
26    /// Access the injected instance.
27    pub fn get(&self) -> &T {
28        &self.inner
29    }
30
31    /// Clone the underlying `Arc`.
32    pub fn arc(&self) -> Arc<T> {
33        Arc::clone(&self.inner)
34    }
35}
36
37impl<T> std::ops::Deref for Inject<T> {
38    type Target = T;
39
40    fn deref(&self) -> &Self::Target {
41        &self.inner
42    }
43}
44
45/// Marker for types that can be constructed via DI without manual registration.
46pub trait Injectable: Sized + Send + Sync + 'static {
47    fn construct(container: &Container) -> Result<Self, DiError>;
48}
49
50/// Helper for optional manual injection outside of macro-generated code.
51pub struct Injector<T> {
52    _marker: PhantomData<T>,
53}
54
55impl<T: Send + Sync + 'static> Injector<T> {
56    pub fn from_container(container: &Container) -> Result<Inject<T>, DiError> {
57        Inject::resolve(container)
58    }
59}