Skip to main content

socketioxide/extract/
extensions.rs

1use std::convert::Infallible;
2use std::sync::Arc;
3
4use crate::adapter::Adapter;
5use crate::handler::{FromConnectParts, FromDisconnectParts, FromMessageParts};
6use crate::socket::{DisconnectReason, Socket};
7use socketioxide_core::Value;
8
9#[cfg(feature = "extensions")]
10pub use extensions_extract::*;
11
12/// It was impossible to find the given extension.
13pub struct ExtensionNotFound<T>(std::marker::PhantomData<T>);
14
15impl<T> std::fmt::Display for ExtensionNotFound<T> {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        write!(
18            f,
19            "Extension of type {} not found, maybe you forgot to insert it in the extensions map?",
20            std::any::type_name::<T>()
21        )
22    }
23}
24impl<T> std::fmt::Debug for ExtensionNotFound<T> {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        write!(f, "ExtensionNotFound {}", std::any::type_name::<T>())
27    }
28}
29impl<T> std::error::Error for ExtensionNotFound<T> {}
30
31fn extract_http_extension<T: Clone + Send + Sync + 'static>(
32    s: &Arc<Socket<impl Adapter>>,
33) -> Result<T, ExtensionNotFound<T>> {
34    s.req_parts()
35        .extensions
36        .get::<T>()
37        .cloned()
38        .ok_or(ExtensionNotFound(std::marker::PhantomData))
39}
40
41/// An Extractor that returns a clone extension from the request parts.
42pub struct HttpExtension<T>(pub T);
43
44/// An Extractor that returns a clone extension from the request parts if it exists.
45pub struct MaybeHttpExtension<T>(pub Option<T>);
46
47impl<A: Adapter, T: Clone + Send + Sync + 'static> FromConnectParts<A> for HttpExtension<T> {
48    type Error = ExtensionNotFound<T>;
49    fn from_connect_parts(
50        s: &Arc<Socket<A>>,
51        _: &Option<Value>,
52    ) -> Result<Self, ExtensionNotFound<T>> {
53        extract_http_extension(s).map(HttpExtension)
54    }
55}
56
57impl<A: Adapter, T: Clone + Send + Sync + 'static> FromConnectParts<A> for MaybeHttpExtension<T> {
58    type Error = Infallible;
59    fn from_connect_parts(s: &Arc<Socket<A>>, _: &Option<Value>) -> Result<Self, Infallible> {
60        Ok(MaybeHttpExtension(extract_http_extension(s).ok()))
61    }
62}
63
64impl<A: Adapter, T: Clone + Send + Sync + 'static> FromDisconnectParts<A> for HttpExtension<T> {
65    type Error = ExtensionNotFound<T>;
66    fn from_disconnect_parts(
67        s: &Arc<Socket<A>>,
68        _: DisconnectReason,
69    ) -> Result<Self, ExtensionNotFound<T>> {
70        extract_http_extension(s).map(HttpExtension)
71    }
72}
73impl<A: Adapter, T: Clone + Send + Sync + 'static> FromDisconnectParts<A>
74    for MaybeHttpExtension<T>
75{
76    type Error = Infallible;
77    fn from_disconnect_parts(s: &Arc<Socket<A>>, _: DisconnectReason) -> Result<Self, Infallible> {
78        Ok(MaybeHttpExtension(extract_http_extension(s).ok()))
79    }
80}
81
82impl<A: Adapter, T: Clone + Send + Sync + 'static> FromMessageParts<A> for HttpExtension<T> {
83    type Error = ExtensionNotFound<T>;
84    fn from_message_parts(
85        s: &Arc<Socket<A>>,
86        _: &mut Value,
87        _: &Option<i64>,
88    ) -> Result<Self, ExtensionNotFound<T>> {
89        extract_http_extension(s).map(HttpExtension)
90    }
91}
92impl<A: Adapter, T: Clone + Send + Sync + 'static> FromMessageParts<A> for MaybeHttpExtension<T> {
93    type Error = Infallible;
94    fn from_message_parts(
95        s: &Arc<Socket<A>>,
96        _: &mut Value,
97        _: &Option<i64>,
98    ) -> Result<Self, Infallible> {
99        Ok(MaybeHttpExtension(extract_http_extension(s).ok()))
100    }
101}
102
103super::__impl_deref!(HttpExtension);
104super::__impl_deref!(MaybeHttpExtension<T>: Option<T>);
105
106#[cfg(feature = "extensions")]
107mod extensions_extract {
108    use super::*;
109
110    fn extract_extension<T: Clone + Send + Sync + 'static>(
111        s: &Arc<Socket<impl Adapter>>,
112    ) -> Result<T, ExtensionNotFound<T>> {
113        s.extensions
114            .get::<T>()
115            .ok_or(ExtensionNotFound(std::marker::PhantomData))
116    }
117
118    /// An Extractor that returns the extension of the given type.
119    /// If the extension is not found,
120    /// the handler won't be called and an error log will be print if the `tracing` feature is enabled.
121    ///
122    /// You can use [`MaybeExtension`] if the extensions you are requesting _may_ not exists.
123    pub struct Extension<T>(pub T);
124
125    /// An Extractor that returns the extension of the given type T if it exists or [`None`] otherwise.
126    pub struct MaybeExtension<T>(pub Option<T>);
127
128    impl<A: Adapter, T: Clone + Send + Sync + 'static> FromConnectParts<A> for Extension<T> {
129        type Error = ExtensionNotFound<T>;
130        fn from_connect_parts(
131            s: &Arc<Socket<A>>,
132            _: &Option<Value>,
133        ) -> Result<Self, ExtensionNotFound<T>> {
134            extract_extension(s).map(Extension)
135        }
136    }
137    impl<A: Adapter, T: Clone + Send + Sync + 'static> FromConnectParts<A> for MaybeExtension<T> {
138        type Error = Infallible;
139        fn from_connect_parts(s: &Arc<Socket<A>>, _: &Option<Value>) -> Result<Self, Infallible> {
140            Ok(MaybeExtension(extract_extension(s).ok()))
141        }
142    }
143    impl<A: Adapter, T: Clone + Send + Sync + 'static> FromDisconnectParts<A> for Extension<T> {
144        type Error = ExtensionNotFound<T>;
145        fn from_disconnect_parts(
146            s: &Arc<Socket<A>>,
147            _: DisconnectReason,
148        ) -> Result<Self, ExtensionNotFound<T>> {
149            extract_extension(s).map(Extension)
150        }
151    }
152    impl<A: Adapter, T: Clone + Send + Sync + 'static> FromDisconnectParts<A> for MaybeExtension<T> {
153        type Error = Infallible;
154        fn from_disconnect_parts(
155            s: &Arc<Socket<A>>,
156            _: DisconnectReason,
157        ) -> Result<Self, Infallible> {
158            Ok(MaybeExtension(extract_extension(s).ok()))
159        }
160    }
161    impl<A: Adapter, T: Clone + Send + Sync + 'static> FromMessageParts<A> for Extension<T> {
162        type Error = ExtensionNotFound<T>;
163        fn from_message_parts(
164            s: &Arc<Socket<A>>,
165            _: &mut Value,
166            _: &Option<i64>,
167        ) -> Result<Self, ExtensionNotFound<T>> {
168            extract_extension(s).map(Extension)
169        }
170    }
171    impl<A: Adapter, T: Clone + Send + Sync + 'static> FromMessageParts<A> for MaybeExtension<T> {
172        type Error = Infallible;
173        fn from_message_parts(
174            s: &Arc<Socket<A>>,
175            _: &mut Value,
176            _: &Option<i64>,
177        ) -> Result<Self, Infallible> {
178            Ok(MaybeExtension(extract_extension(s).ok()))
179        }
180    }
181    super::super::__impl_deref!(Extension);
182    super::super::__impl_deref!(MaybeExtension<T>: Option<T>);
183}