1use std::{ops::Deref, sync::Arc};
2
3use anyhow::Result;
4use axum::{
5 extract::{FromRequestParts, State},
6 http::request::Parts,
7};
8
9use crate::{Container, HttpException};
10
11pub struct Inject<T>(Arc<T>);
20
21impl<T> Inject<T>
22where
23 T: Send + Sync + 'static,
24{
25 pub fn from(container: &Container) -> Result<Self> {
29 let inner = container.resolve::<T>()?;
30 Ok(Self(inner))
31 }
32
33 pub fn into_inner(self) -> Arc<T> {
34 self.0
35 }
36}
37
38impl<T> Deref for Inject<T> {
39 type Target = T;
40
41 fn deref(&self) -> &Self::Target {
42 &self.0
43 }
44}
45
46impl<T> FromRequestParts<Container> for Inject<T>
51where
52 T: Send + Sync + 'static,
53{
54 type Rejection = HttpException;
55
56 async fn from_request_parts(
57 parts: &mut Parts,
58 state: &Container,
59 ) -> Result<Self, Self::Rejection> {
60 let State(container): State<Container> = State::from_request_parts(parts, state)
61 .await
62 .map_err(|_| HttpException::internal_server_error("Container state not available"))?;
63
64 Self::from(&container)
65 .map_err(|_| HttpException::internal_server_error("Dependency not registered"))
66 }
67}