1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
//! Extension trait to simplify optionally polling futures. use pin_project_lite::pin_project; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; /// Construct a fusing adapter that is capable of polling an interior future. /// /// Once the future completes, the adapter will switch to an empty state and /// return [Poll::Pending] until [set][Once::set] again. /// /// # Examples /// /// ```rust /// use std::time::Duration; /// use tokio::time; /// /// # #[tokio::main] /// # async fn main() { /// let mut sleep = async_fuse::once(time::sleep(Duration::from_millis(200))); /// tokio::pin!(sleep); /// /// tokio::select! { /// _ = &mut sleep => { /// assert!(sleep.is_empty()); /// sleep.set(async_fuse::once(time::sleep(Duration::from_millis(200)))); /// } /// } /// /// assert!(!sleep.is_empty()); /// # } /// ``` pub fn once<T>(value: T) -> Once<T> where T: Future, { Once { value: Some(value) } } pin_project! { /// Fusing adapter that is capable of polling an interior value that is /// being fused using a custom polling function. /// /// See [once] for details. pub struct Once<T> { #[pin] value: Option<T>, } } impl<T> Future for Once<T> where T: Future, { type Output = T::Output; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { let inner = match self.as_mut().project().value.as_pin_mut() { Some(inner) => inner, None => return Poll::Pending, }; let value = match inner.poll(cx) { Poll::Ready(value) => value, Poll::Pending => return Poll::Pending, }; self.as_mut().project().value.set(None); Poll::Ready(value) } } impl<T> Once<T> { /// Construct an empty value that can never complete. pub fn empty() -> Once<T> { Once { value: None } } /// Test if the polled for value is empty. /// /// # Examples /// /// ```rust /// use tokio::time; /// use std::time::Duration; /// /// # #[tokio::main] /// # async fn main() { /// let mut sleep = async_fuse::once(time::sleep(Duration::from_millis(200))); /// tokio::pin!(sleep); /// /// assert!(!sleep.is_empty()); /// sleep.set(async_fuse::Once::empty()); /// assert!(sleep.is_empty()); /// # } /// ``` pub fn is_empty(&self) -> bool { self.value.is_none() } }