pollable_map/futures/
optional.rs1use futures::future::FusedFuture;
2use std::future::Future;
3use std::pin::Pin;
4use std::task::{Context, Poll, Waker};
5
6pub struct OptionalFuture<F> {
14 future: Option<F>,
15 waker: Option<Waker>,
16}
17
18impl<F: Unpin> Unpin for OptionalFuture<F> {}
19
20impl<F> Default for OptionalFuture<F> {
21 fn default() -> Self {
22 Self {
23 future: None,
24 waker: None,
25 }
26 }
27}
28
29impl<F> From<Option<F>> for OptionalFuture<F> {
30 fn from(fut: Option<F>) -> Self {
31 Self {
32 future: fut,
33 waker: None,
34 }
35 }
36}
37
38impl<F: Future> From<F> for OptionalFuture<F> {
39 fn from(fut: F) -> Self {
40 Self {
41 future: Some(fut),
42 waker: None,
43 }
44 }
45}
46
47impl<F> OptionalFuture<F> {
48 pub fn new(future: F) -> Self {
50 Self {
51 future: Some(future),
52 waker: None,
53 }
54 }
55
56 pub fn take(&mut self) -> Option<F> {
58 let fut = self.future.take();
59 if let Some(waker) = self.waker.take() {
60 waker.wake();
61 }
62 fut
63 }
64
65 pub fn is_some(&self) -> bool {
67 self.future.is_some()
68 }
69
70 pub fn is_none(&self) -> bool {
72 self.future.is_none()
73 }
74
75 pub fn as_ref(&self) -> Option<&F> {
77 self.future.as_ref()
78 }
79
80 pub fn as_mut(&mut self) -> Option<&mut F> {
82 self.future.as_mut()
83 }
84
85 pub fn replace(&mut self, future: F) -> Option<F> {
87 let fut = self.future.replace(future);
88 if let Some(waker) = self.waker.take() {
89 waker.wake();
90 }
91 fut
92 }
93}
94
95impl<F> Future for OptionalFuture<F>
96where
97 F: Future + Send + Unpin + 'static,
98{
99 type Output = F::Output;
100
101 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
102 let Some(future) = self.future.as_mut() else {
103 self.waker.replace(cx.waker().clone());
104 return Poll::Pending;
105 };
106
107 match Pin::new(future).poll(cx) {
108 Poll::Ready(output) => {
109 self.future.take();
110 Poll::Ready(output)
111 }
112 Poll::Pending => {
113 self.waker.replace(cx.waker().clone());
114 Poll::Pending
115 }
116 }
117 }
118}
119
120impl<F: Future> FusedFuture for OptionalFuture<F>
121where
122 F: Future + Send + Unpin + 'static,
123{
124 fn is_terminated(&self) -> bool {
125 self.future.is_none()
126 }
127}
128
129#[cfg(test)]
130mod test {
131 use super::*;
132
133 #[test]
134 fn test_optional_future() {
135 let mut future = OptionalFuture::new(futures::future::ready(0));
136 assert!(future.is_some());
137 let waker = futures::task::noop_waker_ref();
138
139 let val = Pin::new(&mut future).poll(&mut Context::from_waker(waker));
140 assert_eq!(val, Poll::Ready(0));
141 assert!(future.is_none());
142 }
143
144 #[test]
145 fn reusable_optional_future() {
146 let mut future = OptionalFuture::new(futures::future::ready(0));
147 assert!(future.is_some());
148 let waker = futures::task::noop_waker_ref();
149
150 let val = Pin::new(&mut future).poll(&mut Context::from_waker(waker));
151 assert_eq!(val, Poll::Ready(0));
152 assert!(future.is_none());
153
154 future.replace(futures::future::ready(1));
155 assert!(future.is_some());
156
157 let val = Pin::new(&mut future).poll(&mut Context::from_waker(waker));
158 assert_eq!(val, Poll::Ready(1));
159 assert!(future.is_none());
160 }
161
162 #[test]
163 fn convert_future_to_optional_future() {
164 let fut = futures::future::ready(0);
165
166 let mut future = OptionalFuture::from(fut);
167 assert!(future.is_some());
168 let waker = futures::task::noop_waker_ref();
169
170 let val = Pin::new(&mut future).poll(&mut Context::from_waker(waker));
171 assert_eq!(val, Poll::Ready(0));
172 assert!(future.is_none());
173 }
174}