1use std::{
12 future::{Future, IntoFuture},
13 pin::Pin,
14};
15
16pub trait TransposeFuture {
17 type Output: Future;
18 fn transpose(self) -> Self::Output;
19}
20impl<F: IntoFuture> TransposeFuture for Option<F> {
21 type Output = TransposedOption<F::IntoFuture>;
22 fn transpose(self) -> Self::Output {
31 TransposedOption(self.map(IntoFuture::into_future))
32 }
33}
34pub struct TransposedOption<F>(Option<F>);
35impl<F: Future> Future for TransposedOption<F> {
36 type Output = Option<F::Output>;
37 fn poll(
38 self: std::pin::Pin<&mut Self>,
39 cx: &mut std::task::Context<'_>,
40 ) -> std::task::Poll<Self::Output> {
41 match unsafe { self.map_unchecked_mut(|x| &mut x.0) }.as_pin_mut() {
43 Some(f) => f.poll(cx).map(Some),
44 None => std::task::Poll::Ready(None),
45 }
46 }
47}
48impl<F: IntoFuture, T: Unpin> TransposeFuture for Result<F, T> {
49 type Output = TransposedResult<F::IntoFuture, T>;
50 fn transpose(self) -> Self::Output {
59 TransposedResult(self.map(IntoFuture::into_future).map_err(Some))
60 }
61}
62pub struct TransposedResult<F, T>(Result<F, Option<T>>);
63impl<F: Future, T: Unpin> Future for TransposedResult<F, T> {
64 type Output = Result<F::Output, T>;
65 fn poll(
66 self: std::pin::Pin<&mut Self>,
67 cx: &mut std::task::Context<'_>,
68 ) -> std::task::Poll<Self::Output> {
69 let mapped = unsafe {
71 let x = self.get_unchecked_mut();
72 match &mut x.0 {
73 Ok(f) => Ok(Pin::new_unchecked(f)),
74 Err(e) => Err(Pin::new_unchecked(e)),
75 }
76 };
77 match mapped {
78 Ok(f) => f.poll(cx).map(Ok),
79 Err(e) => std::task::Poll::Ready(Err(e.get_mut().take().unwrap())),
80 }
81 }
82}