refactor: update handler function types to use boxed dynamic dispatch

This commit is contained in:
Compositr 2024-11-01 21:33:19 +11:00
parent 6744b6dee1
commit af18bf2ebe
Signed by: compositr
GPG key ID: 91E3DE20129A0B4A

View file

@ -7,11 +7,12 @@ use std::{
net::{Shutdown, TcpListener}, net::{Shutdown, TcpListener},
}; };
type HandlerFn = fn(Request) -> Response<'static>; type DynHandlerFn = dyn Fn(Request) -> Response<'static>;
type BoxedHandlerFn = Box<DynHandlerFn>;
// Collection of handlers for requests // Collection of handlers for requests
pub struct Handlers { pub struct Handlers {
matchers: HashMap<String, HandlerFn>, matchers: HashMap<String, BoxedHandlerFn>,
} }
impl Handlers { impl Handlers {
@ -30,8 +31,8 @@ impl Handlers {
/// ///
/// path: Path to match (no trailing /) /// path: Path to match (no trailing /)
/// handler: Function to handle the request. Must return a Response /// handler: Function to handle the request. Must return a Response
pub fn add_handler(&mut self, path: &str, handler: HandlerFn) { pub fn add_handler(&mut self, path: &str, handler: impl Fn(Request) -> Response<'static> + 'static) {
self.matchers.insert(path.to_string(), handler); self.matchers.insert(path.to_string(), Box::from(handler));
} }
/// Bind these handlers to a listener in order to handle incoming requests /// Bind these handlers to a listener in order to handle incoming requests
@ -65,11 +66,11 @@ impl Handlers {
} }
} }
fn match_handler(&self, url: &URL) -> Option<HandlerFn> { fn match_handler(&self, url: &URL) -> Option<&BoxedHandlerFn> {
'matching_loop: for (path, handler) in self.matchers.iter() { 'matching_loop: for (path, handler) in self.matchers.iter() {
// Exact match // Exact match
if path == &url.path { if path == &url.path {
return Some(*handler); return Some(handler);
}; };
// Segment matching // Segment matching
@ -109,7 +110,7 @@ impl Handlers {
break 'matching_loop; break 'matching_loop;
} }
return Some(*handler); return Some(handler);
} }
None None