use futures_core::FusedStream; use tokio_stream::{Stream, StreamExt}; use std::pin::Pin; use std::task::{Context, Poll}; // a stream which alternates between Some and None struct Alternate { state: i32, } impl Stream for Alternate { type Item = i32; fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { let val = self.state; self.state += 1; // if it's even, Some(i32), else None if val % 2 == 0 { Poll::Ready(Some(val)) } else { Poll::Ready(None) } } } #[tokio::test] async fn basic_usage() { let mut stream = Alternate { state: 0 }; // the stream goes back and forth assert_eq!(stream.next().await, Some(0)); assert_eq!(stream.next().await, None); assert_eq!(stream.next().await, Some(2)); assert_eq!(stream.next().await, None); // however, once it is fused let mut stream = stream.fuse(); assert!(!stream.is_terminated()); assert_eq!(stream.size_hint(), (0, None)); assert_eq!(stream.next().await, Some(4)); assert!(!stream.is_terminated()); assert_eq!(stream.size_hint(), (0, None)); assert_eq!(stream.next().await, None); assert!(stream.is_terminated()); // it will always return `None` after the first time. assert_eq!(stream.size_hint(), (0, Some(0))); assert_eq!(stream.next().await, None); assert_eq!(stream.size_hint(), (0, Some(0))); assert!(stream.is_terminated()); } #[tokio::test] #[cfg(feature = "time")] async fn interval_stream_is_never_terminated() { use futures_core::stream::FusedStream; use tokio_stream::wrappers::IntervalStream; let interval = tokio::time::interval(std::time::Duration::from_millis(1)); let stream = IntervalStream::new(interval); assert!(!stream.is_terminated()); }