aws_smithy_http_server/operation/
handler.rs1use std::{
7 convert::Infallible,
8 future::Future,
9 marker::PhantomData,
10 task::{Context, Poll},
11};
12
13use futures_util::{future::Map, FutureExt};
14use tower::Service;
15
16use super::OperationShape;
17
18pub trait Handler<Op, Exts>
22where
23 Op: OperationShape,
24{
25 type Future: Future<Output = Result<Op::Output, Op::Error>>;
26
27 fn call(&mut self, input: Op::Input, exts: Exts) -> Self::Future;
28}
29
30trait IntoResult<Ok, Error> {
32 fn into_result(self) -> Result<Ok, Error>;
33}
34
35impl<Ok, Error> IntoResult<Ok, Error> for Result<Ok, Error> {
37 fn into_result(self) -> Result<Ok, Error> {
38 self
39 }
40}
41
42impl<Ok> IntoResult<Ok, Infallible> for Ok {
44 fn into_result(self) -> Result<Ok, Infallible> {
45 Ok(self)
46 }
47}
48
49impl<Op, F, Fut> Handler<Op, ()> for F
51where
52 Op: OperationShape,
53 F: Fn(Op::Input) -> Fut,
54 Fut: Future,
55 Fut::Output: IntoResult<Op::Output, Op::Error>,
56{
57 type Future = Map<Fut, fn(Fut::Output) -> Result<Op::Output, Op::Error>>;
58
59 fn call(&mut self, input: Op::Input, _exts: ()) -> Self::Future {
60 (self)(input).map(IntoResult::into_result)
61 }
62}
63
64macro_rules! impl_handler {
66 ($($var:ident),+) => (
67 impl<Op, F, Fut, $($var,)*> Handler<Op, ($($var,)*)> for F
68 where
69 Op: OperationShape,
70 F: Fn(Op::Input, $($var,)*) -> Fut,
71 Fut: Future,
72 Fut::Output: IntoResult<Op::Output, Op::Error>,
73 {
74 type Future = Map<Fut, fn(Fut::Output) -> Result<Op::Output, Op::Error>>;
75
76 fn call(&mut self, input: Op::Input, exts: ($($var,)*)) -> Self::Future {
77 #[allow(non_snake_case)]
78 let ($($var,)*) = exts;
79 (self)(input, $($var,)*).map(IntoResult::into_result)
80 }
81 }
82 )
83}
84
85impl_handler!(Exts0);
86impl_handler!(Exts0, Exts1);
87impl_handler!(Exts0, Exts1, Exts2);
88impl_handler!(Exts0, Exts1, Exts2, Exts3);
89impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4);
90impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5);
91impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6);
92impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6, Exts7);
93impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6, Exts7, Exts8);
94
95pub trait HandlerExt<Op, Exts>: Handler<Op, Exts>
97where
98 Op: OperationShape,
99{
100 fn into_service(self) -> IntoService<Op, Self>
102 where
103 Self: Sized,
104 {
105 IntoService {
106 handler: self,
107 _operation: PhantomData,
108 }
109 }
110}
111
112impl<Op, Exts, H> HandlerExt<Op, Exts> for H
113where
114 Op: OperationShape,
115 H: Handler<Op, Exts>,
116{
117}
118
119pub struct IntoService<Op, H> {
121 pub(crate) handler: H,
122 pub(crate) _operation: PhantomData<Op>,
123}
124
125impl<Op, H> Clone for IntoService<Op, H>
126where
127 H: Clone,
128{
129 fn clone(&self) -> Self {
130 Self {
131 handler: self.handler.clone(),
132 _operation: PhantomData,
133 }
134 }
135}
136
137impl<Op, Exts, H> Service<(Op::Input, Exts)> for IntoService<Op, H>
138where
139 Op: OperationShape,
140 H: Handler<Op, Exts>,
141{
142 type Response = Op::Output;
143 type Error = Op::Error;
144 type Future = H::Future;
145
146 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
147 Poll::Ready(Ok(()))
148 }
149
150 fn call(&mut self, (input, exts): (Op::Input, Exts)) -> Self::Future {
151 self.handler.call(input, exts)
152 }
153}