1#![warn(missing_docs)]
2pub struct Request<T>(pub T);
17
18pub struct Response<T> {
21 pub inner: Result<T, String>,
23}
24
25impl<T> Response<T> {
26 pub fn ok(value: T) -> Self {
28 Self { inner: Ok(value) }
29 }
30 pub fn err(msg: impl Into<String>) -> Self {
32 Self {
33 inner: Err(msg.into()),
34 }
35 }
36 pub fn is_ok(&self) -> bool {
38 self.inner.is_ok()
39 }
40 pub fn is_err(&self) -> bool {
42 self.inner.is_err()
43 }
44}
45
46pub enum Branch<Req, Resp> {
49 Continue(Request<Req>),
51 Done(Response<Resp>),
53}
54
55pub trait Jig<In> {
59 type Out;
61 fn run(&self, input: In) -> Self::Out;
63}
64
65impl<In, Out, F> Jig<In> for F
66where
67 F: Fn(In) -> Out,
68{
69 type Out = Out;
70 fn run(&self, input: In) -> Out {
71 (self)(input)
72 }
73}
74
75pub struct Pending<F>(pub F);
81
82pub trait Step {
86 type Out;
88 type Fut: core::future::Future<Output = Self::Out>;
90 fn into_step(self) -> Self::Fut;
92}
93
94impl<T> Step for Request<T> {
95 type Out = Request<T>;
96 type Fut = core::future::Ready<Request<T>>;
97 fn into_step(self) -> Self::Fut {
98 core::future::ready(self)
99 }
100}
101
102impl<T> Step for Response<T> {
103 type Out = Response<T>;
104 type Fut = core::future::Ready<Response<T>>;
105 fn into_step(self) -> Self::Fut {
106 core::future::ready(self)
107 }
108}
109
110impl<R, P> Step for Branch<R, P> {
111 type Out = Branch<R, P>;
112 type Fut = core::future::Ready<Branch<R, P>>;
113 fn into_step(self) -> Self::Fut {
114 core::future::ready(self)
115 }
116}
117
118impl<F> Step for Pending<F>
119where
120 F: core::future::Future,
121{
122 type Out = F::Output;
123 type Fut = F;
124 fn into_step(self) -> Self::Fut {
125 self.0
126 }
127}
128
129impl<F> core::future::IntoFuture for Pending<F>
130where
131 F: core::future::Future,
132{
133 type Output = F::Output;
134 type IntoFuture = F;
135 fn into_future(self) -> F {
136 self.0
137 }
138}
139
140impl<F> Pending<F>
141where
142 F: core::future::Future + 'static,
143{
144 pub fn then<J, R>(self, jig: J) -> Pending<impl core::future::Future<Output = R::Out>>
147 where
148 J: Jig<F::Output, Out = R> + 'static,
149 R: Step + 'static,
150 {
151 Pending(async move {
152 let val = self.0.await;
153 jig.run(val).into_step().await
154 })
155 }
156}
157
158pub trait Status {
161 fn ok(&self) -> bool;
163 fn error(&self) -> Option<String> {
165 None
166 }
167}
168
169impl<T> Status for Request<T> {
170 fn ok(&self) -> bool {
171 true
172 }
173}
174
175impl<T> Status for Response<T> {
176 fn ok(&self) -> bool {
177 self.is_ok()
178 }
179 fn error(&self) -> Option<String> {
180 self.inner.as_ref().err().cloned()
181 }
182}
183
184impl<Req, Resp> Status for Branch<Req, Resp> {
185 fn ok(&self) -> bool {
186 match self {
187 Branch::Continue(_) => true,
188 Branch::Done(r) => r.is_ok(),
189 }
190 }
191 fn error(&self) -> Option<String> {
192 match self {
193 Branch::Continue(_) => None,
194 Branch::Done(r) => r.inner.as_ref().err().cloned(),
195 }
196 }
197}
198
199pub trait Merge<Resp> {
203 type Merged;
205 fn into_continue(self) -> Self::Merged;
207 fn from_done(resp: Response<Resp>) -> Self::Merged;
209}
210
211impl<NewReq, Resp> Merge<Resp> for Request<NewReq> {
212 type Merged = Branch<NewReq, Resp>;
213 fn into_continue(self) -> Self::Merged {
214 Branch::Continue(self)
215 }
216 fn from_done(resp: Response<Resp>) -> Self::Merged {
217 Branch::Done(resp)
218 }
219}
220
221impl<Resp> Merge<Resp> for Response<Resp> {
222 type Merged = Response<Resp>;
223 fn into_continue(self) -> Self::Merged {
224 self
225 }
226 fn from_done(resp: Response<Resp>) -> Self::Merged {
227 resp
228 }
229}
230
231impl<NewReq, Resp> Merge<Resp> for Branch<NewReq, Resp> {
232 type Merged = Branch<NewReq, Resp>;
233 fn into_continue(self) -> Self::Merged {
234 self
235 }
236 fn from_done(resp: Response<Resp>) -> Self::Merged {
237 Branch::Done(resp)
238 }
239}
240
241impl<T> Request<T> {
242 pub fn then<J, U>(self, jig: J) -> U
244 where
245 J: Jig<Request<T>, Out = U>,
246 {
247 jig.run(self)
248 }
249}
250
251impl<T> Response<T> {
252 pub fn then<J, U>(self, jig: J) -> Response<U>
254 where
255 J: Jig<Response<T>, Out = Response<U>>,
256 {
257 match self.inner {
258 Ok(_) => jig.run(self),
259 Err(e) => Response { inner: Err(e) },
260 }
261 }
262}
263
264impl<Req, Resp> Branch<Req, Resp> {
265 pub fn then<J>(self, jig: J) -> <J::Out as Merge<Resp>>::Merged
268 where
269 J: Jig<Request<Req>>,
270 J::Out: Merge<Resp>,
271 {
272 match self {
273 Branch::Continue(r) => <J::Out as Merge<Resp>>::into_continue(jig.run(r)),
274 Branch::Done(resp) => <J::Out as Merge<Resp>>::from_done(resp),
275 }
276 }
277}
278
279#[cfg(test)]
280mod tests;