blueprint_core/extract/
extension.rs

1//! A Smart Extractor that extracts any type from the [`Extensions`] of the current [`JobCall`].
2//!
3//! [`Extensions`]: crate::extensions::Extensions
4//! [`JobCall`]: crate::JobCall
5
6use core::convert::Infallible;
7
8use alloc::format;
9
10use crate::FromJobCallParts;
11use crate::extract::OptionalFromJobCallParts;
12use crate::job::call::Parts as JobCallParts;
13
14/// A Specialized extractor for the [`Extensions`] of the current [`JobCall`].
15///
16/// Any type that is stored in the [`Extensions`] of the current [`JobCall`] can be extracted using this extractor.
17///
18/// For Optional extraction, you can use this extractor with `Option<Extension<T>>` where `T` is the type you want to extract.
19///
20/// [`JobCall`]: crate::JobCall
21/// [`Extensions`]: crate::extensions::Extensions
22#[derive(Clone)]
23pub struct Extension<T>(pub T);
24
25crate::__impl_deref!(Extension);
26
27crate::__define_rejection! {
28    #[body = "Extension not found"]
29    /// Rejection type used when the extension is not found in the current [`JobCall`].
30    ///
31    /// [`JobCall`]: crate::JobCall
32    pub struct ExtensionNotFound(Error);
33}
34
35impl<Ctx, T> FromJobCallParts<Ctx> for Extension<T>
36where
37    T: Send + Sync + Clone + 'static,
38    Ctx: Send + Sync + 'static,
39{
40    type Rejection = ExtensionNotFound;
41
42    async fn from_job_call_parts(
43        parts: &mut JobCallParts,
44        _: &Ctx,
45    ) -> Result<Self, Self::Rejection> {
46        let ext = parts.extensions.get::<T>().cloned();
47        match ext {
48            Some(value) => Ok(Extension(value)),
49            None => Err(ExtensionNotFound::from_err(format!(
50                "trying to extract extension of type {} but it was not found",
51                core::any::type_name::<T>()
52            ))),
53        }
54    }
55}
56
57impl<Ctx, T> OptionalFromJobCallParts<Ctx> for Extension<T>
58where
59    T: Send + Sync + Clone + 'static,
60    Ctx: Send + Sync + 'static,
61{
62    type Rejection = Infallible;
63
64    async fn from_job_call_parts(
65        parts: &mut JobCallParts,
66        _: &Ctx,
67    ) -> Result<Option<Self>, Self::Rejection> {
68        let ext = parts.extensions.get::<T>().cloned();
69        match ext {
70            Some(value) => Ok(Some(Extension(value))),
71            None => Ok(None),
72        }
73    }
74}