cute_async/
fut.rs

1//!Future related utilities
2
3use core::task;
4use core::future::Future;
5use core::pin::Pin;
6
7///Trait describing tranformation into future
8pub trait IntoFuture {
9    ///Resulting Future.
10    type Output: Future;
11
12    ///Transforms self into Future
13    fn into_future(self) -> Self::Output;
14}
15
16#[derive(Debug)]
17///Either variant.
18pub enum Either<A, B> {
19    ///Left
20    Left(A),
21    ///Right
22    Right(B),
23}
24
25impl<A, B> Either<A, B> {
26    ///Returns whether it is Left variant or not.
27    pub fn is_left(&self) -> bool {
28        match self {
29            Either::Left(_) => true,
30            Either::Right(_) => false,
31        }
32    }
33}
34
35impl<A> Either<A, A> {
36    ///Consumes self, returning underlying value
37    ///
38    ///Works only if they are of the same type.
39    pub fn into(self) -> A {
40        match self {
41            Either::Left(res) => res,
42            Either::Right(res) => res,
43        }
44    }
45}
46
47impl<A: Unpin, B: Unpin> Unpin for Either<A, B> {}
48
49impl<A: Unpin, B: Unpin> Future for Either<A, B> where A: Future, B: Future<Output = A::Output> {
50    type Output = A::Output;
51
52    fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
53        match *self {
54            Either::Left(ref mut left) => Future::poll(Pin::new(left), ctx),
55            Either::Right(ref mut right) => Future::poll(Pin::new(right), ctx),
56        }
57    }
58}
59
60#[derive(Debug)]
61///The result of Pair.
62///
63///First argument is Output of completed future
64///Second is unfinished Future.
65///
66///Can be polled again to finish the second Future and return tuple of results
67pub struct UnfinishedPair<O, F> {
68    inner: Option<(O, F)>
69}
70
71impl<O, F: Future> UnfinishedPair<O, F> {
72    #[inline(always)]
73    ///Creates new instance.
74    ///
75    ///Order is enforced via type arguments
76    pub fn new(output: O, fut: F) -> Self {
77        Self {
78            inner: Some((output, fut))
79        }
80    }
81
82    #[inline(always)]
83    ///Consumes self returning underlying parts
84    pub fn into_parts(self) -> (O, F) {
85        self.inner.unwrap()
86    }
87}
88
89impl<O: Unpin, F: Unpin> Unpin for UnfinishedPair<O, F> {}
90
91impl<O: Unpin, F: Unpin> Future for UnfinishedPair<O, F> where F: Future {
92    type Output = (O, F::Output);
93
94    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
95        let (_, ref mut fut) = match self.inner.as_mut() {
96            Some(value) => value,
97            None => unreach!()
98        };
99
100        match Pin::new(fut).poll(cx) {
101            task::Poll::Ready(res) => {
102                let left = match self.inner.take() {
103                    Some((left, _)) => left,
104                    None => unreach!()
105                };
106                task::Poll::Ready((left, res))
107            }
108            task::Poll::Pending => task::Poll::Pending,
109        }
110    }
111}
112
113#[derive(Debug)]
114///Pair of futures that are being processed together.
115///
116///First goes left, then right.
117///
118///Resulting `Either` will contain output of future, alongside not completed future.
119pub struct Pair<A, B> {
120    inner: Option<(A, B)>,
121}
122
123impl<A, B> Pair<A, B> {
124    #[inline(always)]
125    ///Creates new instance
126    pub fn new(left: A, right: B) -> Self {
127        Self {
128            inner: Some((left, right)),
129        }
130    }
131
132    #[inline(always)]
133    ///Consumes self returning underlying parts
134    pub fn into_parts(self) -> (A, B) {
135        self.inner.unwrap()
136    }
137}
138
139impl<A: Unpin, B: Unpin> Unpin for Pair<A, B> {}
140
141impl<A: Unpin, B: Unpin> Future for Pair<A, B> where A: Future, B: Future {
142    type Output = Either<UnfinishedPair<A::Output, B>, UnfinishedPair<B::Output, A>>;
143
144    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
145        let (ref mut left, ref mut right) = match self.inner.as_mut() {
146            Some(value) => value,
147            None => unreach!()
148        };
149
150        match Pin::new(left).poll(cx) {
151            task::Poll::Ready(res) => {
152                let right = match self.inner.take() {
153                    Some((_, right)) => right,
154                    None => unreach!()
155                };
156                task::Poll::Ready(Either::Left(UnfinishedPair::new(res, right)))
157            },
158            task::Poll::Pending => match Pin::new(right).poll(cx) {
159                task::Poll::Ready(res) => {
160                    let left = match self.inner.take() {
161                        Some((left, _)) => left,
162                        None => unreach!(),
163                    };
164
165                    task::Poll::Ready(Either::Right(UnfinishedPair::new(res, left)))
166                },
167                task::Poll::Pending => task::Poll::Pending,
168            }
169        }
170    }
171}