krossbar_state_machine/
state.rs1use std::{
2 pin::Pin,
3 task::{Context, Poll},
4};
5
6use futures::{Future, FutureExt};
7
8pub struct State<St, Ret, Err, Fut>
10where
11 Fut: Future<Output = Result<Ret, Err>> + Send,
12{
13 fut: Pin<Box<dyn Future<Output = Result<St, Err>> + Send>>,
15 func: fn(St) -> Fut,
17 func_fut: Option<Pin<Box<Fut>>>,
19}
20
21impl<St: 'static, Ret: 'static, Err: 'static, Fut> State<St, Ret, Err, Fut>
22where
23 Fut: Future<Output = Result<Ret, Err>> + Send + 'static,
24{
25 pub(crate) fn chain(
26 fut: Pin<Box<dyn Future<Output = Result<St, Err>> + Send>>,
27 func: fn(St) -> Fut,
28 ) -> Self {
29 Self {
30 fut,
31 func,
32 func_fut: None,
33 }
34 }
35
36 pub fn then<NRet, NFut>(self, func: fn(Ret) -> NFut) -> State<Ret, NRet, Err, NFut>
38 where
39 NRet: 'static,
40 NFut: Future<Output = Result<NRet, Err>> + Send + 'static,
41 {
42 State::chain(Box::pin(self), func)
43 }
44
45 pub fn unwrap<NRet>(
47 self,
48 func: fn(Result<Ret, Err>) -> NRet,
49 ) -> impl Future<Output = NRet> + Send
50 where
51 NRet: 'static,
52 {
53 self.map(move |value| func(value))
54 }
55}
56
57impl<St, Ret, Err, Fut> Future for State<St, Ret, Err, Fut>
58where
59 Fut: Future<Output = Result<Ret, Err>> + Send,
60{
61 type Output = Result<Ret, Err>;
62
63 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
64 let mut func_fut = match self.func_fut.take() {
66 Some(fut) => fut,
69 _ => {
72 let state = match self.fut.as_mut().poll(cx) {
73 Poll::Ready(value) => match value {
74 Ok(state) => state,
75 Err(e) => return Poll::Ready(Err(e)),
76 },
77 Poll::Pending => return Poll::Pending,
78 };
79
80 Box::pin((self.func)(state))
81 }
82 };
83
84 match func_fut.as_mut().poll(cx) {
85 Poll::Ready(value) => Poll::Ready(value),
86 Poll::Pending => {
87 self.func_fut = Some(func_fut);
89 Poll::Pending
90 }
91 }
92 }
93}
94
95impl<St, Ret, Err, Fut> Unpin for State<St, Ret, Err, Fut> where
96 Fut: Future<Output = Result<Ret, Err>> + Send
97{
98}