tokio-stream-0.1.8/.cargo_vcs_info.json0000644000000001120000000000100134520ustar { "git": { "sha1": "d1a400912e82505c18c6c0c1f05cda06f334e201" } } tokio-stream-0.1.8/CHANGELOG.md000064400000000000000000000040330072674642500141110ustar 00000000000000# 0.1.8 (October 29, 2021) - stream: add `From>` impl for receiver streams ([#4080]) - stream: impl `FromIterator` for `StreamMap` ([#4052]) - signal: make windows docs for signal module show up on unix builds ([#3770]) [#3770]: https://github.com/tokio-rs/tokio/pull/3770 [#4052]: https://github.com/tokio-rs/tokio/pull/4052 [#4080]: https://github.com/tokio-rs/tokio/pull/4080 # 0.1.7 (July 7, 2021) ### Fixed - sync: fix watch wrapper ([#3914]) - time: fix `Timeout::size_hint` ([#3902]) [#3902]: https://github.com/tokio-rs/tokio/pull/3902 [#3914]: https://github.com/tokio-rs/tokio/pull/3914 # 0.1.6 (May 14, 2021) ### Added - stream: implement `Error` and `Display` for `BroadcastStreamRecvError` ([#3745]) ### Fixed - stream: avoid yielding in `AllFuture` and `AnyFuture` ([#3625]) [#3745]: https://github.com/tokio-rs/tokio/pull/3745 [#3625]: https://github.com/tokio-rs/tokio/pull/3625 # 0.1.5 (March 20, 2021) ### Fixed - stream: documentation note for throttle `Unpin` ([#3600]) [#3600]: https://github.com/tokio-rs/tokio/pull/3600 # 0.1.4 (March 9, 2021) Added - signal: add `Signal` wrapper ([#3510]) Fixed - stream: remove duplicate `doc_cfg` declaration ([#3561]) - sync: yield initial value in `WatchStream` ([#3576]) [#3510]: https://github.com/tokio-rs/tokio/pull/3510 [#3561]: https://github.com/tokio-rs/tokio/pull/3561 [#3576]: https://github.com/tokio-rs/tokio/pull/3576 # 0.1.3 (February 5, 2021) Added - sync: add wrapper for broadcast and watch ([#3384], [#3504]) [#3384]: https://github.com/tokio-rs/tokio/pull/3384 [#3504]: https://github.com/tokio-rs/tokio/pull/3504 # 0.1.2 (January 12, 2021) Fixed - docs: fix some wrappers missing in documentation ([#3378]) [#3378]: https://github.com/tokio-rs/tokio/pull/3378 # 0.1.1 (January 4, 2021) Added - add `Stream` wrappers ([#3343]) Fixed - move `async-stream` to `dev-dependencies` ([#3366]) [#3366]: https://github.com/tokio-rs/tokio/pull/3366 [#3343]: https://github.com/tokio-rs/tokio/pull/3343 # 0.1.0 (December 23, 2020) - Initial release tokio-stream-0.1.8/Cargo.toml0000644000000030640000000000100114610ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "tokio-stream" version = "0.1.8" authors = ["Tokio Contributors "] description = "Utilities to work with `Stream` and `tokio`.\n" homepage = "https://tokio.rs" documentation = "https://docs.rs/tokio-stream/0.1.8/tokio_stream" categories = ["asynchronous"] license = "MIT" repository = "https://github.com/tokio-rs/tokio" [package.metadata.docs.rs] all-features = true rustc-args = ["--cfg", "docsrs"] rustdoc-args = ["--cfg", "docsrs"] [dependencies.futures-core] version = "0.3.0" [dependencies.pin-project-lite] version = "0.2.0" [dependencies.tokio] version = "1.8.0" features = ["sync"] [dependencies.tokio-util] version = "0.6.3" optional = true [dev-dependencies.async-stream] version = "0.3" [dev-dependencies.futures] version = "0.3" default-features = false [dev-dependencies.proptest] version = "1" [dev-dependencies.tokio] version = "1.2.0" features = ["full", "test-util"] [features] default = ["time"] fs = ["tokio/fs"] io-util = ["tokio/io-util"] net = ["tokio/net"] signal = ["tokio/signal"] sync = ["tokio/sync", "tokio-util"] time = ["tokio/time"] tokio-stream-0.1.8/Cargo.toml.orig000064400000000000000000000026400072674642500151710ustar 00000000000000[package] name = "tokio-stream" # When releasing to crates.io: # - Remove path dependencies # - Update doc url # - Cargo.toml # - Update CHANGELOG.md. # - Create "tokio-stream-0.1.x" git tag. version = "0.1.8" edition = "2018" authors = ["Tokio Contributors "] license = "MIT" repository = "https://github.com/tokio-rs/tokio" homepage = "https://tokio.rs" documentation = "https://docs.rs/tokio-stream/0.1.8/tokio_stream" description = """ Utilities to work with `Stream` and `tokio`. """ categories = ["asynchronous"] [features] default = ["time"] time = ["tokio/time"] net = ["tokio/net"] io-util = ["tokio/io-util"] fs = ["tokio/fs"] sync = ["tokio/sync", "tokio-util"] signal = ["tokio/signal"] [dependencies] futures-core = { version = "0.3.0" } pin-project-lite = "0.2.0" tokio = { version = "1.8.0", path = "../tokio", features = ["sync"] } tokio-util = { version = "0.6.3", path = "../tokio-util", optional = true } [dev-dependencies] tokio = { version = "1.2.0", path = "../tokio", features = ["full", "test-util"] } async-stream = "0.3" tokio-test = { path = "../tokio-test" } futures = { version = "0.3", default-features = false } proptest = "1" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] # Issue #3770 # # This should allow `docsrs` to be read across projects, so that `tokio-stream` # can pick up stubbed types exported by `tokio`. rustc-args = ["--cfg", "docsrs"] tokio-stream-0.1.8/LICENSE000064400000000000000000000020460072674642500133070ustar 00000000000000Copyright (c) 2021 Tokio Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tokio-stream-0.1.8/src/empty.rs000064400000000000000000000021530072674642500145740ustar 00000000000000use crate::Stream; use core::marker::PhantomData; use core::pin::Pin; use core::task::{Context, Poll}; /// Stream for the [`empty`](fn@empty) function. #[derive(Debug)] #[must_use = "streams do nothing unless polled"] pub struct Empty(PhantomData); impl Unpin for Empty {} unsafe impl Send for Empty {} unsafe impl Sync for Empty {} /// Creates a stream that yields nothing. /// /// The returned stream is immediately ready and returns `None`. Use /// [`stream::pending()`](super::pending()) to obtain a stream that is never /// ready. /// /// # Examples /// /// Basic usage: /// /// ``` /// use tokio_stream::{self as stream, StreamExt}; /// /// #[tokio::main] /// async fn main() { /// let mut none = stream::empty::(); /// /// assert_eq!(None, none.next().await); /// } /// ``` pub const fn empty() -> Empty { Empty(PhantomData) } impl Stream for Empty { type Item = T; fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(None) } fn size_hint(&self) -> (usize, Option) { (0, Some(0)) } } tokio-stream-0.1.8/src/iter.rs000064400000000000000000000027030072674642500144020ustar 00000000000000use crate::Stream; use core::pin::Pin; use core::task::{Context, Poll}; /// Stream for the [`iter`](fn@iter) function. #[derive(Debug)] #[must_use = "streams do nothing unless polled"] pub struct Iter { iter: I, yield_amt: usize, } impl Unpin for Iter {} /// Converts an `Iterator` into a `Stream` which is always ready /// to yield the next value. /// /// Iterators in Rust don't express the ability to block, so this adapter /// simply always calls `iter.next()` and returns that. /// /// ``` /// # async fn dox() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let mut stream = stream::iter(vec![17, 19]); /// /// assert_eq!(stream.next().await, Some(17)); /// assert_eq!(stream.next().await, Some(19)); /// assert_eq!(stream.next().await, None); /// # } /// ``` pub fn iter(i: I) -> Iter where I: IntoIterator, { Iter { iter: i.into_iter(), yield_amt: 0, } } impl Stream for Iter where I: Iterator, { type Item = I::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { // TODO: add coop back if self.yield_amt >= 32 { self.yield_amt = 0; cx.waker().wake_by_ref(); Poll::Pending } else { self.yield_amt += 1; Poll::Ready(self.iter.next()) } } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } tokio-stream-0.1.8/src/lib.rs000064400000000000000000000062370072674642500142130ustar 00000000000000#![allow( clippy::cognitive_complexity, clippy::large_enum_variant, clippy::needless_doctest_main )] #![warn( missing_debug_implementations, missing_docs, rust_2018_idioms, unreachable_pub )] #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] #![doc(test( no_crate_inject, attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) ))] //! Stream utilities for Tokio. //! //! A `Stream` is an asynchronous sequence of values. It can be thought of as //! an asynchronous version of the standard library's `Iterator` trait. //! //! This crate provides helpers to work with them. For examples of usage and a more in-depth //! description of streams you can also refer to the [streams //! tutorial](https://tokio.rs/tokio/tutorial/streams) on the tokio website. //! //! # Iterating over a Stream //! //! Due to similarities with the standard library's `Iterator` trait, some new //! users may assume that they can use `for in` syntax to iterate over a //! `Stream`, but this is unfortunately not possible. Instead, you can use a //! `while let` loop as follows: //! //! ```rust //! use tokio_stream::{self as stream, StreamExt}; //! //! #[tokio::main] //! async fn main() { //! let mut stream = stream::iter(vec![0, 1, 2]); //! //! while let Some(value) = stream.next().await { //! println!("Got {}", value); //! } //! } //! ``` //! //! # Returning a Stream from a function //! //! A common way to stream values from a function is to pass in the sender //! half of a channel and use the receiver as the stream. This requires awaiting //! both futures to ensure progress is made. Another alternative is the //! [async-stream] crate, which contains macros that provide a `yield` keyword //! and allow you to return an `impl Stream`. //! //! [async-stream]: https://docs.rs/async-stream //! //! # Conversion to and from AsyncRead/AsyncWrite //! //! It is often desirable to convert a `Stream` into an [`AsyncRead`], //! especially when dealing with plaintext formats streamed over the network. //! The opposite conversion from an [`AsyncRead`] into a `Stream` is also //! another commonly required feature. To enable these conversions, //! [`tokio-util`] provides the [`StreamReader`] and [`ReaderStream`] //! types when the io feature is enabled. //! //! [`tokio-util`]: https://docs.rs/tokio-util/0.4/tokio_util/codec/index.html //! [`tokio::io`]: https://docs.rs/tokio/1.0/tokio/io/index.html //! [`AsyncRead`]: https://docs.rs/tokio/1.0/tokio/io/trait.AsyncRead.html //! [`AsyncWrite`]: https://docs.rs/tokio/1.0/tokio/io/trait.AsyncWrite.html //! [`ReaderStream`]: https://docs.rs/tokio-util/0.4/tokio_util/io/struct.ReaderStream.html //! [`StreamReader`]: https://docs.rs/tokio-util/0.4/tokio_util/io/struct.StreamReader.html #[macro_use] mod macros; pub mod wrappers; mod stream_ext; pub use stream_ext::{collect::FromStream, StreamExt}; mod empty; pub use empty::{empty, Empty}; mod iter; pub use iter::{iter, Iter}; mod once; pub use once::{once, Once}; mod pending; pub use pending::{pending, Pending}; mod stream_map; pub use stream_map::StreamMap; #[doc(no_inline)] pub use futures_core::Stream; tokio-stream-0.1.8/src/macros.rs000064400000000000000000000025470072674642500147310ustar 00000000000000macro_rules! cfg_fs { ($($item:item)*) => { $( #[cfg(feature = "fs")] #[cfg_attr(docsrs, doc(cfg(feature = "fs")))] $item )* } } macro_rules! cfg_io_util { ($($item:item)*) => { $( #[cfg(feature = "io-util")] #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] $item )* } } macro_rules! cfg_net { ($($item:item)*) => { $( #[cfg(feature = "net")] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] $item )* } } macro_rules! cfg_time { ($($item:item)*) => { $( #[cfg(feature = "time")] #[cfg_attr(docsrs, doc(cfg(feature = "time")))] $item )* } } macro_rules! cfg_sync { ($($item:item)*) => { $( #[cfg(feature = "sync")] #[cfg_attr(docsrs, doc(cfg(feature = "sync")))] $item )* } } macro_rules! cfg_signal { ($($item:item)*) => { $( #[cfg(feature = "signal")] #[cfg_attr(docsrs, doc(cfg(feature = "signal")))] $item )* } } macro_rules! ready { ($e:expr $(,)?) => { match $e { std::task::Poll::Ready(t) => t, std::task::Poll::Pending => return std::task::Poll::Pending, } }; } tokio-stream-0.1.8/src/once.rs000064400000000000000000000022470072674642500143660ustar 00000000000000use crate::{Iter, Stream}; use core::option; use core::pin::Pin; use core::task::{Context, Poll}; /// Stream for the [`once`](fn@once) function. #[derive(Debug)] #[must_use = "streams do nothing unless polled"] pub struct Once { iter: Iter>, } impl Unpin for Once {} /// Creates a stream that emits an element exactly once. /// /// The returned stream is immediately ready and emits the provided value once. /// /// # Examples /// /// ``` /// use tokio_stream::{self as stream, StreamExt}; /// /// #[tokio::main] /// async fn main() { /// // one is the loneliest number /// let mut one = stream::once(1); /// /// assert_eq!(Some(1), one.next().await); /// /// // just one, that's all we get /// assert_eq!(None, one.next().await); /// } /// ``` pub fn once(value: T) -> Once { Once { iter: crate::iter(Some(value).into_iter()), } } impl Stream for Once { type Item = T; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut self.iter).poll_next(cx) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } tokio-stream-0.1.8/src/pending.rs000064400000000000000000000024000072674642500150550ustar 00000000000000use crate::Stream; use core::marker::PhantomData; use core::pin::Pin; use core::task::{Context, Poll}; /// Stream for the [`pending`](fn@pending) function. #[derive(Debug)] #[must_use = "streams do nothing unless polled"] pub struct Pending(PhantomData); impl Unpin for Pending {} unsafe impl Send for Pending {} unsafe impl Sync for Pending {} /// Creates a stream that is never ready /// /// The returned stream is never ready. Attempting to call /// [`next()`](crate::StreamExt::next) will never complete. Use /// [`stream::empty()`](super::empty()) to obtain a stream that is is /// immediately empty but returns no values. /// /// # Examples /// /// Basic usage: /// /// ```no_run /// use tokio_stream::{self as stream, StreamExt}; /// /// #[tokio::main] /// async fn main() { /// let mut never = stream::pending::(); /// /// // This will never complete /// never.next().await; /// /// unreachable!(); /// } /// ``` pub const fn pending() -> Pending { Pending(PhantomData) } impl Stream for Pending { type Item = T; fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Pending } fn size_hint(&self) -> (usize, Option) { (0, None) } } tokio-stream-0.1.8/src/stream_ext/all.rs000064400000000000000000000027740072674642500163720ustar 00000000000000use crate::Stream; use core::future::Future; use core::marker::PhantomPinned; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Future for the [`all`](super::StreamExt::all) method. #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct AllFuture<'a, St: ?Sized, F> { stream: &'a mut St, f: F, // Make this future `!Unpin` for compatibility with async trait methods. #[pin] _pin: PhantomPinned, } } impl<'a, St: ?Sized, F> AllFuture<'a, St, F> { pub(super) fn new(stream: &'a mut St, f: F) -> Self { Self { stream, f, _pin: PhantomPinned, } } } impl Future for AllFuture<'_, St, F> where St: ?Sized + Stream + Unpin, F: FnMut(St::Item) -> bool, { type Output = bool; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let me = self.project(); let mut stream = Pin::new(me.stream); // Take a maximum of 32 items from the stream before yielding. for _ in 0..32 { match futures_core::ready!(stream.as_mut().poll_next(cx)) { Some(v) => { if !(me.f)(v) { return Poll::Ready(false); } } None => return Poll::Ready(true), } } cx.waker().wake_by_ref(); Poll::Pending } } tokio-stream-0.1.8/src/stream_ext/any.rs000064400000000000000000000027730072674642500164100ustar 00000000000000use crate::Stream; use core::future::Future; use core::marker::PhantomPinned; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Future for the [`any`](super::StreamExt::any) method. #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct AnyFuture<'a, St: ?Sized, F> { stream: &'a mut St, f: F, // Make this future `!Unpin` for compatibility with async trait methods. #[pin] _pin: PhantomPinned, } } impl<'a, St: ?Sized, F> AnyFuture<'a, St, F> { pub(super) fn new(stream: &'a mut St, f: F) -> Self { Self { stream, f, _pin: PhantomPinned, } } } impl Future for AnyFuture<'_, St, F> where St: ?Sized + Stream + Unpin, F: FnMut(St::Item) -> bool, { type Output = bool; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let me = self.project(); let mut stream = Pin::new(me.stream); // Take a maximum of 32 items from the stream before yielding. for _ in 0..32 { match futures_core::ready!(stream.as_mut().poll_next(cx)) { Some(v) => { if (me.f)(v) { return Poll::Ready(true); } } None => return Poll::Ready(false), } } cx.waker().wake_by_ref(); Poll::Pending } } tokio-stream-0.1.8/src/stream_ext/chain.rs000064400000000000000000000020070072674642500166710ustar 00000000000000use crate::stream_ext::Fuse; use crate::Stream; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream returned by the [`chain`](super::StreamExt::chain) method. pub struct Chain { #[pin] a: Fuse, #[pin] b: U, } } impl Chain { pub(super) fn new(a: T, b: U) -> Chain where T: Stream, U: Stream, { Chain { a: Fuse::new(a), b } } } impl Stream for Chain where T: Stream, U: Stream, { type Item = T::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { use Poll::Ready; let me = self.project(); if let Some(v) = ready!(me.a.poll_next(cx)) { return Ready(Some(v)); } me.b.poll_next(cx) } fn size_hint(&self) -> (usize, Option) { super::merge_size_hints(self.a.size_hint(), self.b.size_hint()) } } tokio-stream-0.1.8/src/stream_ext/collect.rs000064400000000000000000000150520072674642500172400ustar 00000000000000use crate::Stream; use core::future::Future; use core::marker::PhantomPinned; use core::mem; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; // Do not export this struct until `FromStream` can be unsealed. pin_project! { /// Future returned by the [`collect`](super::StreamExt::collect) method. #[must_use = "futures do nothing unless you `.await` or poll them"] #[derive(Debug)] pub struct Collect where T: Stream, U: FromStream, { #[pin] stream: T, collection: U::InternalCollection, // Make this future `!Unpin` for compatibility with async trait methods. #[pin] _pin: PhantomPinned, } } /// Convert from a [`Stream`](crate::Stream). /// /// This trait is not intended to be used directly. Instead, call /// [`StreamExt::collect()`](super::StreamExt::collect). /// /// # Implementing /// /// Currently, this trait may not be implemented by third parties. The trait is /// sealed in order to make changes in the future. Stabilization is pending /// enhancements to the Rust language. pub trait FromStream: sealed::FromStreamPriv {} impl Collect where T: Stream, U: FromStream, { pub(super) fn new(stream: T) -> Collect { let (lower, upper) = stream.size_hint(); let collection = U::initialize(sealed::Internal, lower, upper); Collect { stream, collection, _pin: PhantomPinned, } } } impl Future for Collect where T: Stream, U: FromStream, { type Output = U; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { use Poll::Ready; loop { let mut me = self.as_mut().project(); let item = match ready!(me.stream.poll_next(cx)) { Some(item) => item, None => { return Ready(U::finalize(sealed::Internal, &mut me.collection)); } }; if !U::extend(sealed::Internal, &mut me.collection, item) { return Ready(U::finalize(sealed::Internal, &mut me.collection)); } } } } // ===== FromStream implementations impl FromStream<()> for () {} impl sealed::FromStreamPriv<()> for () { type InternalCollection = (); fn initialize(_: sealed::Internal, _lower: usize, _upper: Option) {} fn extend(_: sealed::Internal, _collection: &mut (), _item: ()) -> bool { true } fn finalize(_: sealed::Internal, _collection: &mut ()) {} } impl> FromStream for String {} impl> sealed::FromStreamPriv for String { type InternalCollection = String; fn initialize(_: sealed::Internal, _lower: usize, _upper: Option) -> String { String::new() } fn extend(_: sealed::Internal, collection: &mut String, item: T) -> bool { collection.push_str(item.as_ref()); true } fn finalize(_: sealed::Internal, collection: &mut String) -> String { mem::take(collection) } } impl FromStream for Vec {} impl sealed::FromStreamPriv for Vec { type InternalCollection = Vec; fn initialize(_: sealed::Internal, lower: usize, _upper: Option) -> Vec { Vec::with_capacity(lower) } fn extend(_: sealed::Internal, collection: &mut Vec, item: T) -> bool { collection.push(item); true } fn finalize(_: sealed::Internal, collection: &mut Vec) -> Vec { mem::take(collection) } } impl FromStream for Box<[T]> {} impl sealed::FromStreamPriv for Box<[T]> { type InternalCollection = Vec; fn initialize(_: sealed::Internal, lower: usize, upper: Option) -> Vec { as sealed::FromStreamPriv>::initialize(sealed::Internal, lower, upper) } fn extend(_: sealed::Internal, collection: &mut Vec, item: T) -> bool { as sealed::FromStreamPriv>::extend(sealed::Internal, collection, item) } fn finalize(_: sealed::Internal, collection: &mut Vec) -> Box<[T]> { as sealed::FromStreamPriv>::finalize(sealed::Internal, collection) .into_boxed_slice() } } impl FromStream> for Result where U: FromStream {} impl sealed::FromStreamPriv> for Result where U: FromStream, { type InternalCollection = Result; fn initialize( _: sealed::Internal, lower: usize, upper: Option, ) -> Result { Ok(U::initialize(sealed::Internal, lower, upper)) } fn extend( _: sealed::Internal, collection: &mut Self::InternalCollection, item: Result, ) -> bool { assert!(collection.is_ok()); match item { Ok(item) => { let collection = collection.as_mut().ok().expect("invalid state"); U::extend(sealed::Internal, collection, item) } Err(err) => { *collection = Err(err); false } } } fn finalize(_: sealed::Internal, collection: &mut Self::InternalCollection) -> Result { if let Ok(collection) = collection.as_mut() { Ok(U::finalize(sealed::Internal, collection)) } else { let res = mem::replace(collection, Ok(U::initialize(sealed::Internal, 0, Some(0)))); if let Err(err) = res { Err(err) } else { unreachable!(); } } } } pub(crate) mod sealed { #[doc(hidden)] pub trait FromStreamPriv { /// Intermediate type used during collection process /// /// The name of this type is internal and cannot be relied upon. type InternalCollection; /// Initialize the collection fn initialize( internal: Internal, lower: usize, upper: Option, ) -> Self::InternalCollection; /// Extend the collection with the received item /// /// Return `true` to continue streaming, `false` complete collection. fn extend(internal: Internal, collection: &mut Self::InternalCollection, item: T) -> bool; /// Finalize collection into target type. fn finalize(internal: Internal, collection: &mut Self::InternalCollection) -> Self; } #[allow(missing_debug_implementations)] pub struct Internal; } tokio-stream-0.1.8/src/stream_ext/filter.rs000064400000000000000000000026150072674642500171010ustar 00000000000000use crate::Stream; use core::fmt; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream returned by the [`filter`](super::StreamExt::filter) method. #[must_use = "streams do nothing unless polled"] pub struct Filter { #[pin] stream: St, f: F, } } impl fmt::Debug for Filter where St: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Filter") .field("stream", &self.stream) .finish() } } impl Filter { pub(super) fn new(stream: St, f: F) -> Self { Self { stream, f } } } impl Stream for Filter where St: Stream, F: FnMut(&St::Item) -> bool, { type Item = St::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { loop { match ready!(self.as_mut().project().stream.poll_next(cx)) { Some(e) => { if (self.as_mut().project().f)(&e) { return Poll::Ready(Some(e)); } } None => return Poll::Ready(None), } } } fn size_hint(&self) -> (usize, Option) { (0, self.stream.size_hint().1) // can't know a lower bound, due to the predicate } } tokio-stream-0.1.8/src/stream_ext/filter_map.rs000064400000000000000000000026520072674642500177370ustar 00000000000000use crate::Stream; use core::fmt; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream returned by the [`filter_map`](super::StreamExt::filter_map) method. #[must_use = "streams do nothing unless polled"] pub struct FilterMap { #[pin] stream: St, f: F, } } impl fmt::Debug for FilterMap where St: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FilterMap") .field("stream", &self.stream) .finish() } } impl FilterMap { pub(super) fn new(stream: St, f: F) -> Self { Self { stream, f } } } impl Stream for FilterMap where St: Stream, F: FnMut(St::Item) -> Option, { type Item = T; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { loop { match ready!(self.as_mut().project().stream.poll_next(cx)) { Some(e) => { if let Some(e) = (self.as_mut().project().f)(e) { return Poll::Ready(Some(e)); } } None => return Poll::Ready(None), } } } fn size_hint(&self) -> (usize, Option) { (0, self.stream.size_hint().1) // can't know a lower bound, due to the predicate } } tokio-stream-0.1.8/src/stream_ext/fold.rs000064400000000000000000000026610072674642500165410ustar 00000000000000use crate::Stream; use core::future::Future; use core::marker::PhantomPinned; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Future returned by the [`fold`](super::StreamExt::fold) method. #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct FoldFuture { #[pin] stream: St, acc: Option, f: F, // Make this future `!Unpin` for compatibility with async trait methods. #[pin] _pin: PhantomPinned, } } impl FoldFuture { pub(super) fn new(stream: St, init: B, f: F) -> Self { Self { stream, acc: Some(init), f, _pin: PhantomPinned, } } } impl Future for FoldFuture where St: Stream, F: FnMut(B, St::Item) -> B, { type Output = B; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut me = self.project(); loop { let next = ready!(me.stream.as_mut().poll_next(cx)); match next { Some(v) => { let old = me.acc.take().unwrap(); let new = (me.f)(old, v); *me.acc = Some(new); } None => return Poll::Ready(me.acc.take().unwrap()), } } } } tokio-stream-0.1.8/src/stream_ext/fuse.rs000064400000000000000000000021760072674642500165600ustar 00000000000000use crate::Stream; use pin_project_lite::pin_project; use std::pin::Pin; use std::task::{Context, Poll}; pin_project! { /// Stream returned by [`fuse()`][super::StreamExt::fuse]. #[derive(Debug)] pub struct Fuse { #[pin] stream: Option, } } impl Fuse where T: Stream, { pub(crate) fn new(stream: T) -> Fuse { Fuse { stream: Some(stream), } } } impl Stream for Fuse where T: Stream, { type Item = T::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let res = match Option::as_pin_mut(self.as_mut().project().stream) { Some(stream) => ready!(stream.poll_next(cx)), None => return Poll::Ready(None), }; if res.is_none() { // Do not poll the stream anymore self.as_mut().project().stream.set(None); } Poll::Ready(res) } fn size_hint(&self) -> (usize, Option) { match self.stream { Some(ref stream) => stream.size_hint(), None => (0, Some(0)), } } } tokio-stream-0.1.8/src/stream_ext/map.rs000064400000000000000000000021300072674642500163610ustar 00000000000000use crate::Stream; use core::fmt; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream for the [`map`](super::StreamExt::map) method. #[must_use = "streams do nothing unless polled"] pub struct Map { #[pin] stream: St, f: F, } } impl fmt::Debug for Map where St: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Map").field("stream", &self.stream).finish() } } impl Map { pub(super) fn new(stream: St, f: F) -> Self { Map { stream, f } } } impl Stream for Map where St: Stream, F: FnMut(St::Item) -> T, { type Item = T; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.as_mut() .project() .stream .poll_next(cx) .map(|opt| opt.map(|x| (self.as_mut().project().f)(x))) } fn size_hint(&self) -> (usize, Option) { self.stream.size_hint() } } tokio-stream-0.1.8/src/stream_ext/merge.rs000064400000000000000000000035010072674642500167060ustar 00000000000000use crate::stream_ext::Fuse; use crate::Stream; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream returned by the [`merge`](super::StreamExt::merge) method. pub struct Merge { #[pin] a: Fuse, #[pin] b: Fuse, // When `true`, poll `a` first, otherwise, `poll` b`. a_first: bool, } } impl Merge { pub(super) fn new(a: T, b: U) -> Merge where T: Stream, U: Stream, { Merge { a: Fuse::new(a), b: Fuse::new(b), a_first: true, } } } impl Stream for Merge where T: Stream, U: Stream, { type Item = T::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let me = self.project(); let a_first = *me.a_first; // Toggle the flag *me.a_first = !a_first; if a_first { poll_next(me.a, me.b, cx) } else { poll_next(me.b, me.a, cx) } } fn size_hint(&self) -> (usize, Option) { super::merge_size_hints(self.a.size_hint(), self.b.size_hint()) } } fn poll_next( first: Pin<&mut T>, second: Pin<&mut U>, cx: &mut Context<'_>, ) -> Poll> where T: Stream, U: Stream, { use Poll::*; let mut done = true; match first.poll_next(cx) { Ready(Some(val)) => return Ready(Some(val)), Ready(None) => {} Pending => done = false, } match second.poll_next(cx) { Ready(Some(val)) => return Ready(Some(val)), Ready(None) => {} Pending => done = false, } if done { Ready(None) } else { Pending } } tokio-stream-0.1.8/src/stream_ext/next.rs000064400000000000000000000017170072674642500165740ustar 00000000000000use crate::Stream; use core::future::Future; use core::marker::PhantomPinned; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Future for the [`next`](super::StreamExt::next) method. #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct Next<'a, St: ?Sized> { stream: &'a mut St, // Make this future `!Unpin` for compatibility with async trait methods. #[pin] _pin: PhantomPinned, } } impl<'a, St: ?Sized> Next<'a, St> { pub(super) fn new(stream: &'a mut St) -> Self { Next { stream, _pin: PhantomPinned, } } } impl Future for Next<'_, St> { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let me = self.project(); Pin::new(me.stream).poll_next(cx) } } tokio-stream-0.1.8/src/stream_ext/skip.rs000064400000000000000000000030110072674642500165510ustar 00000000000000use crate::Stream; use core::fmt; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream for the [`skip`](super::StreamExt::skip) method. #[must_use = "streams do nothing unless polled"] pub struct Skip { #[pin] stream: St, remaining: usize, } } impl fmt::Debug for Skip where St: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Skip") .field("stream", &self.stream) .finish() } } impl Skip { pub(super) fn new(stream: St, remaining: usize) -> Self { Self { stream, remaining } } } impl Stream for Skip where St: Stream, { type Item = St::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { loop { match ready!(self.as_mut().project().stream.poll_next(cx)) { Some(e) => { if self.remaining == 0 { return Poll::Ready(Some(e)); } *self.as_mut().project().remaining -= 1; } None => return Poll::Ready(None), } } } fn size_hint(&self) -> (usize, Option) { let (lower, upper) = self.stream.size_hint(); let lower = lower.saturating_sub(self.remaining); let upper = upper.map(|x| x.saturating_sub(self.remaining)); (lower, upper) } } tokio-stream-0.1.8/src/stream_ext/skip_while.rs000064400000000000000000000034270072674642500177540ustar 00000000000000use crate::Stream; use core::fmt; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream for the [`skip_while`](super::StreamExt::skip_while) method. #[must_use = "streams do nothing unless polled"] pub struct SkipWhile { #[pin] stream: St, predicate: Option, } } impl fmt::Debug for SkipWhile where St: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SkipWhile") .field("stream", &self.stream) .finish() } } impl SkipWhile { pub(super) fn new(stream: St, predicate: F) -> Self { Self { stream, predicate: Some(predicate), } } } impl Stream for SkipWhile where St: Stream, F: FnMut(&St::Item) -> bool, { type Item = St::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); if let Some(predicate) = this.predicate { loop { match ready!(this.stream.as_mut().poll_next(cx)) { Some(item) => { if !(predicate)(&item) { *this.predicate = None; return Poll::Ready(Some(item)); } } None => return Poll::Ready(None), } } } else { this.stream.poll_next(cx) } } fn size_hint(&self) -> (usize, Option) { let (lower, upper) = self.stream.size_hint(); if self.predicate.is_some() { return (0, upper); } (lower, upper) } } tokio-stream-0.1.8/src/stream_ext/take.rs000064400000000000000000000034610072674642500165400ustar 00000000000000use crate::Stream; use core::cmp; use core::fmt; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream for the [`take`](super::StreamExt::take) method. #[must_use = "streams do nothing unless polled"] pub struct Take { #[pin] stream: St, remaining: usize, } } impl fmt::Debug for Take where St: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Take") .field("stream", &self.stream) .finish() } } impl Take { pub(super) fn new(stream: St, remaining: usize) -> Self { Self { stream, remaining } } } impl Stream for Take where St: Stream, { type Item = St::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { if *self.as_mut().project().remaining > 0 { self.as_mut().project().stream.poll_next(cx).map(|ready| { match &ready { Some(_) => { *self.as_mut().project().remaining -= 1; } None => { *self.as_mut().project().remaining = 0; } } ready }) } else { Poll::Ready(None) } } fn size_hint(&self) -> (usize, Option) { if self.remaining == 0 { return (0, Some(0)); } let (lower, upper) = self.stream.size_hint(); let lower = cmp::min(lower, self.remaining as usize); let upper = match upper { Some(x) if x < self.remaining as usize => Some(x), _ => Some(self.remaining as usize), }; (lower, upper) } } tokio-stream-0.1.8/src/stream_ext/take_while.rs000064400000000000000000000035120072674642500177250ustar 00000000000000use crate::Stream; use core::fmt; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Stream for the [`take_while`](super::StreamExt::take_while) method. #[must_use = "streams do nothing unless polled"] pub struct TakeWhile { #[pin] stream: St, predicate: F, done: bool, } } impl fmt::Debug for TakeWhile where St: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("TakeWhile") .field("stream", &self.stream) .field("done", &self.done) .finish() } } impl TakeWhile { pub(super) fn new(stream: St, predicate: F) -> Self { Self { stream, predicate, done: false, } } } impl Stream for TakeWhile where St: Stream, F: FnMut(&St::Item) -> bool, { type Item = St::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { if !*self.as_mut().project().done { self.as_mut().project().stream.poll_next(cx).map(|ready| { let ready = ready.and_then(|item| { if !(self.as_mut().project().predicate)(&item) { None } else { Some(item) } }); if ready.is_none() { *self.as_mut().project().done = true; } ready }) } else { Poll::Ready(None) } } fn size_hint(&self) -> (usize, Option) { if self.done { return (0, Some(0)); } let (_, upper) = self.stream.size_hint(); (0, upper) } } tokio-stream-0.1.8/src/stream_ext/throttle.rs000064400000000000000000000051050072674642500174560ustar 00000000000000//! Slow down a stream by enforcing a delay between items. use crate::Stream; use tokio::time::{Duration, Instant, Sleep}; use std::future::Future; use std::marker::Unpin; use std::pin::Pin; use std::task::{self, Poll}; use pin_project_lite::pin_project; pub(super) fn throttle(duration: Duration, stream: T) -> Throttle where T: Stream, { Throttle { delay: tokio::time::sleep_until(Instant::now() + duration), duration, has_delayed: true, stream, } } pin_project! { /// Stream for the [`throttle`](throttle) function. This object is `!Unpin`. If you need it to /// implement `Unpin` you can pin your throttle like this: `Box::pin(your_throttle)`. #[derive(Debug)] #[must_use = "streams do nothing unless polled"] pub struct Throttle { #[pin] delay: Sleep, duration: Duration, // Set to true when `delay` has returned ready, but `stream` hasn't. has_delayed: bool, // The stream to throttle #[pin] stream: T, } } // XXX: are these safe if `T: !Unpin`? impl Throttle { /// Acquires a reference to the underlying stream that this combinator is /// pulling from. pub fn get_ref(&self) -> &T { &self.stream } /// Acquires a mutable reference to the underlying stream that this combinator /// is pulling from. /// /// Note that care must be taken to avoid tampering with the state of the stream /// which may otherwise confuse this combinator. pub fn get_mut(&mut self) -> &mut T { &mut self.stream } /// Consumes this combinator, returning the underlying stream. /// /// Note that this may discard intermediate state of this combinator, so care /// should be taken to avoid losing resources when this is called. pub fn into_inner(self) -> T { self.stream } } impl Stream for Throttle { type Item = T::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { let mut me = self.project(); let dur = *me.duration; if !*me.has_delayed && !is_zero(dur) { ready!(me.delay.as_mut().poll(cx)); *me.has_delayed = true; } let value = ready!(me.stream.poll_next(cx)); if value.is_some() { if !is_zero(dur) { me.delay.reset(Instant::now() + dur); } *me.has_delayed = false; } Poll::Ready(value) } } fn is_zero(dur: Duration) -> bool { dur == Duration::from_millis(0) } tokio-stream-0.1.8/src/stream_ext/timeout.rs000064400000000000000000000054110072674642500172770ustar 00000000000000use crate::stream_ext::Fuse; use crate::Stream; use tokio::time::{Instant, Sleep}; use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; use std::fmt; use std::time::Duration; pin_project! { /// Stream returned by the [`timeout`](super::StreamExt::timeout) method. #[must_use = "streams do nothing unless polled"] #[derive(Debug)] pub struct Timeout { #[pin] stream: Fuse, #[pin] deadline: Sleep, duration: Duration, poll_deadline: bool, } } /// Error returned by `Timeout`. #[derive(Debug, PartialEq)] pub struct Elapsed(()); impl Timeout { pub(super) fn new(stream: S, duration: Duration) -> Self { let next = Instant::now() + duration; let deadline = tokio::time::sleep_until(next); Timeout { stream: Fuse::new(stream), deadline, duration, poll_deadline: true, } } } impl Stream for Timeout { type Item = Result; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let me = self.project(); match me.stream.poll_next(cx) { Poll::Ready(v) => { if v.is_some() { let next = Instant::now() + *me.duration; me.deadline.reset(next); *me.poll_deadline = true; } return Poll::Ready(v.map(Ok)); } Poll::Pending => {} }; if *me.poll_deadline { ready!(me.deadline.poll(cx)); *me.poll_deadline = false; return Poll::Ready(Some(Err(Elapsed::new()))); } Poll::Pending } fn size_hint(&self) -> (usize, Option) { let (lower, upper) = self.stream.size_hint(); // The timeout stream may insert an error before and after each message // from the underlying stream, but no more than one error between each // message. Hence the upper bound is computed as 2x+1. // Using a helper function to enable use of question mark operator. fn twice_plus_one(value: Option) -> Option { value?.checked_mul(2)?.checked_add(1) } (lower, twice_plus_one(upper)) } } // ===== impl Elapsed ===== impl Elapsed { pub(crate) fn new() -> Self { Elapsed(()) } } impl fmt::Display for Elapsed { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { "deadline has elapsed".fmt(fmt) } } impl std::error::Error for Elapsed {} impl From for std::io::Error { fn from(_err: Elapsed) -> std::io::Error { std::io::ErrorKind::TimedOut.into() } } tokio-stream-0.1.8/src/stream_ext/try_next.rs000064400000000000000000000021050072674642500174620ustar 00000000000000use crate::stream_ext::Next; use crate::Stream; use core::future::Future; use core::marker::PhantomPinned; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; pin_project! { /// Future for the [`try_next`](super::StreamExt::try_next) method. #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct TryNext<'a, St: ?Sized> { #[pin] inner: Next<'a, St>, // Make this future `!Unpin` for compatibility with async trait methods. #[pin] _pin: PhantomPinned, } } impl<'a, St: ?Sized> TryNext<'a, St> { pub(super) fn new(stream: &'a mut St) -> Self { Self { inner: Next::new(stream), _pin: PhantomPinned, } } } impl> + Unpin> Future for TryNext<'_, St> { type Output = Result, E>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let me = self.project(); me.inner.poll(cx).map(Option::transpose) } } tokio-stream-0.1.8/src/stream_ext.rs000064400000000000000000000676670072674642500156360ustar 00000000000000use futures_core::Stream; mod all; use all::AllFuture; mod any; use any::AnyFuture; mod chain; use chain::Chain; pub(crate) mod collect; use collect::{Collect, FromStream}; mod filter; use filter::Filter; mod filter_map; use filter_map::FilterMap; mod fold; use fold::FoldFuture; mod fuse; use fuse::Fuse; mod map; use map::Map; mod merge; use merge::Merge; mod next; use next::Next; mod skip; use skip::Skip; mod skip_while; use skip_while::SkipWhile; mod try_next; use try_next::TryNext; mod take; use take::Take; mod take_while; use take_while::TakeWhile; cfg_time! { mod timeout; use timeout::Timeout; use tokio::time::Duration; mod throttle; use throttle::{throttle, Throttle}; } /// An extension trait for the [`Stream`] trait that provides a variety of /// convenient combinator functions. /// /// Be aware that the `Stream` trait in Tokio is a re-export of the trait found /// in the [futures] crate, however both Tokio and futures provide separate /// `StreamExt` utility traits, and some utilities are only available on one of /// these traits. Click [here][futures-StreamExt] to see the other `StreamExt` /// trait in the futures crate. /// /// If you need utilities from both `StreamExt` traits, you should prefer to /// import one of them, and use the other through the fully qualified call /// syntax. For example: /// ``` /// // import one of the traits: /// use futures::stream::StreamExt; /// # #[tokio::main(flavor = "current_thread")] /// # async fn main() { /// /// let a = tokio_stream::iter(vec![1, 3, 5]); /// let b = tokio_stream::iter(vec![2, 4, 6]); /// /// // use the fully qualified call syntax for the other trait: /// let merged = tokio_stream::StreamExt::merge(a, b); /// /// // use normal call notation for futures::stream::StreamExt::collect /// let output: Vec<_> = merged.collect().await; /// assert_eq!(output, vec![1, 2, 3, 4, 5, 6]); /// # } /// ``` /// /// [`Stream`]: crate::Stream /// [futures]: https://docs.rs/futures /// [futures-StreamExt]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html pub trait StreamExt: Stream { /// Consumes and returns the next value in the stream or `None` if the /// stream is finished. /// /// Equivalent to: /// /// ```ignore /// async fn next(&mut self) -> Option; /// ``` /// /// Note that because `next` doesn't take ownership over the stream, /// the [`Stream`] type must be [`Unpin`]. If you want to use `next` with a /// [`!Unpin`](Unpin) stream, you'll first have to pin the stream. This can /// be done by boxing the stream using [`Box::pin`] or /// pinning it to the stack using the `pin_mut!` macro from the `pin_utils` /// crate. /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let mut stream = stream::iter(1..=3); /// /// assert_eq!(stream.next().await, Some(1)); /// assert_eq!(stream.next().await, Some(2)); /// assert_eq!(stream.next().await, Some(3)); /// assert_eq!(stream.next().await, None); /// # } /// ``` fn next(&mut self) -> Next<'_, Self> where Self: Unpin, { Next::new(self) } /// Consumes and returns the next item in the stream. If an error is /// encountered before the next item, the error is returned instead. /// /// Equivalent to: /// /// ```ignore /// async fn try_next(&mut self) -> Result, E>; /// ``` /// /// This is similar to the [`next`](StreamExt::next) combinator, /// but returns a [`Result, E>`](Result) rather than /// an [`Option>`](Option), making for easy use /// with the [`?`](std::ops::Try) operator. /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let mut stream = stream::iter(vec![Ok(1), Ok(2), Err("nope")]); /// /// assert_eq!(stream.try_next().await, Ok(Some(1))); /// assert_eq!(stream.try_next().await, Ok(Some(2))); /// assert_eq!(stream.try_next().await, Err("nope")); /// # } /// ``` fn try_next(&mut self) -> TryNext<'_, Self> where Self: Stream> + Unpin, { TryNext::new(self) } /// Maps this stream's items to a different type, returning a new stream of /// the resulting type. /// /// The provided closure is executed over all elements of this stream as /// they are made available. It is executed inline with calls to /// [`poll_next`](Stream::poll_next). /// /// Note that this function consumes the stream passed into it and returns a /// wrapped version of it, similar to the existing `map` methods in the /// standard library. /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let stream = stream::iter(1..=3); /// let mut stream = stream.map(|x| x + 3); /// /// assert_eq!(stream.next().await, Some(4)); /// assert_eq!(stream.next().await, Some(5)); /// assert_eq!(stream.next().await, Some(6)); /// # } /// ``` fn map(self, f: F) -> Map where F: FnMut(Self::Item) -> T, Self: Sized, { Map::new(self, f) } /// Combine two streams into one by interleaving the output of both as it /// is produced. /// /// Values are produced from the merged stream in the order they arrive from /// the two source streams. If both source streams provide values /// simultaneously, the merge stream alternates between them. This provides /// some level of fairness. You should not chain calls to `merge`, as this /// will break the fairness of the merging. /// /// The merged stream completes once **both** source streams complete. When /// one source stream completes before the other, the merge stream /// exclusively polls the remaining stream. /// /// For merging multiple streams, consider using [`StreamMap`] instead. /// /// [`StreamMap`]: crate::StreamMap /// /// # Examples /// /// ``` /// use tokio_stream::{StreamExt, Stream}; /// use tokio::sync::mpsc; /// use tokio::time; /// /// use std::time::Duration; /// use std::pin::Pin; /// /// # /* /// #[tokio::main] /// # */ /// # #[tokio::main(flavor = "current_thread")] /// async fn main() { /// # time::pause(); /// let (tx1, mut rx1) = mpsc::channel::(10); /// let (tx2, mut rx2) = mpsc::channel::(10); /// /// // Convert the channels to a `Stream`. /// let rx1 = Box::pin(async_stream::stream! { /// while let Some(item) = rx1.recv().await { /// yield item; /// } /// }) as Pin + Send>>; /// /// let rx2 = Box::pin(async_stream::stream! { /// while let Some(item) = rx2.recv().await { /// yield item; /// } /// }) as Pin + Send>>; /// /// let mut rx = rx1.merge(rx2); /// /// tokio::spawn(async move { /// // Send some values immediately /// tx1.send(1).await.unwrap(); /// tx1.send(2).await.unwrap(); /// /// // Let the other task send values /// time::sleep(Duration::from_millis(20)).await; /// /// tx1.send(4).await.unwrap(); /// }); /// /// tokio::spawn(async move { /// // Wait for the first task to send values /// time::sleep(Duration::from_millis(5)).await; /// /// tx2.send(3).await.unwrap(); /// /// time::sleep(Duration::from_millis(25)).await; /// /// // Send the final value /// tx2.send(5).await.unwrap(); /// }); /// /// assert_eq!(1, rx.next().await.unwrap()); /// assert_eq!(2, rx.next().await.unwrap()); /// assert_eq!(3, rx.next().await.unwrap()); /// assert_eq!(4, rx.next().await.unwrap()); /// assert_eq!(5, rx.next().await.unwrap()); /// /// // The merged stream is consumed /// assert!(rx.next().await.is_none()); /// } /// ``` fn merge(self, other: U) -> Merge where U: Stream, Self: Sized, { Merge::new(self, other) } /// Filters the values produced by this stream according to the provided /// predicate. /// /// As values of this stream are made available, the provided predicate `f` /// will be run against them. If the predicate /// resolves to `true`, then the stream will yield the value, but if the /// predicate resolves to `false`, then the value /// will be discarded and the next value will be produced. /// /// Note that this function consumes the stream passed into it and returns a /// wrapped version of it, similar to [`Iterator::filter`] method in the /// standard library. /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let stream = stream::iter(1..=8); /// let mut evens = stream.filter(|x| x % 2 == 0); /// /// assert_eq!(Some(2), evens.next().await); /// assert_eq!(Some(4), evens.next().await); /// assert_eq!(Some(6), evens.next().await); /// assert_eq!(Some(8), evens.next().await); /// assert_eq!(None, evens.next().await); /// # } /// ``` fn filter(self, f: F) -> Filter where F: FnMut(&Self::Item) -> bool, Self: Sized, { Filter::new(self, f) } /// Filters the values produced by this stream while simultaneously mapping /// them to a different type according to the provided closure. /// /// As values of this stream are made available, the provided function will /// be run on them. If the predicate `f` resolves to /// [`Some(item)`](Some) then the stream will yield the value `item`, but if /// it resolves to [`None`], then the value will be skipped. /// /// Note that this function consumes the stream passed into it and returns a /// wrapped version of it, similar to [`Iterator::filter_map`] method in the /// standard library. /// /// # Examples /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let stream = stream::iter(1..=8); /// let mut evens = stream.filter_map(|x| { /// if x % 2 == 0 { Some(x + 1) } else { None } /// }); /// /// assert_eq!(Some(3), evens.next().await); /// assert_eq!(Some(5), evens.next().await); /// assert_eq!(Some(7), evens.next().await); /// assert_eq!(Some(9), evens.next().await); /// assert_eq!(None, evens.next().await); /// # } /// ``` fn filter_map(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option, Self: Sized, { FilterMap::new(self, f) } /// Creates a stream which ends after the first `None`. /// /// After a stream returns `None`, behavior is undefined. Future calls to /// `poll_next` may or may not return `Some(T)` again or they may panic. /// `fuse()` adapts a stream, ensuring that after `None` is given, it will /// return `None` forever. /// /// # Examples /// /// ``` /// 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 = self.state + 1; /// /// // if it's even, Some(i32), else None /// if val % 2 == 0 { /// Poll::Ready(Some(val)) /// } else { /// Poll::Ready(None) /// } /// } /// } /// /// #[tokio::main] /// async fn main() { /// 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_eq!(stream.next().await, Some(4)); /// assert_eq!(stream.next().await, None); /// /// // it will always return `None` after the first time. /// assert_eq!(stream.next().await, None); /// assert_eq!(stream.next().await, None); /// assert_eq!(stream.next().await, None); /// } /// ``` fn fuse(self) -> Fuse where Self: Sized, { Fuse::new(self) } /// Creates a new stream of at most `n` items of the underlying stream. /// /// Once `n` items have been yielded from this stream then it will always /// return that the stream is done. /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let mut stream = stream::iter(1..=10).take(3); /// /// assert_eq!(Some(1), stream.next().await); /// assert_eq!(Some(2), stream.next().await); /// assert_eq!(Some(3), stream.next().await); /// assert_eq!(None, stream.next().await); /// # } /// ``` fn take(self, n: usize) -> Take where Self: Sized, { Take::new(self, n) } /// Take elements from this stream while the provided predicate /// resolves to `true`. /// /// This function, like `Iterator::take_while`, will take elements from the /// stream until the predicate `f` resolves to `false`. Once one element /// returns false it will always return that the stream is done. /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let mut stream = stream::iter(1..=10).take_while(|x| *x <= 3); /// /// assert_eq!(Some(1), stream.next().await); /// assert_eq!(Some(2), stream.next().await); /// assert_eq!(Some(3), stream.next().await); /// assert_eq!(None, stream.next().await); /// # } /// ``` fn take_while(self, f: F) -> TakeWhile where F: FnMut(&Self::Item) -> bool, Self: Sized, { TakeWhile::new(self, f) } /// Creates a new stream that will skip the `n` first items of the /// underlying stream. /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let mut stream = stream::iter(1..=10).skip(7); /// /// assert_eq!(Some(8), stream.next().await); /// assert_eq!(Some(9), stream.next().await); /// assert_eq!(Some(10), stream.next().await); /// assert_eq!(None, stream.next().await); /// # } /// ``` fn skip(self, n: usize) -> Skip where Self: Sized, { Skip::new(self, n) } /// Skip elements from the underlying stream while the provided predicate /// resolves to `true`. /// /// This function, like [`Iterator::skip_while`], will ignore elements from the /// stream until the predicate `f` resolves to `false`. Once one element /// returns false, the rest of the elements will be yielded. /// /// [`Iterator::skip_while`]: std::iter::Iterator::skip_while() /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// let mut stream = stream::iter(vec![1,2,3,4,1]).skip_while(|x| *x < 3); /// /// assert_eq!(Some(3), stream.next().await); /// assert_eq!(Some(4), stream.next().await); /// assert_eq!(Some(1), stream.next().await); /// assert_eq!(None, stream.next().await); /// # } /// ``` fn skip_while(self, f: F) -> SkipWhile where F: FnMut(&Self::Item) -> bool, Self: Sized, { SkipWhile::new(self, f) } /// Tests if every element of the stream matches a predicate. /// /// Equivalent to: /// /// ```ignore /// async fn all(&mut self, f: F) -> bool; /// ``` /// /// `all()` takes a closure that returns `true` or `false`. It applies /// this closure to each element of the stream, and if they all return /// `true`, then so does `all`. If any of them return `false`, it /// returns `false`. An empty stream returns `true`. /// /// `all()` is short-circuiting; in other words, it will stop processing /// as soon as it finds a `false`, given that no matter what else happens, /// the result will also be `false`. /// /// An empty stream returns `true`. /// /// # Examples /// /// Basic usage: /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let a = [1, 2, 3]; /// /// assert!(stream::iter(&a).all(|&x| x > 0).await); /// /// assert!(!stream::iter(&a).all(|&x| x > 2).await); /// # } /// ``` /// /// Stopping at the first `false`: /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let a = [1, 2, 3]; /// /// let mut iter = stream::iter(&a); /// /// assert!(!iter.all(|&x| x != 2).await); /// /// // we can still use `iter`, as there are more elements. /// assert_eq!(iter.next().await, Some(&3)); /// # } /// ``` fn all(&mut self, f: F) -> AllFuture<'_, Self, F> where Self: Unpin, F: FnMut(Self::Item) -> bool, { AllFuture::new(self, f) } /// Tests if any element of the stream matches a predicate. /// /// Equivalent to: /// /// ```ignore /// async fn any(&mut self, f: F) -> bool; /// ``` /// /// `any()` takes a closure that returns `true` or `false`. It applies /// this closure to each element of the stream, and if any of them return /// `true`, then so does `any()`. If they all return `false`, it /// returns `false`. /// /// `any()` is short-circuiting; in other words, it will stop processing /// as soon as it finds a `true`, given that no matter what else happens, /// the result will also be `true`. /// /// An empty stream returns `false`. /// /// Basic usage: /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let a = [1, 2, 3]; /// /// assert!(stream::iter(&a).any(|&x| x > 0).await); /// /// assert!(!stream::iter(&a).any(|&x| x > 5).await); /// # } /// ``` /// /// Stopping at the first `true`: /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// /// let a = [1, 2, 3]; /// /// let mut iter = stream::iter(&a); /// /// assert!(iter.any(|&x| x != 2).await); /// /// // we can still use `iter`, as there are more elements. /// assert_eq!(iter.next().await, Some(&2)); /// # } /// ``` fn any(&mut self, f: F) -> AnyFuture<'_, Self, F> where Self: Unpin, F: FnMut(Self::Item) -> bool, { AnyFuture::new(self, f) } /// Combine two streams into one by first returning all values from the /// first stream then all values from the second stream. /// /// As long as `self` still has values to emit, no values from `other` are /// emitted, even if some are ready. /// /// # Examples /// /// ``` /// use tokio_stream::{self as stream, StreamExt}; /// /// #[tokio::main] /// async fn main() { /// let one = stream::iter(vec![1, 2, 3]); /// let two = stream::iter(vec![4, 5, 6]); /// /// let mut stream = one.chain(two); /// /// assert_eq!(stream.next().await, Some(1)); /// assert_eq!(stream.next().await, Some(2)); /// assert_eq!(stream.next().await, Some(3)); /// assert_eq!(stream.next().await, Some(4)); /// assert_eq!(stream.next().await, Some(5)); /// assert_eq!(stream.next().await, Some(6)); /// assert_eq!(stream.next().await, None); /// } /// ``` fn chain(self, other: U) -> Chain where U: Stream, Self: Sized, { Chain::new(self, other) } /// A combinator that applies a function to every element in a stream /// producing a single, final value. /// /// Equivalent to: /// /// ```ignore /// async fn fold(self, init: B, f: F) -> B; /// ``` /// /// # Examples /// Basic usage: /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, *}; /// /// let s = stream::iter(vec![1u8, 2, 3]); /// let sum = s.fold(0, |acc, x| acc + x).await; /// /// assert_eq!(sum, 6); /// # } /// ``` fn fold(self, init: B, f: F) -> FoldFuture where Self: Sized, F: FnMut(B, Self::Item) -> B, { FoldFuture::new(self, init, f) } /// Drain stream pushing all emitted values into a collection. /// /// Equivalent to: /// /// ```ignore /// async fn collect(self) -> T; /// ``` /// /// `collect` streams all values, awaiting as needed. Values are pushed into /// a collection. A number of different target collection types are /// supported, including [`Vec`](std::vec::Vec), /// [`String`](std::string::String), and [`Bytes`]. /// /// [`Bytes`]: https://docs.rs/bytes/0.6.0/bytes/struct.Bytes.html /// /// # `Result` /// /// `collect()` can also be used with streams of type `Result` where /// `T: FromStream<_>`. In this case, `collect()` will stream as long as /// values yielded from the stream are `Ok(_)`. If `Err(_)` is encountered, /// streaming is terminated and `collect()` returns the `Err`. /// /// # Notes /// /// `FromStream` is currently a sealed trait. Stabilization is pending /// enhancements to the Rust language. /// /// # Examples /// /// Basic usage: /// /// ``` /// use tokio_stream::{self as stream, StreamExt}; /// /// #[tokio::main] /// async fn main() { /// let doubled: Vec = /// stream::iter(vec![1, 2, 3]) /// .map(|x| x * 2) /// .collect() /// .await; /// /// assert_eq!(vec![2, 4, 6], doubled); /// } /// ``` /// /// Collecting a stream of `Result` values /// /// ``` /// use tokio_stream::{self as stream, StreamExt}; /// /// #[tokio::main] /// async fn main() { /// // A stream containing only `Ok` values will be collected /// let values: Result, &str> = /// stream::iter(vec![Ok(1), Ok(2), Ok(3)]) /// .collect() /// .await; /// /// assert_eq!(Ok(vec![1, 2, 3]), values); /// /// // A stream containing `Err` values will return the first error. /// let results = vec![Ok(1), Err("no"), Ok(2), Ok(3), Err("nein")]; /// /// let values: Result, &str> = /// stream::iter(results) /// .collect() /// .await; /// /// assert_eq!(Err("no"), values); /// } /// ``` fn collect(self) -> Collect where T: FromStream, Self: Sized, { Collect::new(self) } /// Applies a per-item timeout to the passed stream. /// /// `timeout()` takes a `Duration` that represents the maximum amount of /// time each element of the stream has to complete before timing out. /// /// If the wrapped stream yields a value before the deadline is reached, the /// value is returned. Otherwise, an error is returned. The caller may decide /// to continue consuming the stream and will eventually get the next source /// stream value once it becomes available. /// /// # Notes /// /// This function consumes the stream passed into it and returns a /// wrapped version of it. /// /// Polling the returned stream will continue to poll the inner stream even /// if one or more items time out. /// /// # Examples /// /// Suppose we have a stream `int_stream` that yields 3 numbers (1, 2, 3): /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{self as stream, StreamExt}; /// use std::time::Duration; /// # let int_stream = stream::iter(1..=3); /// /// let int_stream = int_stream.timeout(Duration::from_secs(1)); /// tokio::pin!(int_stream); /// /// // When no items time out, we get the 3 elements in succession: /// assert_eq!(int_stream.try_next().await, Ok(Some(1))); /// assert_eq!(int_stream.try_next().await, Ok(Some(2))); /// assert_eq!(int_stream.try_next().await, Ok(Some(3))); /// assert_eq!(int_stream.try_next().await, Ok(None)); /// /// // If the second item times out, we get an error and continue polling the stream: /// # let mut int_stream = stream::iter(vec![Ok(1), Err(()), Ok(2), Ok(3)]); /// assert_eq!(int_stream.try_next().await, Ok(Some(1))); /// assert!(int_stream.try_next().await.is_err()); /// assert_eq!(int_stream.try_next().await, Ok(Some(2))); /// assert_eq!(int_stream.try_next().await, Ok(Some(3))); /// assert_eq!(int_stream.try_next().await, Ok(None)); /// /// // If we want to stop consuming the source stream the first time an /// // element times out, we can use the `take_while` operator: /// # let int_stream = stream::iter(vec![Ok(1), Err(()), Ok(2), Ok(3)]); /// let mut int_stream = int_stream.take_while(Result::is_ok); /// /// assert_eq!(int_stream.try_next().await, Ok(Some(1))); /// assert_eq!(int_stream.try_next().await, Ok(None)); /// # } /// ``` #[cfg(all(feature = "time"))] #[cfg_attr(docsrs, doc(cfg(feature = "time")))] fn timeout(self, duration: Duration) -> Timeout where Self: Sized, { Timeout::new(self, duration) } /// Slows down a stream by enforcing a delay between items. /// /// # Example /// /// Create a throttled stream. /// ```rust,no_run /// use std::time::Duration; /// use tokio_stream::StreamExt; /// /// # async fn dox() { /// let item_stream = futures::stream::repeat("one").throttle(Duration::from_secs(2)); /// tokio::pin!(item_stream); /// /// loop { /// // The string will be produced at most every 2 seconds /// println!("{:?}", item_stream.next().await); /// } /// # } /// ``` #[cfg(all(feature = "time"))] #[cfg_attr(docsrs, doc(cfg(feature = "time")))] fn throttle(self, duration: Duration) -> Throttle where Self: Sized, { throttle(duration, self) } } impl StreamExt for St where St: Stream {} /// Merge the size hints from two streams. fn merge_size_hints( (left_low, left_high): (usize, Option), (right_low, right_hign): (usize, Option), ) -> (usize, Option) { let low = left_low.saturating_add(right_low); let high = match (left_high, right_hign) { (Some(h1), Some(h2)) => h1.checked_add(h2), _ => None, }; (low, high) } tokio-stream-0.1.8/src/stream_map.rs000064400000000000000000000467600072674642500156020ustar 00000000000000use crate::Stream; use std::borrow::Borrow; use std::hash::Hash; use std::pin::Pin; use std::task::{Context, Poll}; /// Combine many streams into one, indexing each source stream with a unique /// key. /// /// `StreamMap` is similar to [`StreamExt::merge`] in that it combines source /// streams into a single merged stream that yields values in the order that /// they arrive from the source streams. However, `StreamMap` has a lot more /// flexibility in usage patterns. /// /// `StreamMap` can: /// /// * Merge an arbitrary number of streams. /// * Track which source stream the value was received from. /// * Handle inserting and removing streams from the set of managed streams at /// any point during iteration. /// /// All source streams held by `StreamMap` are indexed using a key. This key is /// included with the value when a source stream yields a value. The key is also /// used to remove the stream from the `StreamMap` before the stream has /// completed streaming. /// /// # `Unpin` /// /// Because the `StreamMap` API moves streams during runtime, both streams and /// keys must be `Unpin`. In order to insert a `!Unpin` stream into a /// `StreamMap`, use [`pin!`] to pin the stream to the stack or [`Box::pin`] to /// pin the stream in the heap. /// /// # Implementation /// /// `StreamMap` is backed by a `Vec<(K, V)>`. There is no guarantee that this /// internal implementation detail will persist in future versions, but it is /// important to know the runtime implications. In general, `StreamMap` works /// best with a "smallish" number of streams as all entries are scanned on /// insert, remove, and polling. In cases where a large number of streams need /// to be merged, it may be advisable to use tasks sending values on a shared /// [`mpsc`] channel. /// /// [`StreamExt::merge`]: crate::StreamExt::merge /// [`mpsc`]: https://docs.rs/tokio/1.0/tokio/sync/mpsc/index.html /// [`pin!`]: https://docs.rs/tokio/1.0/tokio/macro.pin.html /// [`Box::pin`]: std::boxed::Box::pin /// /// # Examples /// /// Merging two streams, then remove them after receiving the first value /// /// ``` /// use tokio_stream::{StreamExt, StreamMap, Stream}; /// use tokio::sync::mpsc; /// use std::pin::Pin; /// /// #[tokio::main] /// async fn main() { /// let (tx1, mut rx1) = mpsc::channel::(10); /// let (tx2, mut rx2) = mpsc::channel::(10); /// /// // Convert the channels to a `Stream`. /// let rx1 = Box::pin(async_stream::stream! { /// while let Some(item) = rx1.recv().await { /// yield item; /// } /// }) as Pin + Send>>; /// /// let rx2 = Box::pin(async_stream::stream! { /// while let Some(item) = rx2.recv().await { /// yield item; /// } /// }) as Pin + Send>>; /// /// tokio::spawn(async move { /// tx1.send(1).await.unwrap(); /// /// // This value will never be received. The send may or may not return /// // `Err` depending on if the remote end closed first or not. /// let _ = tx1.send(2).await; /// }); /// /// tokio::spawn(async move { /// tx2.send(3).await.unwrap(); /// let _ = tx2.send(4).await; /// }); /// /// let mut map = StreamMap::new(); /// /// // Insert both streams /// map.insert("one", rx1); /// map.insert("two", rx2); /// /// // Read twice /// for _ in 0..2 { /// let (key, val) = map.next().await.unwrap(); /// /// if key == "one" { /// assert_eq!(val, 1); /// } else { /// assert_eq!(val, 3); /// } /// /// // Remove the stream to prevent reading the next value /// map.remove(key); /// } /// } /// ``` /// /// This example models a read-only client to a chat system with channels. The /// client sends commands to join and leave channels. `StreamMap` is used to /// manage active channel subscriptions. /// /// For simplicity, messages are displayed with `println!`, but they could be /// sent to the client over a socket. /// /// ```no_run /// use tokio_stream::{Stream, StreamExt, StreamMap}; /// /// enum Command { /// Join(String), /// Leave(String), /// } /// /// fn commands() -> impl Stream { /// // Streams in user commands by parsing `stdin`. /// # tokio_stream::pending() /// } /// /// // Join a channel, returns a stream of messages received on the channel. /// fn join(channel: &str) -> impl Stream + Unpin { /// // left as an exercise to the reader /// # tokio_stream::pending() /// } /// /// #[tokio::main] /// async fn main() { /// let mut channels = StreamMap::new(); /// /// // Input commands (join / leave channels). /// let cmds = commands(); /// tokio::pin!(cmds); /// /// loop { /// tokio::select! { /// Some(cmd) = cmds.next() => { /// match cmd { /// Command::Join(chan) => { /// // Join the channel and add it to the `channels` /// // stream map /// let msgs = join(&chan); /// channels.insert(chan, msgs); /// } /// Command::Leave(chan) => { /// channels.remove(&chan); /// } /// } /// } /// Some((chan, msg)) = channels.next() => { /// // Received a message, display it on stdout with the channel /// // it originated from. /// println!("{}: {}", chan, msg); /// } /// // Both the `commands` stream and the `channels` stream are /// // complete. There is no more work to do, so leave the loop. /// else => break, /// } /// } /// } /// ``` #[derive(Debug)] pub struct StreamMap { /// Streams stored in the map entries: Vec<(K, V)>, } impl StreamMap { /// An iterator visiting all key-value pairs in arbitrary order. /// /// The iterator element type is &'a (K, V). /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut map = StreamMap::new(); /// /// map.insert("a", pending::()); /// map.insert("b", pending()); /// map.insert("c", pending()); /// /// for (key, stream) in map.iter() { /// println!("({}, {:?})", key, stream); /// } /// ``` pub fn iter(&self) -> impl Iterator { self.entries.iter() } /// An iterator visiting all key-value pairs mutably in arbitrary order. /// /// The iterator element type is &'a mut (K, V). /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut map = StreamMap::new(); /// /// map.insert("a", pending::()); /// map.insert("b", pending()); /// map.insert("c", pending()); /// /// for (key, stream) in map.iter_mut() { /// println!("({}, {:?})", key, stream); /// } /// ``` pub fn iter_mut(&mut self) -> impl Iterator { self.entries.iter_mut() } /// Creates an empty `StreamMap`. /// /// The stream map is initially created with a capacity of `0`, so it will /// not allocate until it is first inserted into. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, Pending}; /// /// let map: StreamMap<&str, Pending<()>> = StreamMap::new(); /// ``` pub fn new() -> StreamMap { StreamMap { entries: vec![] } } /// Creates an empty `StreamMap` with the specified capacity. /// /// The stream map will be able to hold at least `capacity` elements without /// reallocating. If `capacity` is 0, the stream map will not allocate. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, Pending}; /// /// let map: StreamMap<&str, Pending<()>> = StreamMap::with_capacity(10); /// ``` pub fn with_capacity(capacity: usize) -> StreamMap { StreamMap { entries: Vec::with_capacity(capacity), } } /// Returns an iterator visiting all keys in arbitrary order. /// /// The iterator element type is &'a K. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut map = StreamMap::new(); /// /// map.insert("a", pending::()); /// map.insert("b", pending()); /// map.insert("c", pending()); /// /// for key in map.keys() { /// println!("{}", key); /// } /// ``` pub fn keys(&self) -> impl Iterator { self.iter().map(|(k, _)| k) } /// An iterator visiting all values in arbitrary order. /// /// The iterator element type is &'a V. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut map = StreamMap::new(); /// /// map.insert("a", pending::()); /// map.insert("b", pending()); /// map.insert("c", pending()); /// /// for stream in map.values() { /// println!("{:?}", stream); /// } /// ``` pub fn values(&self) -> impl Iterator { self.iter().map(|(_, v)| v) } /// An iterator visiting all values mutably in arbitrary order. /// /// The iterator element type is &'a mut V. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut map = StreamMap::new(); /// /// map.insert("a", pending::()); /// map.insert("b", pending()); /// map.insert("c", pending()); /// /// for stream in map.values_mut() { /// println!("{:?}", stream); /// } /// ``` pub fn values_mut(&mut self) -> impl Iterator { self.iter_mut().map(|(_, v)| v) } /// Returns the number of streams the map can hold without reallocating. /// /// This number is a lower bound; the `StreamMap` might be able to hold /// more, but is guaranteed to be able to hold at least this many. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, Pending}; /// /// let map: StreamMap> = StreamMap::with_capacity(100); /// assert!(map.capacity() >= 100); /// ``` pub fn capacity(&self) -> usize { self.entries.capacity() } /// Returns the number of streams in the map. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut a = StreamMap::new(); /// assert_eq!(a.len(), 0); /// a.insert(1, pending::()); /// assert_eq!(a.len(), 1); /// ``` pub fn len(&self) -> usize { self.entries.len() } /// Returns `true` if the map contains no elements. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut a = StreamMap::new(); /// assert!(a.is_empty()); /// a.insert(1, pending::()); /// assert!(!a.is_empty()); /// ``` pub fn is_empty(&self) -> bool { self.entries.is_empty() } /// Clears the map, removing all key-stream pairs. Keeps the allocated /// memory for reuse. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut a = StreamMap::new(); /// a.insert(1, pending::()); /// a.clear(); /// assert!(a.is_empty()); /// ``` pub fn clear(&mut self) { self.entries.clear(); } /// Insert a key-stream pair into the map. /// /// If the map did not have this key present, `None` is returned. /// /// If the map did have this key present, the new `stream` replaces the old /// one and the old stream is returned. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut map = StreamMap::new(); /// /// assert!(map.insert(37, pending::()).is_none()); /// assert!(!map.is_empty()); /// /// map.insert(37, pending()); /// assert!(map.insert(37, pending()).is_some()); /// ``` pub fn insert(&mut self, k: K, stream: V) -> Option where K: Hash + Eq, { let ret = self.remove(&k); self.entries.push((k, stream)); ret } /// Removes a key from the map, returning the stream at the key if the key was previously in the map. /// /// The key may be any borrowed form of the map's key type, but `Hash` and /// `Eq` on the borrowed form must match those for the key type. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut map = StreamMap::new(); /// map.insert(1, pending::()); /// assert!(map.remove(&1).is_some()); /// assert!(map.remove(&1).is_none()); /// ``` pub fn remove(&mut self, k: &Q) -> Option where K: Borrow, Q: Hash + Eq, { for i in 0..self.entries.len() { if self.entries[i].0.borrow() == k { return Some(self.entries.swap_remove(i).1); } } None } /// Returns `true` if the map contains a stream for the specified key. /// /// The key may be any borrowed form of the map's key type, but `Hash` and /// `Eq` on the borrowed form must match those for the key type. /// /// # Examples /// /// ``` /// use tokio_stream::{StreamMap, pending}; /// /// let mut map = StreamMap::new(); /// map.insert(1, pending::()); /// assert_eq!(map.contains_key(&1), true); /// assert_eq!(map.contains_key(&2), false); /// ``` pub fn contains_key(&self, k: &Q) -> bool where K: Borrow, Q: Hash + Eq, { for i in 0..self.entries.len() { if self.entries[i].0.borrow() == k { return true; } } false } } impl StreamMap where K: Unpin, V: Stream + Unpin, { /// Polls the next value, includes the vec entry index fn poll_next_entry(&mut self, cx: &mut Context<'_>) -> Poll> { use Poll::*; let start = self::rand::thread_rng_n(self.entries.len() as u32) as usize; let mut idx = start; for _ in 0..self.entries.len() { let (_, stream) = &mut self.entries[idx]; match Pin::new(stream).poll_next(cx) { Ready(Some(val)) => return Ready(Some((idx, val))), Ready(None) => { // Remove the entry self.entries.swap_remove(idx); // Check if this was the last entry, if so the cursor needs // to wrap if idx == self.entries.len() { idx = 0; } else if idx < start && start <= self.entries.len() { // The stream being swapped into the current index has // already been polled, so skip it. idx = idx.wrapping_add(1) % self.entries.len(); } } Pending => { idx = idx.wrapping_add(1) % self.entries.len(); } } } // If the map is empty, then the stream is complete. if self.entries.is_empty() { Ready(None) } else { Pending } } } impl Default for StreamMap { fn default() -> Self { Self::new() } } impl Stream for StreamMap where K: Clone + Unpin, V: Stream + Unpin, { type Item = (K, V::Item); fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { if let Some((idx, val)) = ready!(self.poll_next_entry(cx)) { let key = self.entries[idx].0.clone(); Poll::Ready(Some((key, val))) } else { Poll::Ready(None) } } fn size_hint(&self) -> (usize, Option) { let mut ret = (0, Some(0)); for (_, stream) in &self.entries { let hint = stream.size_hint(); ret.0 += hint.0; match (ret.1, hint.1) { (Some(a), Some(b)) => ret.1 = Some(a + b), (Some(_), None) => ret.1 = None, _ => {} } } ret } } impl std::iter::FromIterator<(K, V)> for StreamMap where K: Hash + Eq, { fn from_iter>(iter: T) -> Self { let iterator = iter.into_iter(); let (lower_bound, _) = iterator.size_hint(); let mut stream_map = Self::with_capacity(lower_bound); for (key, value) in iterator { stream_map.insert(key, value); } stream_map } } mod rand { use std::cell::Cell; mod loom { #[cfg(not(loom))] pub(crate) mod rand { use std::collections::hash_map::RandomState; use std::hash::{BuildHasher, Hash, Hasher}; use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering::Relaxed; static COUNTER: AtomicU32 = AtomicU32::new(1); pub(crate) fn seed() -> u64 { let rand_state = RandomState::new(); let mut hasher = rand_state.build_hasher(); // Hash some unique-ish data to generate some new state COUNTER.fetch_add(1, Relaxed).hash(&mut hasher); // Get the seed hasher.finish() } } #[cfg(loom)] pub(crate) mod rand { pub(crate) fn seed() -> u64 { 1 } } } /// Fast random number generate /// /// Implement xorshift64+: 2 32-bit xorshift sequences added together. /// Shift triplet `[17,7,16]` was calculated as indicated in Marsaglia's /// Xorshift paper: /// This generator passes the SmallCrush suite, part of TestU01 framework: /// #[derive(Debug)] pub(crate) struct FastRand { one: Cell, two: Cell, } impl FastRand { /// Initialize a new, thread-local, fast random number generator. pub(crate) fn new(seed: u64) -> FastRand { let one = (seed >> 32) as u32; let mut two = seed as u32; if two == 0 { // This value cannot be zero two = 1; } FastRand { one: Cell::new(one), two: Cell::new(two), } } pub(crate) fn fastrand_n(&self, n: u32) -> u32 { // This is similar to fastrand() % n, but faster. // See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ let mul = (self.fastrand() as u64).wrapping_mul(n as u64); (mul >> 32) as u32 } fn fastrand(&self) -> u32 { let mut s1 = self.one.get(); let s0 = self.two.get(); s1 ^= s1 << 17; s1 = s1 ^ s0 ^ s1 >> 7 ^ s0 >> 16; self.one.set(s0); self.two.set(s1); s0.wrapping_add(s1) } } // Used by `StreamMap` pub(crate) fn thread_rng_n(n: u32) -> u32 { thread_local! { static THREAD_RNG: FastRand = FastRand::new(loom::rand::seed()); } THREAD_RNG.with(|rng| rng.fastrand_n(n)) } } tokio-stream-0.1.8/src/wrappers/broadcast.rs000064400000000000000000000047240072674642500172510ustar 00000000000000use std::pin::Pin; use tokio::sync::broadcast::error::RecvError; use tokio::sync::broadcast::Receiver; use futures_core::Stream; use tokio_util::sync::ReusableBoxFuture; use std::fmt; use std::task::{Context, Poll}; /// A wrapper around [`tokio::sync::broadcast::Receiver`] that implements [`Stream`]. /// /// [`tokio::sync::broadcast::Receiver`]: struct@tokio::sync::broadcast::Receiver /// [`Stream`]: trait@crate::Stream #[cfg_attr(docsrs, doc(cfg(feature = "sync")))] pub struct BroadcastStream { inner: ReusableBoxFuture<(Result, Receiver)>, } /// An error returned from the inner stream of a [`BroadcastStream`]. #[derive(Debug, PartialEq)] pub enum BroadcastStreamRecvError { /// The receiver lagged too far behind. Attempting to receive again will /// return the oldest message still retained by the channel. /// /// Includes the number of skipped messages. Lagged(u64), } impl fmt::Display for BroadcastStreamRecvError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { BroadcastStreamRecvError::Lagged(amt) => write!(f, "channel lagged by {}", amt), } } } impl std::error::Error for BroadcastStreamRecvError {} async fn make_future(mut rx: Receiver) -> (Result, Receiver) { let result = rx.recv().await; (result, rx) } impl BroadcastStream { /// Create a new `BroadcastStream`. pub fn new(rx: Receiver) -> Self { Self { inner: ReusableBoxFuture::new(make_future(rx)), } } } impl Stream for BroadcastStream { type Item = Result; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let (result, rx) = ready!(self.inner.poll(cx)); self.inner.set(make_future(rx)); match result { Ok(item) => Poll::Ready(Some(Ok(item))), Err(RecvError::Closed) => Poll::Ready(None), Err(RecvError::Lagged(n)) => { Poll::Ready(Some(Err(BroadcastStreamRecvError::Lagged(n)))) } } } } impl fmt::Debug for BroadcastStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("BroadcastStream").finish() } } impl From> for BroadcastStream { fn from(recv: Receiver) -> Self { Self::new(recv) } } tokio-stream-0.1.8/src/wrappers/interval.rs000064400000000000000000000021750072674642500171310ustar 00000000000000use crate::Stream; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::time::{Instant, Interval}; /// A wrapper around [`Interval`] that implements [`Stream`]. /// /// [`Interval`]: struct@tokio::time::Interval /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "time")))] pub struct IntervalStream { inner: Interval, } impl IntervalStream { /// Create a new `IntervalStream`. pub fn new(interval: Interval) -> Self { Self { inner: interval } } /// Get back the inner `Interval`. pub fn into_inner(self) -> Interval { self.inner } } impl Stream for IntervalStream { type Item = Instant; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.inner.poll_tick(cx).map(Some) } fn size_hint(&self) -> (usize, Option) { (std::usize::MAX, None) } } impl AsRef for IntervalStream { fn as_ref(&self) -> &Interval { &self.inner } } impl AsMut for IntervalStream { fn as_mut(&mut self) -> &mut Interval { &mut self.inner } } tokio-stream-0.1.8/src/wrappers/lines.rs000064400000000000000000000030060072674642500164110ustar 00000000000000use crate::Stream; use pin_project_lite::pin_project; use std::io; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::io::{AsyncBufRead, Lines}; pin_project! { /// A wrapper around [`tokio::io::Lines`] that implements [`Stream`]. /// /// [`tokio::io::Lines`]: struct@tokio::io::Lines /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct LinesStream { #[pin] inner: Lines, } } impl LinesStream { /// Create a new `LinesStream`. pub fn new(lines: Lines) -> Self { Self { inner: lines } } /// Get back the inner `Lines`. pub fn into_inner(self) -> Lines { self.inner } /// Obtain a pinned reference to the inner `Lines`. #[allow(clippy::wrong_self_convention)] // https://github.com/rust-lang/rust-clippy/issues/4546 pub fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Lines> { self.project().inner } } impl Stream for LinesStream { type Item = io::Result; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project() .inner .poll_next_line(cx) .map(Result::transpose) } } impl AsRef> for LinesStream { fn as_ref(&self) -> &Lines { &self.inner } } impl AsMut> for LinesStream { fn as_mut(&mut self) -> &mut Lines { &mut self.inner } } tokio-stream-0.1.8/src/wrappers/mpsc_bounded.rs000064400000000000000000000033750072674642500177520ustar 00000000000000use crate::Stream; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::sync::mpsc::Receiver; /// A wrapper around [`tokio::sync::mpsc::Receiver`] that implements [`Stream`]. /// /// [`tokio::sync::mpsc::Receiver`]: struct@tokio::sync::mpsc::Receiver /// [`Stream`]: trait@crate::Stream #[derive(Debug)] pub struct ReceiverStream { inner: Receiver, } impl ReceiverStream { /// Create a new `ReceiverStream`. pub fn new(recv: Receiver) -> Self { Self { inner: recv } } /// Get back the inner `Receiver`. pub fn into_inner(self) -> Receiver { self.inner } /// Closes the receiving half of a channel without dropping it. /// /// This prevents any further messages from being sent on the channel while /// still enabling the receiver to drain messages that are buffered. Any /// outstanding [`Permit`] values will still be able to send messages. /// /// To guarantee no messages are dropped, after calling `close()`, you must /// receive all items from the stream until `None` is returned. /// /// [`Permit`]: struct@tokio::sync::mpsc::Permit pub fn close(&mut self) { self.inner.close() } } impl Stream for ReceiverStream { type Item = T; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.inner.poll_recv(cx) } } impl AsRef> for ReceiverStream { fn as_ref(&self) -> &Receiver { &self.inner } } impl AsMut> for ReceiverStream { fn as_mut(&mut self) -> &mut Receiver { &mut self.inner } } impl From> for ReceiverStream { fn from(recv: Receiver) -> Self { Self::new(recv) } } tokio-stream-0.1.8/src/wrappers/mpsc_unbounded.rs000064400000000000000000000032220072674642500203040ustar 00000000000000use crate::Stream; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::sync::mpsc::UnboundedReceiver; /// A wrapper around [`tokio::sync::mpsc::UnboundedReceiver`] that implements [`Stream`]. /// /// [`tokio::sync::mpsc::UnboundedReceiver`]: struct@tokio::sync::mpsc::UnboundedReceiver /// [`Stream`]: trait@crate::Stream #[derive(Debug)] pub struct UnboundedReceiverStream { inner: UnboundedReceiver, } impl UnboundedReceiverStream { /// Create a new `UnboundedReceiverStream`. pub fn new(recv: UnboundedReceiver) -> Self { Self { inner: recv } } /// Get back the inner `UnboundedReceiver`. pub fn into_inner(self) -> UnboundedReceiver { self.inner } /// Closes the receiving half of a channel without dropping it. /// /// This prevents any further messages from being sent on the channel while /// still enabling the receiver to drain messages that are buffered. pub fn close(&mut self) { self.inner.close() } } impl Stream for UnboundedReceiverStream { type Item = T; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.inner.poll_recv(cx) } } impl AsRef> for UnboundedReceiverStream { fn as_ref(&self) -> &UnboundedReceiver { &self.inner } } impl AsMut> for UnboundedReceiverStream { fn as_mut(&mut self) -> &mut UnboundedReceiver { &mut self.inner } } impl From> for UnboundedReceiverStream { fn from(recv: UnboundedReceiver) -> Self { Self::new(recv) } } tokio-stream-0.1.8/src/wrappers/read_dir.rs000064400000000000000000000021210072674642500170450ustar 00000000000000use crate::Stream; use std::io; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::fs::{DirEntry, ReadDir}; /// A wrapper around [`tokio::fs::ReadDir`] that implements [`Stream`]. /// /// [`tokio::fs::ReadDir`]: struct@tokio::fs::ReadDir /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "fs")))] pub struct ReadDirStream { inner: ReadDir, } impl ReadDirStream { /// Create a new `ReadDirStream`. pub fn new(read_dir: ReadDir) -> Self { Self { inner: read_dir } } /// Get back the inner `ReadDir`. pub fn into_inner(self) -> ReadDir { self.inner } } impl Stream for ReadDirStream { type Item = io::Result; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.inner.poll_next_entry(cx).map(Result::transpose) } } impl AsRef for ReadDirStream { fn as_ref(&self) -> &ReadDir { &self.inner } } impl AsMut for ReadDirStream { fn as_mut(&mut self) -> &mut ReadDir { &mut self.inner } } tokio-stream-0.1.8/src/wrappers/signal_unix.rs000064400000000000000000000017740072674642500176310ustar 00000000000000use crate::Stream; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::signal::unix::Signal; /// A wrapper around [`Signal`] that implements [`Stream`]. /// /// [`Signal`]: struct@tokio::signal::unix::Signal /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(all(unix, feature = "signal"))))] pub struct SignalStream { inner: Signal, } impl SignalStream { /// Create a new `SignalStream`. pub fn new(interval: Signal) -> Self { Self { inner: interval } } /// Get back the inner `Signal`. pub fn into_inner(self) -> Signal { self.inner } } impl Stream for SignalStream { type Item = (); fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.inner.poll_recv(cx) } } impl AsRef for SignalStream { fn as_ref(&self) -> &Signal { &self.inner } } impl AsMut for SignalStream { fn as_mut(&mut self) -> &mut Signal { &mut self.inner } } tokio-stream-0.1.8/src/wrappers/signal_windows.rs000064400000000000000000000037160072674642500203360ustar 00000000000000use crate::Stream; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::signal::windows::{CtrlBreak, CtrlC}; /// A wrapper around [`CtrlC`] that implements [`Stream`]. /// /// [`CtrlC`]: struct@tokio::signal::windows::CtrlC /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(all(windows, feature = "signal"))))] pub struct CtrlCStream { inner: CtrlC, } impl CtrlCStream { /// Create a new `CtrlCStream`. pub fn new(interval: CtrlC) -> Self { Self { inner: interval } } /// Get back the inner `CtrlC`. pub fn into_inner(self) -> CtrlC { self.inner } } impl Stream for CtrlCStream { type Item = (); fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.inner.poll_recv(cx) } } impl AsRef for CtrlCStream { fn as_ref(&self) -> &CtrlC { &self.inner } } impl AsMut for CtrlCStream { fn as_mut(&mut self) -> &mut CtrlC { &mut self.inner } } /// A wrapper around [`CtrlBreak`] that implements [`Stream`]. /// /// [`CtrlBreak`]: struct@tokio::signal::windows::CtrlBreak /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(all(windows, feature = "signal"))))] pub struct CtrlBreakStream { inner: CtrlBreak, } impl CtrlBreakStream { /// Create a new `CtrlBreakStream`. pub fn new(interval: CtrlBreak) -> Self { Self { inner: interval } } /// Get back the inner `CtrlBreak`. pub fn into_inner(self) -> CtrlBreak { self.inner } } impl Stream for CtrlBreakStream { type Item = (); fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.inner.poll_recv(cx) } } impl AsRef for CtrlBreakStream { fn as_ref(&self) -> &CtrlBreak { &self.inner } } impl AsMut for CtrlBreakStream { fn as_mut(&mut self) -> &mut CtrlBreak { &mut self.inner } } tokio-stream-0.1.8/src/wrappers/split.rs000064400000000000000000000030120072674642500164270ustar 00000000000000use crate::Stream; use pin_project_lite::pin_project; use std::io; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::io::{AsyncBufRead, Split}; pin_project! { /// A wrapper around [`tokio::io::Split`] that implements [`Stream`]. /// /// [`tokio::io::Split`]: struct@tokio::io::Split /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct SplitStream { #[pin] inner: Split, } } impl SplitStream { /// Create a new `SplitStream`. pub fn new(split: Split) -> Self { Self { inner: split } } /// Get back the inner `Split`. pub fn into_inner(self) -> Split { self.inner } /// Obtain a pinned reference to the inner `Split`. #[allow(clippy::wrong_self_convention)] // https://github.com/rust-lang/rust-clippy/issues/4546 pub fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Split> { self.project().inner } } impl Stream for SplitStream { type Item = io::Result>; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project() .inner .poll_next_segment(cx) .map(Result::transpose) } } impl AsRef> for SplitStream { fn as_ref(&self) -> &Split { &self.inner } } impl AsMut> for SplitStream { fn as_mut(&mut self) -> &mut Split { &mut self.inner } } tokio-stream-0.1.8/src/wrappers/tcp_listener.rs000064400000000000000000000025260072674642500200000ustar 00000000000000use crate::Stream; use std::io; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::net::{TcpListener, TcpStream}; /// A wrapper around [`TcpListener`] that implements [`Stream`]. /// /// [`TcpListener`]: struct@tokio::net::TcpListener /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] pub struct TcpListenerStream { inner: TcpListener, } impl TcpListenerStream { /// Create a new `TcpListenerStream`. pub fn new(listener: TcpListener) -> Self { Self { inner: listener } } /// Get back the inner `TcpListener`. pub fn into_inner(self) -> TcpListener { self.inner } } impl Stream for TcpListenerStream { type Item = io::Result; fn poll_next( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { match self.inner.poll_accept(cx) { Poll::Ready(Ok((stream, _))) => Poll::Ready(Some(Ok(stream))), Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))), Poll::Pending => Poll::Pending, } } } impl AsRef for TcpListenerStream { fn as_ref(&self) -> &TcpListener { &self.inner } } impl AsMut for TcpListenerStream { fn as_mut(&mut self) -> &mut TcpListener { &mut self.inner } } tokio-stream-0.1.8/src/wrappers/unix_listener.rs000064400000000000000000000025660072674642500202010ustar 00000000000000use crate::Stream; use std::io; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::net::{UnixListener, UnixStream}; /// A wrapper around [`UnixListener`] that implements [`Stream`]. /// /// [`UnixListener`]: struct@tokio::net::UnixListener /// [`Stream`]: trait@crate::Stream #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(all(unix, feature = "net"))))] pub struct UnixListenerStream { inner: UnixListener, } impl UnixListenerStream { /// Create a new `UnixListenerStream`. pub fn new(listener: UnixListener) -> Self { Self { inner: listener } } /// Get back the inner `UnixListener`. pub fn into_inner(self) -> UnixListener { self.inner } } impl Stream for UnixListenerStream { type Item = io::Result; fn poll_next( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { match self.inner.poll_accept(cx) { Poll::Ready(Ok((stream, _))) => Poll::Ready(Some(Ok(stream))), Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))), Poll::Pending => Poll::Pending, } } } impl AsRef for UnixListenerStream { fn as_ref(&self) -> &UnixListener { &self.inner } } impl AsMut for UnixListenerStream { fn as_mut(&mut self) -> &mut UnixListener { &mut self.inner } } tokio-stream-0.1.8/src/wrappers/watch.rs000064400000000000000000000054060072674642500164130ustar 00000000000000use std::pin::Pin; use tokio::sync::watch::Receiver; use futures_core::Stream; use tokio_util::sync::ReusableBoxFuture; use std::fmt; use std::task::{Context, Poll}; use tokio::sync::watch::error::RecvError; /// A wrapper around [`tokio::sync::watch::Receiver`] that implements [`Stream`]. /// /// This stream will always start by yielding the current value when the WatchStream is polled, /// regardless of whether it was the initial value or sent afterwards. /// /// # Examples /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{StreamExt, wrappers::WatchStream}; /// use tokio::sync::watch; /// /// let (tx, rx) = watch::channel("hello"); /// let mut rx = WatchStream::new(rx); /// /// assert_eq!(rx.next().await, Some("hello")); /// /// tx.send("goodbye").unwrap(); /// assert_eq!(rx.next().await, Some("goodbye")); /// # } /// ``` /// /// ``` /// # #[tokio::main] /// # async fn main() { /// use tokio_stream::{StreamExt, wrappers::WatchStream}; /// use tokio::sync::watch; /// /// let (tx, rx) = watch::channel("hello"); /// let mut rx = WatchStream::new(rx); /// /// tx.send("goodbye").unwrap(); /// assert_eq!(rx.next().await, Some("goodbye")); /// # } /// ``` /// /// [`tokio::sync::watch::Receiver`]: struct@tokio::sync::watch::Receiver /// [`Stream`]: trait@crate::Stream #[cfg_attr(docsrs, doc(cfg(feature = "sync")))] pub struct WatchStream { inner: ReusableBoxFuture<(Result<(), RecvError>, Receiver)>, } async fn make_future( mut rx: Receiver, ) -> (Result<(), RecvError>, Receiver) { let result = rx.changed().await; (result, rx) } impl WatchStream { /// Create a new `WatchStream`. pub fn new(rx: Receiver) -> Self { Self { inner: ReusableBoxFuture::new(async move { (Ok(()), rx) }), } } } impl Stream for WatchStream { type Item = T; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let (result, mut rx) = ready!(self.inner.poll(cx)); match result { Ok(_) => { let received = (*rx.borrow_and_update()).clone(); self.inner.set(make_future(rx)); Poll::Ready(Some(received)) } Err(_) => { self.inner.set(make_future(rx)); Poll::Ready(None) } } } } impl Unpin for WatchStream {} impl fmt::Debug for WatchStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("WatchStream").finish() } } impl From> for WatchStream { fn from(recv: Receiver) -> Self { Self::new(recv) } } tokio-stream-0.1.8/src/wrappers.rs000064400000000000000000000021750072674642500153050ustar 00000000000000//! Wrappers for Tokio types that implement `Stream`. /// Error types for the wrappers. pub mod errors { cfg_sync! { pub use crate::wrappers::broadcast::BroadcastStreamRecvError; } } mod mpsc_bounded; pub use mpsc_bounded::ReceiverStream; mod mpsc_unbounded; pub use mpsc_unbounded::UnboundedReceiverStream; cfg_sync! { mod broadcast; pub use broadcast::BroadcastStream; mod watch; pub use watch::WatchStream; } cfg_signal! { #[cfg(unix)] mod signal_unix; #[cfg(unix)] pub use signal_unix::SignalStream; #[cfg(any(windows, docsrs))] mod signal_windows; #[cfg(any(windows, docsrs))] pub use signal_windows::{CtrlCStream, CtrlBreakStream}; } cfg_time! { mod interval; pub use interval::IntervalStream; } cfg_net! { mod tcp_listener; pub use tcp_listener::TcpListenerStream; #[cfg(unix)] mod unix_listener; #[cfg(unix)] pub use unix_listener::UnixListenerStream; } cfg_io_util! { mod split; pub use split::SplitStream; mod lines; pub use lines::LinesStream; } cfg_fs! { mod read_dir; pub use read_dir::ReadDirStream; } tokio-stream-0.1.8/tests/async_send_sync.rs000064400000000000000000000072410072674642500171760ustar 00000000000000#![allow(clippy::diverging_sub_expression)] use std::rc::Rc; #[allow(dead_code)] type BoxStream = std::pin::Pin>>; #[allow(dead_code)] fn require_send(_t: &T) {} #[allow(dead_code)] fn require_sync(_t: &T) {} #[allow(dead_code)] fn require_unpin(_t: &T) {} #[allow(dead_code)] struct Invalid; trait AmbiguousIfSend { fn some_item(&self) {} } impl AmbiguousIfSend<()> for T {} impl AmbiguousIfSend for T {} trait AmbiguousIfSync { fn some_item(&self) {} } impl AmbiguousIfSync<()> for T {} impl AmbiguousIfSync for T {} trait AmbiguousIfUnpin { fn some_item(&self) {} } impl AmbiguousIfUnpin<()> for T {} impl AmbiguousIfUnpin for T {} macro_rules! into_todo { ($typ:ty) => {{ let x: $typ = todo!(); x }}; } macro_rules! async_assert_fn { ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): Send & Sync) => { #[allow(unreachable_code)] #[allow(unused_variables)] const _: fn() = || { let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); require_send(&f); require_sync(&f); }; }; ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): Send & !Sync) => { #[allow(unreachable_code)] #[allow(unused_variables)] const _: fn() = || { let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); require_send(&f); AmbiguousIfSync::some_item(&f); }; }; ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): !Send & Sync) => { #[allow(unreachable_code)] #[allow(unused_variables)] const _: fn() = || { let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); AmbiguousIfSend::some_item(&f); require_sync(&f); }; }; ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): !Send & !Sync) => { #[allow(unreachable_code)] #[allow(unused_variables)] const _: fn() = || { let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); AmbiguousIfSend::some_item(&f); AmbiguousIfSync::some_item(&f); }; }; ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): !Unpin) => { #[allow(unreachable_code)] #[allow(unused_variables)] const _: fn() = || { let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); AmbiguousIfUnpin::some_item(&f); }; }; ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): Unpin) => { #[allow(unreachable_code)] #[allow(unused_variables)] const _: fn() = || { let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); require_unpin(&f); }; }; } async_assert_fn!(tokio_stream::empty>(): Send & Sync); async_assert_fn!(tokio_stream::pending>(): Send & Sync); async_assert_fn!(tokio_stream::iter(std::vec::IntoIter): Send & Sync); async_assert_fn!(tokio_stream::StreamExt::next(&mut BoxStream<()>): !Unpin); async_assert_fn!(tokio_stream::StreamExt::try_next(&mut BoxStream>): !Unpin); async_assert_fn!(tokio_stream::StreamExt::all(&mut BoxStream<()>, fn(())->bool): !Unpin); async_assert_fn!(tokio_stream::StreamExt::any(&mut BoxStream<()>, fn(())->bool): !Unpin); async_assert_fn!(tokio_stream::StreamExt::fold(&mut BoxStream<()>, (), fn((), ())->()): !Unpin); async_assert_fn!(tokio_stream::StreamExt::collect>(&mut BoxStream<()>): !Unpin); tokio-stream-0.1.8/tests/stream_chain.rs000064400000000000000000000047510072674642500164540ustar 00000000000000use tokio_stream::{self as stream, Stream, StreamExt}; use tokio_test::{assert_pending, assert_ready, task}; mod support { pub(crate) mod mpsc; } use support::mpsc; #[tokio::test] async fn basic_usage() { let one = stream::iter(vec![1, 2, 3]); let two = stream::iter(vec![4, 5, 6]); let mut stream = one.chain(two); assert_eq!(stream.size_hint(), (6, Some(6))); assert_eq!(stream.next().await, Some(1)); assert_eq!(stream.size_hint(), (5, Some(5))); assert_eq!(stream.next().await, Some(2)); assert_eq!(stream.size_hint(), (4, Some(4))); assert_eq!(stream.next().await, Some(3)); assert_eq!(stream.size_hint(), (3, Some(3))); assert_eq!(stream.next().await, Some(4)); assert_eq!(stream.size_hint(), (2, Some(2))); assert_eq!(stream.next().await, Some(5)); assert_eq!(stream.size_hint(), (1, Some(1))); assert_eq!(stream.next().await, Some(6)); assert_eq!(stream.size_hint(), (0, Some(0))); assert_eq!(stream.next().await, None); assert_eq!(stream.size_hint(), (0, Some(0))); assert_eq!(stream.next().await, None); } #[tokio::test] async fn pending_first() { let (tx1, rx1) = mpsc::unbounded_channel_stream(); let (tx2, rx2) = mpsc::unbounded_channel_stream(); let mut stream = task::spawn(rx1.chain(rx2)); assert_eq!(stream.size_hint(), (0, None)); assert_pending!(stream.poll_next()); tx2.send(2).unwrap(); assert!(!stream.is_woken()); assert_pending!(stream.poll_next()); tx1.send(1).unwrap(); assert!(stream.is_woken()); assert_eq!(Some(1), assert_ready!(stream.poll_next())); assert_pending!(stream.poll_next()); drop(tx1); assert_eq!(stream.size_hint(), (0, None)); assert!(stream.is_woken()); assert_eq!(Some(2), assert_ready!(stream.poll_next())); assert_eq!(stream.size_hint(), (0, None)); drop(tx2); assert_eq!(stream.size_hint(), (0, None)); assert_eq!(None, assert_ready!(stream.poll_next())); } #[test] fn size_overflow() { struct Monster; impl tokio_stream::Stream for Monster { type Item = (); fn poll_next( self: std::pin::Pin<&mut Self>, _cx: &mut std::task::Context<'_>, ) -> std::task::Poll> { panic!() } fn size_hint(&self) -> (usize, Option) { (usize::MAX, Some(usize::MAX)) } } let m1 = Monster; let m2 = Monster; let m = m1.chain(m2); assert_eq!(m.size_hint(), (usize::MAX, None)); } tokio-stream-0.1.8/tests/stream_collect.rs000064400000000000000000000066510072674642500170200ustar 00000000000000use tokio_stream::{self as stream, StreamExt}; use tokio_test::{assert_pending, assert_ready, assert_ready_err, assert_ready_ok, task}; mod support { pub(crate) mod mpsc; } use support::mpsc; #[allow(clippy::let_unit_value)] #[tokio::test] async fn empty_unit() { // Drains the stream. let mut iter = vec![(), (), ()].into_iter(); let _: () = stream::iter(&mut iter).collect().await; assert!(iter.next().is_none()); } #[tokio::test] async fn empty_vec() { let coll: Vec = stream::empty().collect().await; assert!(coll.is_empty()); } #[tokio::test] async fn empty_box_slice() { let coll: Box<[u32]> = stream::empty().collect().await; assert!(coll.is_empty()); } #[tokio::test] async fn empty_string() { let coll: String = stream::empty::<&str>().collect().await; assert!(coll.is_empty()); } #[tokio::test] async fn empty_result() { let coll: Result, &str> = stream::empty().collect().await; assert_eq!(Ok(vec![]), coll); } #[tokio::test] async fn collect_vec_items() { let (tx, rx) = mpsc::unbounded_channel_stream(); let mut fut = task::spawn(rx.collect::>()); assert_pending!(fut.poll()); tx.send(1).unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); tx.send(2).unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); drop(tx); assert!(fut.is_woken()); let coll = assert_ready!(fut.poll()); assert_eq!(vec![1, 2], coll); } #[tokio::test] async fn collect_string_items() { let (tx, rx) = mpsc::unbounded_channel_stream(); let mut fut = task::spawn(rx.collect::()); assert_pending!(fut.poll()); tx.send("hello ".to_string()).unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); tx.send("world".to_string()).unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); drop(tx); assert!(fut.is_woken()); let coll = assert_ready!(fut.poll()); assert_eq!("hello world", coll); } #[tokio::test] async fn collect_str_items() { let (tx, rx) = mpsc::unbounded_channel_stream(); let mut fut = task::spawn(rx.collect::()); assert_pending!(fut.poll()); tx.send("hello ").unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); tx.send("world").unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); drop(tx); assert!(fut.is_woken()); let coll = assert_ready!(fut.poll()); assert_eq!("hello world", coll); } #[tokio::test] async fn collect_results_ok() { let (tx, rx) = mpsc::unbounded_channel_stream(); let mut fut = task::spawn(rx.collect::>()); assert_pending!(fut.poll()); tx.send(Ok("hello ")).unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); tx.send(Ok("world")).unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); drop(tx); assert!(fut.is_woken()); let coll = assert_ready_ok!(fut.poll()); assert_eq!("hello world", coll); } #[tokio::test] async fn collect_results_err() { let (tx, rx) = mpsc::unbounded_channel_stream(); let mut fut = task::spawn(rx.collect::>()); assert_pending!(fut.poll()); tx.send(Ok("hello ")).unwrap(); assert!(fut.is_woken()); assert_pending!(fut.poll()); tx.send(Err("oh no")).unwrap(); assert!(fut.is_woken()); let err = assert_ready_err!(fut.poll()); assert_eq!("oh no", err); } tokio-stream-0.1.8/tests/stream_empty.rs000064400000000000000000000004170072674642500165230ustar 00000000000000use tokio_stream::{self as stream, Stream, StreamExt}; #[tokio::test] async fn basic_usage() { let mut stream = stream::empty::(); for _ in 0..2 { assert_eq!(stream.size_hint(), (0, Some(0))); assert_eq!(None, stream.next().await); } } tokio-stream-0.1.8/tests/stream_fuse.rs000064400000000000000000000024360072674642500163320ustar 00000000000000use 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_eq!(stream.size_hint(), (0, None)); assert_eq!(stream.next().await, Some(4)); assert_eq!(stream.size_hint(), (0, None)); assert_eq!(stream.next().await, None); // 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))); } tokio-stream-0.1.8/tests/stream_iter.rs000064400000000000000000000005300072674642500163240ustar 00000000000000use tokio_stream as stream; use tokio_test::task; use std::iter; #[tokio::test] async fn coop() { let mut stream = task::spawn(stream::iter(iter::repeat(1))); for _ in 0..10_000 { if stream.poll_next().is_pending() { assert!(stream.is_woken()); return; } } panic!("did not yield"); } tokio-stream-0.1.8/tests/stream_merge.rs000064400000000000000000000036610072674642500164700ustar 00000000000000use tokio_stream::{self as stream, Stream, StreamExt}; use tokio_test::task; use tokio_test::{assert_pending, assert_ready}; mod support { pub(crate) mod mpsc; } use support::mpsc; #[tokio::test] async fn merge_sync_streams() { let mut s = stream::iter(vec![0, 2, 4, 6]).merge(stream::iter(vec![1, 3, 5])); for i in 0..7 { let rem = 7 - i; assert_eq!(s.size_hint(), (rem, Some(rem))); assert_eq!(Some(i), s.next().await); } assert!(s.next().await.is_none()); } #[tokio::test] async fn merge_async_streams() { let (tx1, rx1) = mpsc::unbounded_channel_stream(); let (tx2, rx2) = mpsc::unbounded_channel_stream(); let mut rx = task::spawn(rx1.merge(rx2)); assert_eq!(rx.size_hint(), (0, None)); assert_pending!(rx.poll_next()); tx1.send(1).unwrap(); assert!(rx.is_woken()); assert_eq!(Some(1), assert_ready!(rx.poll_next())); assert_pending!(rx.poll_next()); tx2.send(2).unwrap(); assert!(rx.is_woken()); assert_eq!(Some(2), assert_ready!(rx.poll_next())); assert_pending!(rx.poll_next()); drop(tx1); assert!(rx.is_woken()); assert_pending!(rx.poll_next()); tx2.send(3).unwrap(); assert!(rx.is_woken()); assert_eq!(Some(3), assert_ready!(rx.poll_next())); assert_pending!(rx.poll_next()); drop(tx2); assert!(rx.is_woken()); assert_eq!(None, assert_ready!(rx.poll_next())); } #[test] fn size_overflow() { struct Monster; impl tokio_stream::Stream for Monster { type Item = (); fn poll_next( self: std::pin::Pin<&mut Self>, _cx: &mut std::task::Context<'_>, ) -> std::task::Poll> { panic!() } fn size_hint(&self) -> (usize, Option) { (usize::MAX, Some(usize::MAX)) } } let m1 = Monster; let m2 = Monster; let m = m1.merge(m2); assert_eq!(m.size_hint(), (usize::MAX, None)); } tokio-stream-0.1.8/tests/stream_once.rs000064400000000000000000000004700072674642500163100ustar 00000000000000use tokio_stream::{self as stream, Stream, StreamExt}; #[tokio::test] async fn basic_usage() { let mut one = stream::once(1); assert_eq!(one.size_hint(), (1, Some(1))); assert_eq!(Some(1), one.next().await); assert_eq!(one.size_hint(), (0, Some(0))); assert_eq!(None, one.next().await); } tokio-stream-0.1.8/tests/stream_pending.rs000064400000000000000000000005610072674642500170110ustar 00000000000000use tokio_stream::{self as stream, Stream, StreamExt}; use tokio_test::{assert_pending, task}; #[tokio::test] async fn basic_usage() { let mut stream = stream::pending::(); for _ in 0..2 { assert_eq!(stream.size_hint(), (0, None)); let mut next = task::spawn(async { stream.next().await }); assert_pending!(next.poll()); } } tokio-stream-0.1.8/tests/stream_stream_map.rs000064400000000000000000000220260072674642500175150ustar 00000000000000use tokio_stream::{self as stream, pending, Stream, StreamExt, StreamMap}; use tokio_test::{assert_ok, assert_pending, assert_ready, task}; mod support { pub(crate) mod mpsc; } use support::mpsc; use std::pin::Pin; macro_rules! assert_ready_some { ($($t:tt)*) => { match assert_ready!($($t)*) { Some(v) => v, None => panic!("expected `Some`, got `None`"), } }; } macro_rules! assert_ready_none { ($($t:tt)*) => { match assert_ready!($($t)*) { None => {} Some(v) => panic!("expected `None`, got `Some({:?})`", v), } }; } #[tokio::test] async fn empty() { let mut map = StreamMap::<&str, stream::Pending<()>>::new(); assert_eq!(map.len(), 0); assert!(map.is_empty()); assert!(map.next().await.is_none()); assert!(map.next().await.is_none()); assert!(map.remove("foo").is_none()); } #[tokio::test] async fn single_entry() { let mut map = task::spawn(StreamMap::new()); let (tx, rx) = mpsc::unbounded_channel_stream(); let rx = Box::pin(rx); assert_ready_none!(map.poll_next()); assert!(map.insert("foo", rx).is_none()); assert!(map.contains_key("foo")); assert!(!map.contains_key("bar")); assert_eq!(map.len(), 1); assert!(!map.is_empty()); assert_pending!(map.poll_next()); assert_ok!(tx.send(1)); assert!(map.is_woken()); let (k, v) = assert_ready_some!(map.poll_next()); assert_eq!(k, "foo"); assert_eq!(v, 1); assert_pending!(map.poll_next()); assert_ok!(tx.send(2)); assert!(map.is_woken()); let (k, v) = assert_ready_some!(map.poll_next()); assert_eq!(k, "foo"); assert_eq!(v, 2); assert_pending!(map.poll_next()); drop(tx); assert!(map.is_woken()); assert_ready_none!(map.poll_next()); } #[tokio::test] async fn multiple_entries() { let mut map = task::spawn(StreamMap::new()); let (tx1, rx1) = mpsc::unbounded_channel_stream(); let (tx2, rx2) = mpsc::unbounded_channel_stream(); let rx1 = Box::pin(rx1); let rx2 = Box::pin(rx2); map.insert("foo", rx1); map.insert("bar", rx2); assert_pending!(map.poll_next()); assert_ok!(tx1.send(1)); assert!(map.is_woken()); let (k, v) = assert_ready_some!(map.poll_next()); assert_eq!(k, "foo"); assert_eq!(v, 1); assert_pending!(map.poll_next()); assert_ok!(tx2.send(2)); assert!(map.is_woken()); let (k, v) = assert_ready_some!(map.poll_next()); assert_eq!(k, "bar"); assert_eq!(v, 2); assert_pending!(map.poll_next()); assert_ok!(tx1.send(3)); assert_ok!(tx2.send(4)); assert!(map.is_woken()); // Given the randomization, there is no guarantee what order the values will // be received in. let mut v = (0..2) .map(|_| assert_ready_some!(map.poll_next())) .collect::>(); assert_pending!(map.poll_next()); v.sort_unstable(); assert_eq!(v[0].0, "bar"); assert_eq!(v[0].1, 4); assert_eq!(v[1].0, "foo"); assert_eq!(v[1].1, 3); drop(tx1); assert!(map.is_woken()); assert_pending!(map.poll_next()); drop(tx2); assert_ready_none!(map.poll_next()); } #[tokio::test] async fn insert_remove() { let mut map = task::spawn(StreamMap::new()); let (tx, rx) = mpsc::unbounded_channel_stream(); let rx = Box::pin(rx); assert_ready_none!(map.poll_next()); assert!(map.insert("foo", rx).is_none()); let rx = map.remove("foo").unwrap(); assert_ok!(tx.send(1)); assert!(!map.is_woken()); assert_ready_none!(map.poll_next()); assert!(map.insert("bar", rx).is_none()); let v = assert_ready_some!(map.poll_next()); assert_eq!(v.0, "bar"); assert_eq!(v.1, 1); assert!(map.remove("bar").is_some()); assert_ready_none!(map.poll_next()); assert!(map.is_empty()); assert_eq!(0, map.len()); } #[tokio::test] async fn replace() { let mut map = task::spawn(StreamMap::new()); let (tx1, rx1) = mpsc::unbounded_channel_stream(); let (tx2, rx2) = mpsc::unbounded_channel_stream(); let rx1 = Box::pin(rx1); let rx2 = Box::pin(rx2); assert!(map.insert("foo", rx1).is_none()); assert_pending!(map.poll_next()); let _rx1 = map.insert("foo", rx2).unwrap(); assert_pending!(map.poll_next()); tx1.send(1).unwrap(); assert_pending!(map.poll_next()); tx2.send(2).unwrap(); assert!(map.is_woken()); let v = assert_ready_some!(map.poll_next()); assert_eq!(v.0, "foo"); assert_eq!(v.1, 2); } #[test] fn size_hint_with_upper() { let mut map = StreamMap::new(); map.insert("a", stream::iter(vec![1])); map.insert("b", stream::iter(vec![1, 2])); map.insert("c", stream::iter(vec![1, 2, 3])); assert_eq!(3, map.len()); assert!(!map.is_empty()); let size_hint = map.size_hint(); assert_eq!(size_hint, (6, Some(6))); } #[test] fn size_hint_without_upper() { let mut map = StreamMap::new(); map.insert("a", pin_box(stream::iter(vec![1]))); map.insert("b", pin_box(stream::iter(vec![1, 2]))); map.insert("c", pin_box(pending())); let size_hint = map.size_hint(); assert_eq!(size_hint, (3, None)); } #[test] fn new_capacity_zero() { let map = StreamMap::<&str, stream::Pending<()>>::new(); assert_eq!(0, map.capacity()); assert!(map.keys().next().is_none()); } #[test] fn with_capacity() { let map = StreamMap::<&str, stream::Pending<()>>::with_capacity(10); assert!(10 <= map.capacity()); assert!(map.keys().next().is_none()); } #[test] fn iter_keys() { let mut map = StreamMap::new(); map.insert("a", pending::()); map.insert("b", pending()); map.insert("c", pending()); let mut keys = map.keys().collect::>(); keys.sort_unstable(); assert_eq!(&keys[..], &[&"a", &"b", &"c"]); } #[test] fn iter_values() { let mut map = StreamMap::new(); map.insert("a", stream::iter(vec![1])); map.insert("b", stream::iter(vec![1, 2])); map.insert("c", stream::iter(vec![1, 2, 3])); let mut size_hints = map.values().map(|s| s.size_hint().0).collect::>(); size_hints.sort_unstable(); assert_eq!(&size_hints[..], &[1, 2, 3]); } #[test] fn iter_values_mut() { let mut map = StreamMap::new(); map.insert("a", stream::iter(vec![1])); map.insert("b", stream::iter(vec![1, 2])); map.insert("c", stream::iter(vec![1, 2, 3])); let mut size_hints = map .values_mut() .map(|s: &mut _| s.size_hint().0) .collect::>(); size_hints.sort_unstable(); assert_eq!(&size_hints[..], &[1, 2, 3]); } #[test] fn clear() { let mut map = task::spawn(StreamMap::new()); map.insert("a", stream::iter(vec![1])); map.insert("b", stream::iter(vec![1, 2])); map.insert("c", stream::iter(vec![1, 2, 3])); assert_ready_some!(map.poll_next()); map.clear(); assert_ready_none!(map.poll_next()); assert!(map.is_empty()); } #[test] fn contains_key_borrow() { let mut map = StreamMap::new(); map.insert("foo".to_string(), pending::<()>()); assert!(map.contains_key("foo")); } #[test] fn one_ready_many_none() { // Run a few times because of randomness for _ in 0..100 { let mut map = task::spawn(StreamMap::new()); map.insert(0, pin_box(stream::empty())); map.insert(1, pin_box(stream::empty())); map.insert(2, pin_box(stream::once("hello"))); map.insert(3, pin_box(stream::pending())); let v = assert_ready_some!(map.poll_next()); assert_eq!(v, (2, "hello")); } } proptest::proptest! { #[test] fn fuzz_pending_complete_mix(kinds: Vec) { use std::task::{Context, Poll}; struct DidPoll { did_poll: bool, inner: T, } impl Stream for DidPoll { type Item = T::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.did_poll = true; Pin::new(&mut self.inner).poll_next(cx) } } for _ in 0..10 { let mut map = task::spawn(StreamMap::new()); let mut expect = 0; for (i, &is_empty) in kinds.iter().enumerate() { let inner = if is_empty { pin_box(stream::empty::<()>()) } else { expect += 1; pin_box(stream::pending::<()>()) }; let stream = DidPoll { did_poll: false, inner, }; map.insert(i, stream); } if expect == 0 { assert_ready_none!(map.poll_next()); } else { assert_pending!(map.poll_next()); assert_eq!(expect, map.values().count()); for stream in map.values() { assert!(stream.did_poll); } } } } } fn pin_box + 'static, U>(s: T) -> Pin>> { Box::pin(s) } tokio-stream-0.1.8/tests/stream_timeout.rs000064400000000000000000000057050072674642500170600ustar 00000000000000#![cfg(feature = "full")] use tokio::time::{self, sleep, Duration}; use tokio_stream::{self, StreamExt}; use tokio_test::*; use futures::StreamExt as _; async fn maybe_sleep(idx: i32) -> i32 { if idx % 2 == 0 { sleep(ms(200)).await; } idx } fn ms(n: u64) -> Duration { Duration::from_millis(n) } #[tokio::test] async fn basic_usage() { time::pause(); // Items 2 and 4 time out. If we run the stream until it completes, // we end up with the following items: // // [Ok(1), Err(Elapsed), Ok(2), Ok(3), Err(Elapsed), Ok(4)] let stream = stream::iter(1..=4).then(maybe_sleep).timeout(ms(100)); let mut stream = task::spawn(stream); // First item completes immediately assert_ready_eq!(stream.poll_next(), Some(Ok(1))); // Second item is delayed 200ms, times out after 100ms assert_pending!(stream.poll_next()); time::advance(ms(150)).await; let v = assert_ready!(stream.poll_next()); assert!(v.unwrap().is_err()); assert_pending!(stream.poll_next()); time::advance(ms(100)).await; assert_ready_eq!(stream.poll_next(), Some(Ok(2))); // Third item is ready immediately assert_ready_eq!(stream.poll_next(), Some(Ok(3))); // Fourth item is delayed 200ms, times out after 100ms assert_pending!(stream.poll_next()); time::advance(ms(60)).await; assert_pending!(stream.poll_next()); // nothing ready yet time::advance(ms(60)).await; let v = assert_ready!(stream.poll_next()); assert!(v.unwrap().is_err()); // timeout! time::advance(ms(120)).await; assert_ready_eq!(stream.poll_next(), Some(Ok(4))); // Done. assert_ready_eq!(stream.poll_next(), None); } #[tokio::test] async fn return_elapsed_errors_only_once() { time::pause(); let stream = stream::iter(1..=3).then(maybe_sleep).timeout(ms(50)); let mut stream = task::spawn(stream); // First item completes immediately assert_ready_eq!(stream.poll_next(), Some(Ok(1))); // Second item is delayed 200ms, times out after 50ms. Only one `Elapsed` // error is returned. assert_pending!(stream.poll_next()); // time::advance(ms(51)).await; let v = assert_ready!(stream.poll_next()); assert!(v.unwrap().is_err()); // timeout! // deadline elapses again, but no error is returned time::advance(ms(50)).await; assert_pending!(stream.poll_next()); time::advance(ms(100)).await; assert_ready_eq!(stream.poll_next(), Some(Ok(2))); assert_ready_eq!(stream.poll_next(), Some(Ok(3))); // Done assert_ready_eq!(stream.poll_next(), None); } #[tokio::test] async fn no_timeouts() { let stream = stream::iter(vec![1, 3, 5]) .then(maybe_sleep) .timeout(ms(100)); let mut stream = task::spawn(stream); assert_ready_eq!(stream.poll_next(), Some(Ok(1))); assert_ready_eq!(stream.poll_next(), Some(Ok(3))); assert_ready_eq!(stream.poll_next(), Some(Ok(5))); assert_ready_eq!(stream.poll_next(), None); } tokio-stream-0.1.8/tests/support/mpsc.rs000064400000000000000000000005760072674642500164760ustar 00000000000000use async_stream::stream; use tokio::sync::mpsc::{self, UnboundedSender}; use tokio_stream::Stream; pub fn unbounded_channel_stream() -> (UnboundedSender, impl Stream) { let (tx, mut rx) = mpsc::unbounded_channel(); let stream = stream! { while let Some(item) = rx.recv().await { yield item; } }; (tx, stream) } tokio-stream-0.1.8/tests/time_throttle.rs000064400000000000000000000011350072674642500166730ustar 00000000000000#![warn(rust_2018_idioms)] #![cfg(feature = "full")] use tokio::time; use tokio_stream::StreamExt; use tokio_test::*; use std::time::Duration; #[tokio::test] async fn usage() { time::pause(); let mut stream = task::spawn(futures::stream::repeat(()).throttle(Duration::from_millis(100))); assert_ready!(stream.poll_next()); assert_pending!(stream.poll_next()); time::advance(Duration::from_millis(90)).await; assert_pending!(stream.poll_next()); time::advance(Duration::from_millis(101)).await; assert!(stream.is_woken()); assert_ready!(stream.poll_next()); } tokio-stream-0.1.8/tests/watch.rs000064400000000000000000000012500072674642500151140ustar 00000000000000#![cfg(feature = "sync")] use tokio::sync::watch; use tokio_stream::wrappers::WatchStream; use tokio_stream::StreamExt; #[tokio::test] async fn message_not_twice() { let (tx, rx) = watch::channel("hello"); let mut counter = 0; let mut stream = WatchStream::new(rx).map(move |payload| { println!("{}", payload); if payload == "goodbye" { counter += 1; } if counter >= 2 { panic!("too many goodbyes"); } }); let task = tokio::spawn(async move { while stream.next().await.is_some() {} }); // Send goodbye just once tx.send("goodbye").unwrap(); drop(tx); task.await.unwrap(); }