Skip to main content

commonware_utils/
futures.rs

1//! Utilities for working with futures.
2
3use core::ops::{Deref, DerefMut};
4use futures::{
5    StreamExt,
6    future::{self, AbortHandle, Abortable, Aborted},
7    stream::{FuturesUnordered, SelectNextSome},
8};
9use pin_project::pin_project;
10use std::{collections::BTreeMap, future::Future, pin::Pin, task::Poll};
11
12mod shared;
13mod try_join_all;
14pub use shared::{Shared, WeakShared};
15pub use try_join_all::try_join_all;
16
17/// A future type that can be used in [Pool].
18type PooledFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
19
20/// An unordered pool of futures.
21///
22/// Futures can be added to the pool, and removed from the pool as they resolve.
23///
24/// **Note:** This pool is not thread-safe and should not be used across threads without external
25/// synchronization.
26pub struct Pool<'a, T> {
27    pool: FuturesUnordered<PooledFuture<'a, T>>,
28}
29
30impl<'a, T: Send> Default for Pool<'a, T> {
31    fn default() -> Self {
32        // Insert a dummy future (that never resolves) to prevent the stream from being empty.
33        // Else, the `select_next_some()` function returns `None` instantly.
34        let pool = FuturesUnordered::new();
35        pool.push(Self::create_dummy_future());
36        Self { pool }
37    }
38}
39
40impl<'a, T: Send> Pool<'a, T> {
41    /// Returns the number of futures in the pool.
42    pub fn len(&self) -> usize {
43        // Subtract the dummy future.
44        self.pool.len().checked_sub(1).unwrap()
45    }
46
47    /// Returns `true` if the pool is empty.
48    pub fn is_empty(&self) -> bool {
49        self.len() == 0
50    }
51
52    /// Adds a future to the pool.
53    ///
54    /// The future must be `Send` and outlive `'a` to ensure it can be safely stored and executed.
55    pub fn push(&mut self, future: impl Future<Output = T> + Send + 'a) {
56        self.pool.push(Box::pin(future));
57    }
58
59    /// Returns a futures that resolves to the next future in the pool that resolves.
60    ///
61    /// If the pool is empty, the future will never resolve.
62    pub fn next_completed(&mut self) -> SelectNextSome<'_, FuturesUnordered<PooledFuture<'a, T>>> {
63        self.pool.select_next_some()
64    }
65
66    /// Cancels all futures in the pool.
67    ///
68    /// Excludes the dummy future.
69    pub fn cancel_all(&mut self) {
70        self.pool.clear();
71        self.pool.push(Self::create_dummy_future());
72    }
73
74    /// Creates a dummy future that never resolves.
75    fn create_dummy_future() -> PooledFuture<'a, T> {
76        Box::pin(async { future::pending::<T>().await })
77    }
78}
79
80/// A handle that can be used to abort a specific future in an [AbortablePool].
81///
82/// When the aborter is dropped, the associated future is aborted.
83pub struct Aborter {
84    inner: AbortHandle,
85}
86
87impl Drop for Aborter {
88    fn drop(&mut self) {
89        self.inner.abort();
90    }
91}
92
93/// A future type that can be used in [AbortablePool].
94type AbortablePooledFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T, Aborted>> + Send + 'a>>;
95
96/// An unordered pool of futures that can be individually aborted.
97///
98/// Each future added to the pool returns an [Aborter]. When the aborter is dropped,
99/// the associated future is aborted.
100///
101/// **Note:** This pool is not thread-safe and should not be used across threads without external
102/// synchronization.
103pub struct AbortablePool<'a, T> {
104    pool: FuturesUnordered<AbortablePooledFuture<'a, T>>,
105}
106
107impl<'a, T: Send> Default for AbortablePool<'a, T> {
108    fn default() -> Self {
109        // Insert a dummy future (that never resolves) to prevent the stream from being empty.
110        // Else, the `select_next_some()` function returns `None` instantly.
111        let pool = FuturesUnordered::new();
112        pool.push(Self::create_dummy_future());
113        Self { pool }
114    }
115}
116
117impl<'a, T: Send> AbortablePool<'a, T> {
118    /// Returns the number of futures in the pool.
119    pub fn len(&self) -> usize {
120        // Subtract the dummy future.
121        self.pool.len().checked_sub(1).unwrap()
122    }
123
124    /// Returns `true` if the pool is empty.
125    pub fn is_empty(&self) -> bool {
126        self.len() == 0
127    }
128
129    /// Adds a future to the pool and returns an [Aborter] that can be used to abort it.
130    ///
131    /// The future must be `Send` and outlive `'a` to ensure it can be safely stored and executed.
132    /// When the returned [Aborter] is dropped, the future will be aborted.
133    pub fn push(&mut self, future: impl Future<Output = T> + Send + 'a) -> Aborter {
134        let (handle, registration) = AbortHandle::new_pair();
135        let abortable_future = Abortable::new(future, registration);
136        self.pool.push(Box::pin(abortable_future));
137        Aborter { inner: handle }
138    }
139
140    /// Returns a future that resolves to the next future in the pool that resolves.
141    ///
142    /// If the pool is empty, the future will never resolve.
143    /// Returns `Ok(T)` for successful completion or `Err(Aborted)` for aborted futures.
144    pub fn next_completed(
145        &mut self,
146    ) -> SelectNextSome<'_, FuturesUnordered<AbortablePooledFuture<'a, T>>> {
147        self.pool.select_next_some()
148    }
149
150    /// Creates a dummy future that never resolves.
151    fn create_dummy_future() -> AbortablePooledFuture<'a, T> {
152        Box::pin(async { Ok(future::pending::<T>().await) })
153    }
154}
155
156/// An optional future that yields [Poll::Pending] when [None]. Useful within `select!` macros,
157/// where a future may be conditionally present.
158///
159/// Not to be confused with [futures::future::OptionFuture], which resolves to [None] immediately
160/// when the inner future is `None`.
161#[pin_project]
162pub struct OptionFuture<F: Future>(#[pin] Option<F>);
163
164impl<F: Future> Default for OptionFuture<F> {
165    fn default() -> Self {
166        Self(None)
167    }
168}
169
170impl<F: Future> From<Option<F>> for OptionFuture<F> {
171    fn from(opt: Option<F>) -> Self {
172        Self(opt)
173    }
174}
175
176impl<F: Future> Deref for OptionFuture<F> {
177    type Target = Option<F>;
178
179    fn deref(&self) -> &Self::Target {
180        &self.0
181    }
182}
183
184impl<F: Future> DerefMut for OptionFuture<F> {
185    fn deref_mut(&mut self) -> &mut Self::Target {
186        &mut self.0
187    }
188}
189
190impl<F: Future> Future for OptionFuture<F> {
191    type Output = F::Output;
192
193    fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
194        let this = self.project();
195        this.0
196            .as_pin_mut()
197            .map_or_else(|| Poll::Pending, |fut| fut.poll(cx))
198    }
199}
200
201/// The result of an operation that consumes and returns a value.
202///
203/// [rebind] and [rebind_entry] restore the value and return the extra outputs:
204///
205/// | Operation returns | Value restored | Helper returns |
206/// | --- | --- | --- |
207/// | `Ok(value)` | `value` | `Ok(())` |
208/// | `Ok((value, a))` | `value` | `Ok(a)` |
209/// | `Ok((value, a, b))` | `value` | `Ok((a, b))` |
210pub trait Threaded<T> {
211    /// The outputs beyond the threaded value.
212    type Rest;
213
214    /// Splits into the threaded value and the extra outputs.
215    fn split(self) -> (T, Self::Rest);
216}
217
218impl<T> Threaded<T> for T {
219    type Rest = ();
220
221    fn split(self) -> (T, ()) {
222        (self, ())
223    }
224}
225
226impl<T, A> Threaded<T> for (T, A) {
227    type Rest = A;
228
229    fn split(self) -> (T, A) {
230        self
231    }
232}
233
234impl<T, A, B> Threaded<T> for (T, A, B) {
235    type Rest = (A, B);
236
237    fn split(self) -> (T, (A, B)) {
238        let (value, a, b) = self;
239        (value, (a, b))
240    }
241}
242
243/// Runs an async operation that consumes the value in `slot`, then restores the
244/// returned value and yields any extra outputs (see [Threaded]).
245///
246/// Use this to call a method that consumes `self` on a value stored in an [Option].
247///
248/// On error, `slot` stays empty.
249///
250/// # Cancellation
251///
252/// The value is removed when this future is first polled. Dropping the future while
253/// the operation is pending leaves `slot` empty.
254///
255/// # Examples
256///
257/// Append a record to a journal whose `append` method returns `(Self, offset, length)`:
258///
259/// ```
260/// use commonware_utils::futures::rebind;
261///
262/// # #[derive(Default)]
263/// # struct Journal(Vec<u8>);
264/// # impl Journal {
265/// #     async fn append(mut self, record: &[u8]) -> Result<(Self, usize, usize), &'static str> {
266/// #         let offset = self.0.len();
267/// #         self.0.extend_from_slice(record);
268/// #         Ok((self, offset, record.len()))
269/// #     }
270/// # }
271/// # futures::executor::block_on(async {
272/// let mut journal = Some(Journal::default());
273/// let (offset, len) = rebind(&mut journal, |journal| journal.append(b"vote"))
274///     .await
275///     .expect("append failed");
276/// assert_eq!((offset, len), (0, 4));
277/// assert!(journal.is_some());
278/// # });
279/// ```
280///
281/// # Panics
282///
283/// Panics when `slot` is empty.
284pub async fn rebind<T, Out, Fut, E>(
285    slot: &mut Option<T>,
286    op: impl FnOnce(T) -> Fut,
287) -> Result<Out::Rest, E>
288where
289    Out: Threaded<T>,
290    Fut: Future<Output = Result<Out, E>>,
291{
292    let value = slot.take().expect("cannot rebind an empty slot");
293    let (value, rest) = op(value).await?.split();
294    *slot = Some(value);
295    Ok(rest)
296}
297
298/// Runs an async operation that consumes the value at `key` in `map`, then restores
299/// the returned value under the original key and yields any extra outputs (see [Threaded]).
300///
301/// Use this to call a method that consumes `self` on a value stored in a [BTreeMap].
302/// For a value stored in an [Option], use [rebind].
303///
304/// On error, the entry stays absent.
305///
306/// # Cancellation
307///
308/// The entry is removed when this future is first polled. Dropping the future while
309/// the operation is pending leaves the entry absent.
310///
311/// # Examples
312///
313/// Append a record to epoch 7's journal, whose `append` method returns `(Self, position)`:
314///
315/// ```
316/// use commonware_utils::futures::rebind_entry;
317/// use std::collections::BTreeMap;
318///
319/// # #[derive(Default)]
320/// # struct Journal(Vec<&'static str>);
321/// # impl Journal {
322/// #     async fn append(mut self, record: &'static str) -> Result<(Self, usize), &'static str> {
323/// #         let position = self.0.len();
324/// #         self.0.push(record);
325/// #         Ok((self, position))
326/// #     }
327/// # }
328/// # futures::executor::block_on(async {
329/// let mut journals = BTreeMap::from([(7, Journal::default())]);
330/// let position = rebind_entry(&mut journals, &7, |journal| journal.append("vote"))
331///     .await
332///     .expect("append failed");
333/// assert_eq!(position, 0);
334/// assert!(journals.contains_key(&7));
335/// # });
336/// ```
337///
338/// # Panics
339///
340/// Panics when `key` is absent from `map`.
341pub async fn rebind_entry<K, V, Out, Fut, E>(
342    map: &mut BTreeMap<K, V>,
343    key: &K,
344    op: impl FnOnce(V) -> Fut,
345) -> Result<Out::Rest, E>
346where
347    K: Ord,
348    Out: Threaded<V>,
349    Fut: Future<Output = Result<Out, E>>,
350{
351    let (key, value) = map
352        .remove_entry(key)
353        .expect("cannot rebind a missing entry");
354    let (value, rest) = op(value).await?.split();
355    map.insert(key, value);
356    Ok(rest)
357}
358
359#[cfg(test)]
360mod tests {
361    use super::*;
362    use crate::channel::oneshot;
363    use futures::{
364        executor::block_on,
365        future::{self, Either, select},
366        pin_mut,
367    };
368    use std::{
369        sync::{
370            Arc,
371            atomic::{AtomicBool, Ordering},
372        },
373        thread,
374        time::Duration,
375    };
376
377    /// A future that resolves after a given duration.
378    fn delay(duration: Duration) -> impl Future<Output = ()> {
379        let (sender, receiver) = oneshot::channel();
380        thread::spawn(move || {
381            thread::sleep(duration);
382            sender.send(()).unwrap();
383        });
384        async move {
385            let _ = receiver.await;
386        }
387    }
388
389    #[test]
390    fn test_initialization() {
391        let pool = Pool::<i32>::default();
392        assert_eq!(pool.len(), 0);
393        assert!(pool.is_empty());
394    }
395
396    #[test]
397    fn test_dummy_future_doesnt_resolve() {
398        block_on(async {
399            let mut pool = Pool::<i32>::default();
400            let stream_future = pool.next_completed();
401            let timeout_future = async {
402                delay(Duration::from_millis(100)).await;
403            };
404            pin_mut!(stream_future);
405            pin_mut!(timeout_future);
406            let result = select(stream_future, timeout_future).await;
407            match result {
408                Either::Left((_, _)) => panic!("Stream resolved unexpectedly"),
409                Either::Right((_, _)) => {
410                    // Timeout occurred, which is expected
411                }
412            }
413        });
414    }
415
416    #[test]
417    fn test_adding_futures() {
418        let mut pool = Pool::<i32>::default();
419        assert_eq!(pool.len(), 0);
420        assert!(pool.is_empty());
421
422        pool.push(async { 42 });
423        assert_eq!(pool.len(), 1);
424        assert!(!pool.is_empty(),);
425
426        pool.push(async { 43 });
427        assert_eq!(pool.len(), 2,);
428    }
429
430    #[test]
431    fn test_streaming_resolved_futures() {
432        block_on(async move {
433            let mut pool = Pool::<i32>::default();
434            pool.push(future::ready(42));
435            let result = pool.next_completed().await;
436            assert_eq!(result, 42,);
437            assert!(pool.is_empty(),);
438        });
439    }
440
441    #[test]
442    fn test_multiple_futures() {
443        block_on(async move {
444            let mut pool = Pool::<i32>::default();
445
446            // Futures resolve in order of completion, not addition order
447            let (finisher_1, finished_1) = oneshot::channel();
448            let (finisher_3, finished_3) = oneshot::channel();
449            pool.push(async move {
450                finished_1.await.unwrap();
451                finisher_3.send(()).unwrap();
452                1
453            });
454            pool.push(async move {
455                finisher_1.send(()).unwrap();
456                2
457            });
458            pool.push(async move {
459                finished_3.await.unwrap();
460                3
461            });
462
463            let first = pool.next_completed().await;
464            assert_eq!(first, 2, "First resolved should be 2");
465            let second = pool.next_completed().await;
466            assert_eq!(second, 1, "Second resolved should be 1");
467            let third = pool.next_completed().await;
468            assert_eq!(third, 3, "Third resolved should be 3");
469            assert!(pool.is_empty(),);
470        });
471    }
472
473    #[test]
474    fn test_cancel_all() {
475        block_on(async move {
476            let flag = Arc::new(AtomicBool::new(false));
477            let flag_clone = flag.clone();
478            let mut pool = Pool::<i32>::default();
479
480            // Push a future that will set the flag to true when it resolves.
481            let (finisher, finished) = oneshot::channel();
482            pool.push(async move {
483                finished.await.unwrap();
484                flag_clone.store(true, Ordering::SeqCst);
485                42
486            });
487            assert_eq!(pool.len(), 1);
488
489            // Cancel all futures.
490            pool.cancel_all();
491            assert!(pool.is_empty());
492            assert!(!flag.load(Ordering::SeqCst));
493
494            // Send the finisher signal (should be ignored).
495            let _ = finisher.send(());
496
497            // Stream should not resolve future after cancellation.
498            let stream_future = pool.next_completed();
499            let timeout_future = async {
500                delay(Duration::from_millis(100)).await;
501            };
502            pin_mut!(stream_future);
503            pin_mut!(timeout_future);
504            let result = select(stream_future, timeout_future).await;
505            match result {
506                Either::Left((_, _)) => panic!("Stream resolved after cancellation"),
507                Either::Right((_, _)) => {
508                    // Wait for the timeout to trigger.
509                }
510            }
511            assert!(!flag.load(Ordering::SeqCst));
512
513            // Push and await a new future.
514            pool.push(future::ready(42));
515            assert_eq!(pool.len(), 1);
516            let result = pool.next_completed().await;
517            assert_eq!(result, 42);
518            assert!(pool.is_empty());
519        });
520    }
521
522    #[test]
523    fn test_many_futures() {
524        block_on(async move {
525            let mut pool = Pool::<i32>::default();
526            let num_futures = 1000;
527            for i in 0..num_futures {
528                pool.push(future::ready(i));
529            }
530            assert_eq!(pool.len(), num_futures as usize);
531
532            let mut sum = 0;
533            for _ in 0..num_futures {
534                let value = pool.next_completed().await;
535                sum += value;
536            }
537            let expected_sum = (0..num_futures).sum::<i32>();
538            assert_eq!(
539                sum, expected_sum,
540                "Sum of resolved values should match expected"
541            );
542            assert!(
543                pool.is_empty(),
544                "Pool should be empty after all futures resolve"
545            );
546        });
547    }
548
549    #[test]
550    fn test_borrowing_futures() {
551        block_on(async {
552            let values = vec![1, 2, 3];
553
554            // The pool borrows `values`, so it cannot outlive it.
555            let mut pool = Pool::<&i32>::default();
556            for value in &values {
557                pool.push(async move { value });
558            }
559            assert_eq!(pool.len(), values.len());
560
561            let mut sum = 0;
562            for _ in 0..values.len() {
563                sum += *pool.next_completed().await;
564            }
565            assert_eq!(sum, 6);
566            assert!(pool.is_empty());
567        });
568    }
569
570    #[test]
571    fn test_abortable_pool_initialization() {
572        let pool = AbortablePool::<i32>::default();
573        assert_eq!(pool.len(), 0);
574        assert!(pool.is_empty());
575    }
576
577    #[test]
578    fn test_abortable_pool_adding_futures() {
579        let mut pool = AbortablePool::<i32>::default();
580        assert_eq!(pool.len(), 0);
581        assert!(pool.is_empty());
582
583        let _hook1 = pool.push(async { 42 });
584        assert_eq!(pool.len(), 1);
585        assert!(!pool.is_empty());
586
587        let _hook2 = pool.push(async { 43 });
588        assert_eq!(pool.len(), 2);
589    }
590
591    #[test]
592    fn test_abortable_pool_successful_completion() {
593        block_on(async move {
594            let mut pool = AbortablePool::<i32>::default();
595            let _hook = pool.push(future::ready(42));
596            let result = pool.next_completed().await;
597            assert_eq!(result, Ok(42));
598            assert!(pool.is_empty());
599        });
600    }
601
602    #[test]
603    fn test_abortable_pool_aborts_pre_polled_ready_future() {
604        block_on(async move {
605            let mut pool = AbortablePool::<i32>::default();
606            let hook = pool.push(future::ready(42));
607            drop(hook);
608            let result = pool.next_completed().await;
609            assert!(result.is_err());
610        });
611    }
612
613    #[test]
614    fn test_abortable_pool_drop_abort() {
615        block_on(async move {
616            let mut pool = AbortablePool::<i32>::default();
617
618            let (sender, receiver) = oneshot::channel();
619            let hook = pool.push(async move {
620                receiver.await.unwrap();
621                42
622            });
623
624            drop(hook);
625
626            let result = pool.next_completed().await;
627            assert!(result.is_err());
628            assert!(pool.is_empty());
629
630            let _ = sender.send(());
631        });
632    }
633
634    #[test]
635    fn test_abortable_pool_partial_abort() {
636        block_on(async move {
637            let mut pool = AbortablePool::<i32>::default();
638
639            let _hook1 = pool.push(future::ready(1));
640            let (sender, receiver) = oneshot::channel();
641            let hook2 = pool.push(async move {
642                receiver.await.unwrap();
643                2
644            });
645            let _hook3 = pool.push(future::ready(3));
646
647            assert_eq!(pool.len(), 3);
648
649            drop(hook2);
650
651            let mut results = Vec::new();
652            for _ in 0..3 {
653                let result = pool.next_completed().await;
654                results.push(result);
655            }
656
657            let successful: Vec<_> = results.iter().filter_map(|r| r.as_ref().ok()).collect();
658            let aborted: Vec<_> = results.iter().filter(|r| r.is_err()).collect();
659
660            assert_eq!(successful.len(), 2);
661            assert_eq!(aborted.len(), 1);
662            assert!(successful.contains(&&1));
663            assert!(successful.contains(&&3));
664            assert!(pool.is_empty());
665
666            let _ = sender.send(());
667        });
668    }
669
670    #[test]
671    fn test_abortable_pool_borrowing_futures() {
672        block_on(async {
673            let value = 42;
674            let mut pool = AbortablePool::<&i32>::default();
675
676            // A borrowing future is aborted by its aborter, which holds no borrow itself.
677            let (sender, receiver) = oneshot::channel::<()>();
678            let hook = pool.push(async {
679                receiver.await.unwrap();
680                &value
681            });
682            drop(hook);
683            assert!(pool.next_completed().await.is_err());
684
685            let _hook = pool.push(async { &value });
686            assert_eq!(pool.next_completed().await, Ok(&42));
687            assert!(pool.is_empty());
688
689            let _ = sender.send(());
690        });
691    }
692
693    #[test]
694    fn test_rebind_restores_value_and_yields_rest() {
695        block_on(async {
696            let mut slot = Some(1u32);
697            let rest: Result<(&str, bool), &str> = rebind(&mut slot, |value| {
698                future::ready(Ok((value + 1, "rest", true)))
699            })
700            .await;
701            assert_eq!(rest, Ok(("rest", true)));
702            assert_eq!(slot, Some(2));
703
704            let rest: Result<(), &str> =
705                rebind(&mut slot, |value| future::ready(Ok(value + 1))).await;
706            assert_eq!(rest, Ok(()));
707            assert_eq!(slot, Some(3));
708        });
709    }
710
711    #[test]
712    fn test_rebind_error_destroys_value() {
713        block_on(async {
714            let mut slot = Some(1u32);
715            let rest: Result<(), &str> =
716                rebind(&mut slot, |_| future::ready(Err::<u32, _>("failed"))).await;
717            assert_eq!(rest, Err("failed"));
718            assert_eq!(slot, None);
719        });
720    }
721
722    #[test]
723    #[should_panic(expected = "cannot rebind an empty slot")]
724    fn test_rebind_empty_slot_panics() {
725        block_on(async {
726            let mut slot: Option<u32> = None;
727            let _: Result<(), &str> = rebind(&mut slot, |v| future::ready(Ok(v))).await;
728        });
729    }
730
731    #[test]
732    fn test_rebind_entry_restores_value_and_yields_rest() {
733        block_on(async {
734            let mut map = BTreeMap::from([("a", 1u32), ("b", 10)]);
735            let rest: Result<bool, &str> =
736                rebind_entry(&mut map, &"a", |value| future::ready(Ok((value + 1, true)))).await;
737            assert_eq!(rest, Ok(true));
738            assert_eq!(map, BTreeMap::from([("a", 2), ("b", 10)]));
739        });
740    }
741
742    #[test]
743    fn test_rebind_entry_error_destroys_value() {
744        block_on(async {
745            let mut map = BTreeMap::from([("a", 1u32)]);
746            let rest: Result<(), &str> =
747                rebind_entry(&mut map, &"a", |_| future::ready(Err::<u32, _>("failed"))).await;
748            assert_eq!(rest, Err("failed"));
749            assert!(map.is_empty());
750        });
751    }
752
753    #[test]
754    #[should_panic(expected = "cannot rebind a missing entry")]
755    fn test_rebind_entry_missing_entry_panics() {
756        block_on(async {
757            let mut map: BTreeMap<&str, u32> = BTreeMap::new();
758            let _: Result<(), &str> = rebind_entry(&mut map, &"a", |v| future::ready(Ok(v))).await;
759        });
760    }
761
762    #[test]
763    fn test_option_future() {
764        block_on(async {
765            let option_future = OptionFuture::<oneshot::Receiver<()>>::from(None);
766            pin_mut!(option_future);
767
768            let waker = futures::task::noop_waker();
769            let mut cx = std::task::Context::from_waker(&waker);
770            assert!(option_future.poll(&mut cx).is_pending());
771
772            let (tx, rx) = oneshot::channel();
773            let option_future: OptionFuture<_> = Some(rx).into();
774            pin_mut!(option_future);
775
776            tx.send(1usize).unwrap();
777            assert_eq!(option_future.poll(&mut cx), Poll::Ready(Ok(1)));
778        });
779    }
780}