use std::fmt::{self, Debug};
use std::rc::Rc;
use std::sync::Arc;
use crate::{path::Path, Method, Request, Response};
type StatelessRoute = Box<dyn Fn(&Request) -> Response + Send + Sync>;
type StatefulRoute<State> = Box<dyn Fn(Arc<State>, &Request) -> Response + Send + Sync>;
pub enum RouteType<State> {
Stateless(StatelessRoute),
Stateful(StatefulRoute<State>),
}
#[derive(Debug)]
pub struct Route<State> {
method: Method,
path: Path,
pub(crate) handler: RouteType<State>,
}
impl<State> Route<State> {
pub(crate) fn new(method: Method, path: String, handler: StatelessRoute) -> Self {
Self {
method,
path: Path::new(path),
handler: RouteType::Stateless(handler),
}
}
pub(crate) fn new_stateful(
method: Method,
path: String,
handler: StatefulRoute<State>,
) -> Self {
Self {
method,
path: Path::new(path),
handler: RouteType::Stateful(handler),
}
}
pub(crate) fn is_stateful(&self) -> bool {
matches!(self.handler, RouteType::Stateful(_))
}
pub(crate) fn matches(&self, req: Rc<Request>) -> Option<Vec<(String, String)>> {
if self.method != Method::ANY && self.method != req.method {
return None;
}
self.path.match_path(req.path.clone())
}
}
impl<State> Debug for RouteType<State> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RouteType::Stateless(_) => f.write_str("stateless"),
RouteType::Stateful(_) => f.write_str("stateful"),
}
}
}