aws_smithy_http_server/routing/
route.rs1use crate::body::{Body, BoxBody};
36use http::{Request, Response};
37use std::{
38    convert::Infallible,
39    fmt,
40    future::Future,
41    pin::Pin,
42    task::{Context, Poll},
43};
44use tower::{
45    util::{BoxCloneService, Oneshot},
46    Service, ServiceExt,
47};
48
49pub struct Route<B = Body> {
53    service: BoxCloneService<Request<B>, Response<BoxBody>, Infallible>,
54}
55
56impl<B> Route<B> {
57    pub fn new<T>(svc: T) -> Self
59    where
60        T: Service<Request<B>, Response = Response<BoxBody>, Error = Infallible> + Clone + Send + 'static,
61        T::Future: Send + 'static,
62    {
63        Self {
64            service: BoxCloneService::new(svc),
65        }
66    }
67}
68
69impl<ReqBody> Clone for Route<ReqBody> {
70    fn clone(&self) -> Self {
71        Self {
72            service: self.service.clone(),
73        }
74    }
75}
76
77impl<ReqBody> fmt::Debug for Route<ReqBody> {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        f.debug_struct("Route").finish()
80    }
81}
82
83impl<B> Service<Request<B>> for Route<B> {
84    type Response = Response<BoxBody>;
85    type Error = Infallible;
86    type Future = RouteFuture<B>;
87
88    #[inline]
89    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
90        Poll::Ready(Ok(()))
91    }
92
93    #[inline]
94    fn call(&mut self, req: Request<B>) -> Self::Future {
95        RouteFuture::new(self.service.clone().oneshot(req))
96    }
97}
98
99pin_project_lite::pin_project! {
100    pub struct RouteFuture<B> {
102        #[pin]
103        future: Oneshot<BoxCloneService<Request<B>, Response<BoxBody>, Infallible>, Request<B>>,
104    }
105}
106
107impl<B> RouteFuture<B> {
108    pub(crate) fn new(future: Oneshot<BoxCloneService<Request<B>, Response<BoxBody>, Infallible>, Request<B>>) -> Self {
109        RouteFuture { future }
110    }
111}
112
113impl<B> Future for RouteFuture<B> {
114    type Output = Result<Response<BoxBody>, Infallible>;
115
116    #[inline]
117    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
118        self.project().future.poll(cx)
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    #[test]
127    fn traits() {
128        use crate::test_helpers::*;
129
130        assert_send::<Route<()>>();
131    }
132}