1use std::{ops::Deref, sync::Arc};
2
3use anyhow::Result;
4use axum::{
5 extract::{FromRequestParts, State},
6 http::request::Parts,
7};
8
9use crate::{framework_log, 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 framework_log(format!("Injecting {}.", std::any::type_name::<T>()));
30 let inner = container.resolve::<T>()?;
31 Ok(Self(inner))
32 }
33
34 pub fn into_inner(self) -> Arc<T> {
35 self.0
36 }
37}
38
39impl<T> Deref for Inject<T> {
40 type Target = T;
41
42 fn deref(&self) -> &Self::Target {
43 &self.0
44 }
45}
46
47impl<T> FromRequestParts<Container> for Inject<T>
52where
53 T: Send + Sync + 'static,
54{
55 type Rejection = HttpException;
56
57 async fn from_request_parts(
58 parts: &mut Parts,
59 state: &Container,
60 ) -> Result<Self, Self::Rejection> {
61 let State(container): State<Container> = State::from_request_parts(parts, state)
62 .await
63 .map_err(|_| HttpException::internal_server_error("Container state not available"))?;
64
65 Self::from(&container).map_err(|err| {
66 HttpException::internal_server_error(format!(
67 "Failed to resolve dependency `{}`: {}",
68 std::any::type_name::<T>(),
69 err
70 ))
71 })
72 }
73}
74
75impl<T> AsRef<T> for Inject<T> {
76 fn as_ref(&self) -> &T {
77 &self.0
78 }
79}