use std::{convert::Infallible, fmt}; use http::Request; use tower::Service; use crate::{ body::HttpBody, handler::Handler, routing::{future::RouteFuture, Route}, Router, }; pub(crate) struct BoxedIntoRoute(Box>); impl BoxedIntoRoute where S: Clone + Send + Sync + 'static, B: Send + 'static, { pub(crate) fn from_handler(handler: H) -> Self where H: Handler, T: 'static, B: HttpBody, { Self(Box::new(MakeErasedHandler { handler, into_route: |handler, state| Route::new(Handler::with_state(handler, state)), })) } } impl BoxedIntoRoute { pub(crate) fn map(self, f: F) -> BoxedIntoRoute where S: 'static, B: 'static, E: 'static, F: FnOnce(Route) -> Route + Clone + Send + 'static, B2: HttpBody + 'static, E2: 'static, { BoxedIntoRoute(Box::new(Map { inner: self.0, layer: Box::new(f), })) } pub(crate) fn into_route(self, state: S) -> Route { self.0.into_route(state) } } impl Clone for BoxedIntoRoute { fn clone(&self) -> Self { Self(self.0.clone_box()) } } impl fmt::Debug for BoxedIntoRoute { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("BoxedIntoRoute").finish() } } pub(crate) trait ErasedIntoRoute: Send { fn clone_box(&self) -> Box>; fn into_route(self: Box, state: S) -> Route; fn call_with_state(self: Box, request: Request, state: S) -> RouteFuture; } pub(crate) struct MakeErasedHandler { pub(crate) handler: H, pub(crate) into_route: fn(H, S) -> Route, } impl ErasedIntoRoute for MakeErasedHandler where H: Clone + Send + 'static, S: 'static, B: HttpBody + 'static, { fn clone_box(&self) -> Box> { Box::new(self.clone()) } fn into_route(self: Box, state: S) -> Route { (self.into_route)(self.handler, state) } fn call_with_state( self: Box, request: Request, state: S, ) -> RouteFuture { self.into_route(state).call(request) } } impl Clone for MakeErasedHandler where H: Clone, { fn clone(&self) -> Self { Self { handler: self.handler.clone(), into_route: self.into_route, } } } pub(crate) struct MakeErasedRouter { pub(crate) router: Router, pub(crate) into_route: fn(Router, S) -> Route, } impl ErasedIntoRoute for MakeErasedRouter where S: Clone + Send + Sync + 'static, B: HttpBody + Send + 'static, { fn clone_box(&self) -> Box> { Box::new(self.clone()) } fn into_route(self: Box, state: S) -> Route { (self.into_route)(self.router, state) } fn call_with_state( mut self: Box, request: Request, state: S, ) -> RouteFuture { self.router.call_with_state(request, state) } } impl Clone for MakeErasedRouter where S: Clone, { fn clone(&self) -> Self { Self { router: self.router.clone(), into_route: self.into_route, } } } pub(crate) struct Map { pub(crate) inner: Box>, pub(crate) layer: Box>, } impl ErasedIntoRoute for Map where S: 'static, B: 'static, E: 'static, B2: HttpBody + 'static, E2: 'static, { fn clone_box(&self) -> Box> { Box::new(Self { inner: self.inner.clone_box(), layer: self.layer.clone_box(), }) } fn into_route(self: Box, state: S) -> Route { (self.layer)(self.inner.into_route(state)) } fn call_with_state(self: Box, request: Request, state: S) -> RouteFuture { (self.layer)(self.inner.into_route(state)).call(request) } } pub(crate) trait LayerFn: FnOnce(Route) -> Route + Send { fn clone_box(&self) -> Box>; } impl LayerFn for F where F: FnOnce(Route) -> Route + Clone + Send + 'static, { fn clone_box(&self) -> Box> { Box::new(self.clone()) } }