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}