blaze_pk/
router.rs

1//! Router implementation for routing packet components to different functions
2//! and automatically decoding the packet contents to the function type
3
4use crate::{
5    error::{DecodeError, DecodeResult},
6    packet::{FromRequest, IntoResponse, Packet, PacketComponents},
7};
8use std::{
9    collections::HashMap,
10    future::Future,
11    marker::PhantomData,
12    pin::Pin,
13    task::{ready, Context, Poll},
14};
15
16/// Empty type used to represent the format of handler
17/// that is provided state
18///
19/// This type is just used to prevent implementation conflicts
20/// between stateful and stateless handlers
21pub struct FormatA;
22
23/// Empty type used to represent the format of handler
24/// that is not provided state
25///
26/// This type is just used to prevent implementation conflicts
27/// between stateful and stateless handlers
28pub struct FormatB;
29
30/// Wrapper over the [FromRequest] type to support the unit type
31/// to differentiate
32pub trait FromRequestInternal: Sized + 'static {
33    fn from_request(req: &Packet) -> DecodeResult<Self>;
34}
35
36/// Unit type implementation for handlers that don't take a req type
37impl FromRequestInternal for () {
38    fn from_request(_req: &Packet) -> DecodeResult<Self> {
39        Ok(())
40    }
41}
42
43/// Implementation for normal [FromRequest] implementations
44impl<F: FromRequest> FromRequestInternal for F {
45    fn from_request(req: &Packet) -> DecodeResult<Self> {
46        F::from_request(req)
47    }
48}
49
50/// Pin boxed future type that is Send and lives for 'a
51type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
52
53/// Trait implemented by handlers which can provided a boxed future
54/// to a response type which can be turned into a response
55///
56/// `State`  The type of state provided to the handler
57/// `Format` The format of the handler function (FormatA, FormatB)
58/// `Req`    The request value type for the handler
59/// `Res`    The response type for the handler
60pub trait Handler<'a, State, Format, Req, Res>: Send + Sync + 'static {
61    /// Handle function for calling the underlying handle logic using
62    /// the proivded state and packet
63    ///
64    /// `state`  The state to provide
65    /// `packet` The packet to handle
66    fn handle(&self, state: &'a mut State, req: Req) -> BoxFuture<'a, Res>;
67}
68
69/// Future which results in a response packet being produced that can
70/// only live for the lifetime of 'a which is the state lifetime
71type PacketFuture<'a> = BoxFuture<'a, Packet>;
72
73/// Handler implementation for async functions that take the state as well
74/// as a request type
75///
76/// ```
77/// struct State;
78/// struct Req;
79/// struct Res;
80///
81/// async fn test(state: &mut State, req: Req) -> Res {
82///     Res {}
83/// }
84/// ```
85impl<'a, State, Fun, Fut, Req, Res> Handler<'a, State, FormatA, Req, Res> for Fun
86where
87    Fun: Fn(&'a mut State, Req) -> Fut + Send + Sync + 'static,
88    Fut: Future<Output = Res> + Send + 'a,
89    Req: FromRequest,
90    Res: IntoResponse,
91    State: Send + 'static,
92{
93    fn handle(&self, state: &'a mut State, req: Req) -> BoxFuture<'a, Res> {
94        Box::pin(self(state, req))
95    }
96}
97
98/// Handler implementation for async functions that take the request type
99/// without any state
100///
101/// ```
102/// struct Req;
103/// struct Res;
104///
105/// async fn test(req: Req) -> Res {
106///     Res {}
107/// }
108/// ```
109impl<State, Fun, Fut, Req, Res> Handler<'_, State, FormatB, Req, Res> for Fun
110where
111    Fun: Fn(Req) -> Fut + Send + Sync + 'static,
112    Fut: Future<Output = Res> + Send + 'static,
113    Req: FromRequest,
114    Res: IntoResponse,
115    State: Send + 'static,
116{
117    fn handle(&self, _state: &mut State, req: Req) -> BoxFuture<'static, Res> {
118        Box::pin(self(req))
119    }
120}
121
122/// Handler implementation for async functions that take the state with no
123/// request type
124///
125/// ```
126/// struct State;
127/// struct Res;
128///
129/// async fn test(state: &mut State) -> Res {
130///     Res {}
131/// }
132/// ```
133impl<'a, State, Fun, Fut, Res> Handler<'a, State, FormatA, (), Res> for Fun
134where
135    Fun: Fn(&'a mut State) -> Fut + Send + Sync + 'static,
136    Fut: Future<Output = Res> + Send + 'a,
137    Res: IntoResponse,
138    State: Send + 'static,
139{
140    fn handle(&self, state: &'a mut State, _: ()) -> BoxFuture<'a, Res> {
141        Box::pin(self(state))
142    }
143}
144
145/// Handler implementation for async functions with no arguments
146///
147/// ```
148/// struct Res;
149///
150/// async fn test() -> Res {
151///     Res {}
152/// }
153/// ```
154impl<State, Fun, Fut, Res> Handler<'_, State, FormatB, (), Res> for Fun
155where
156    Fun: Fn() -> Fut + Send + Sync + 'static,
157    Fut: Future<Output = Res> + Send + 'static,
158    Res: IntoResponse,
159    State: Send + 'static,
160{
161    fn handle(&self, _state: &mut State, _: ()) -> BoxFuture<'static, Res> {
162        Box::pin(self())
163    }
164}
165
166/// Future wrapper that wraps a future from a handler in order
167/// to poll the underlying future and then transform the future
168/// result into the response packet
169///
170/// 'a:   The lifetime of the session
171/// `Res` The response type for the handler
172struct HandlerFuture<'a, Res> {
173    /// The future from the hanlder
174    fut: BoxFuture<'a, Res>,
175    /// The packet the handler is responding to
176    packet: Packet,
177}
178
179impl<'a, Res> Future for HandlerFuture<'a, Res>
180where
181    Res: IntoResponse,
182{
183    type Output = Packet;
184
185    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
186        let this = self.get_mut();
187        // Poll the underlying future
188        let fut = Pin::new(&mut this.fut);
189        let res = ready!(fut.poll(cx));
190        // Transform the result
191        let packet = res.into_response(&this.packet);
192        Poll::Ready(packet)
193    }
194}
195
196/// Trait for erasing the inner types of the handler routes
197trait Route<S>: Send + Sync {
198    /// Handle function for calling the handler logic on the actual implementation
199    /// producing a future that lives as long as the state
200    ///
201    /// `state`  The state provided
202    /// `packet` The packet to handle with the route
203    fn handle<'s>(&self, state: &'s mut S, packet: Packet)
204        -> Result<PacketFuture<'s>, HandleError>;
205}
206
207/// Route wrapper over a handler for storing the phantom type data
208/// and implementing Route
209struct HandlerRoute<H, Format, Req, Res> {
210    /// The underlying handler
211    handler: H,
212    /// Marker for storing related data
213    _marker: PhantomData<fn(Format, Req) -> Res>,
214}
215
216/// Route implementation for handlers wrapped by handler routes
217impl<H, State, Format, Req, Res> Route<State> for HandlerRoute<H, Format, Req, Res>
218where
219    for<'a> H: Handler<'a, State, Format, Req, Res>,
220    Req: FromRequestInternal,
221    Res: IntoResponse,
222    Format: 'static,
223    State: Send + 'static,
224{
225    fn handle<'s>(
226        &self,
227        state: &'s mut State,
228        packet: Packet,
229    ) -> Result<PacketFuture<'s>, HandleError> {
230        let req = match Req::from_request(&packet) {
231            Ok(value) => value,
232            Err(err) => return Err(HandleError::Decoding(err)),
233        };
234        let fut = self.handler.handle(state, req);
235        Ok(Box::pin(HandlerFuture { fut, packet }))
236    }
237}
238
239/// Route implementation for storing components mapped to route
240/// handlers
241pub struct Router<C, S> {
242    /// The map of components to routes
243    routes: HashMap<C, Box<dyn Route<S>>>,
244}
245
246impl<C, S> Default for Router<C, S> {
247    fn default() -> Self {
248        Self {
249            routes: Default::default(),
250        }
251    }
252}
253
254impl<C, S> Router<C, S>
255where
256    C: PacketComponents,
257    S: Send + 'static,
258{
259    /// Creates a new router
260    pub fn new() -> Self {
261        Self::default()
262    }
263
264    /// Adds a new route to the router where the route is something that implements
265    /// the handler type with any lifetime. The value is wrapped with a HandlerRoute
266    /// and stored boxed in the routes map under the component key
267    ///
268    /// `component` The component key for the route
269    /// `route`     The actual route handler function
270    pub fn route<Format, Req, Res>(
271        &mut self,
272        component: C,
273        route: impl for<'a> Handler<'a, S, Format, Req, Res>,
274    ) where
275        Req: FromRequestInternal,
276        Res: IntoResponse,
277        Format: 'static,
278    {
279        self.routes.insert(
280            component,
281            Box::new(HandlerRoute {
282                handler: route,
283                _marker: PhantomData,
284            }),
285        );
286    }
287
288    /// Handle function takes the provided packet retrieves the component from its header
289    /// and finds the matching route (Returning an empty response immediately if none match)
290    /// and providing the state the route along with the packet awaiting the route future
291    ///
292    /// `state`  The provided state
293    /// `packet` The packet to handle
294    pub fn handle<'a>(
295        &self,
296        state: &'a mut S,
297        packet: Packet,
298    ) -> Result<PacketFuture<'a>, HandleError> {
299        let target = match C::from_header(&packet.header) {
300            Some(value) => value,
301            None => return Err(HandleError::MissingHandler(packet)),
302        };
303
304        let route = match self.routes.get(&target) {
305            Some(value) => value,
306            None => return Err(HandleError::MissingHandler(packet)),
307        };
308
309        route.handle(state, packet)
310    }
311}
312
313/// Error that can occur while handling a packet
314#[derive(Debug)]
315pub enum HandleError {
316    /// There wasn't an available handler for the provided packet
317    MissingHandler(Packet),
318    /// Decoding error while reading the packet
319    Decoding(DecodeError),
320}