├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── benches ├── future.rs └── stream.rs ├── examples ├── future.rs └── stream.rs └── src ├── future.rs ├── lib.rs └── stream.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: build 19 | run: cargo build --tests --examples --benches --verbose 20 | - name: test 21 | run: cargo test --verbose 22 | 23 | clippy: 24 | name: clippy 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@v2 28 | - run: rustup component add clippy 29 | - uses: actions-rs/cargo@v1 30 | with: 31 | command: clippy 32 | args: --all --lib --tests --examples -- --deny warnings 33 | 34 | coverage: 35 | name: coverage 36 | runs-on: ubuntu-latest 37 | steps: 38 | - uses: actions/checkout@v2 39 | - name: run cargo-tarpaulin 40 | uses: actions-rs/tarpaulin@v0.1 41 | with: 42 | version: '0.15.0' 43 | args: '-- --test-threads 1' 44 | 45 | - name: upload to codecov.io 46 | uses: codecov/codecov-action@v1.0.2 47 | with: 48 | token: ${{secrets.CODECOV_TOKEN}} 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-async-combinators" 3 | version = "0.3.2" 4 | authors = ["Roman Proskuryakov "] 5 | description = "toy futures combinators" 6 | license = "MIT" 7 | readme = "README.md" 8 | homepage = "https://github.com/kpp/futures-async-combinators" 9 | repository = "https://github.com/kpp/futures-async-combinators" 10 | keywords = ["async", "await", "futures"] 11 | edition = "2018" 12 | 13 | [badges] 14 | # Available options are `actively-developed`, `passively-maintained`, 15 | # `as-is`, `none`, `experimental`, `looking-for-maintainer`, `deprecated`. 16 | maintenance = { status = "experimental" } 17 | 18 | [dependencies] 19 | pin-utils = "0.1.0" 20 | futures-core = "0.3" 21 | 22 | [dev-dependencies] 23 | futures = "0.3" 24 | criterion = "0.3" 25 | 26 | [[bench]] 27 | name = "stream" 28 | harness = false 29 | 30 | [[bench]] 31 | name = "future" 32 | harness = false 33 | 34 | [profile.bench] 35 | opt-level = 3 36 | debug = false 37 | lto = true 38 | debug-assertions = false 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE.NGS IN THE SOFTWARE. 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # futures-async-combinators 2 | 3 | [![Build Status][ci-badge]][ci-url] 4 | [![Coverage Status][cov-badge]][cov-url] 5 | [![Docs][doc-badge]][doc-url] 6 | 7 | [ci-badge]: https://github.com/kpp/futures-async-combinators/workflows/CI/badge.svg?branch=master 8 | [ci-url]: https://github.com/kpp/futures-async-combinators/actions 9 | [cov-badge]: https://codecov.io/gh/kpp/futures-async-combinators/branch/master/graph/badge.svg?token=X29P76ICLS 10 | [cov-url]: https://codecov.io/gh/kpp/futures-async-combinators 11 | [doc-badge]: https://docs.rs/futures-async-combinators/badge.svg 12 | [doc-url]: https://docs.rs/futures-async-combinators 13 | 14 | FOR LEARNING PURPOSES ONLY 15 | 16 | This is a greatly simplified implementation of [Future combinators](https://docs.rs/futures/0.3.8/futures/) 17 | like `FutureExt::map`, `TryFutureExt::and_then`... 18 | 19 | # Requirements 20 | 21 | Rust 1.39.0 for async/await. 22 | 23 | # State 24 | 25 | Future 26 | 27 | - [x] future::and_then 28 | - [x] future::err_into 29 | - [x] future::flatten 30 | - [x] future::flatten_stream 31 | - [x] future::inspect 32 | - [x] future::into_stream 33 | - [x] future::map 34 | - [x] future::map_err 35 | - [x] future::map_ok 36 | - [x] future::or_else 37 | - [x] future::poll_fn 38 | - [x] future::ready 39 | - [x] future::then 40 | - [x] future::unwrap_or_else 41 | 42 | Stream 43 | 44 | - [x] stream::chain 45 | - [x] stream::collect 46 | - [x] stream::concat 47 | - [x] stream::filter 48 | - [x] stream::filter_map 49 | - [x] stream::flatten 50 | - [x] stream::fold 51 | - [x] stream::for_each 52 | - [x] stream::inspect 53 | - [x] stream::into_future 54 | - [x] stream::iter 55 | - [x] stream::map 56 | - [x] stream::next 57 | - [x] stream::once 58 | - [x] stream::poll_fn 59 | - [x] stream::repeat 60 | - [x] stream::skip 61 | - [x] stream::skip_while 62 | - [x] stream::take 63 | - [x] stream::take_while 64 | - [x] stream::then 65 | - [x] stream::unfold 66 | - [x] stream::zip 67 | 68 | 69 | # Why 70 | 71 | To understand how combinators work by looking at clean source code. Compare: 72 | 73 | ```rust 74 | pub async fn then<...>(future, f) -> ... 75 | { 76 | let new_future = f(future.await); 77 | new_future.await 78 | } 79 | ``` 80 | 81 | with original 82 | 83 | ```rust 84 | impl Then 85 | { 86 | fn poll(self, waker) -> Poll<...> { 87 | self.as_mut().chain().poll(waker, |output, f| f(output)) 88 | } 89 | } 90 | 91 | impl Chain 92 | { 93 | fn poll(self, waker, f) -> Poll<...> 94 | { 95 | let mut f = Some(f); 96 | 97 | // Safe to call `get_unchecked_mut` because we won't move the futures. 98 | let this = unsafe { Pin::get_unchecked_mut(self) }; 99 | 100 | loop { 101 | let (output, data) = match this { 102 | Chain::First(fut1, data) => { 103 | match unsafe { Pin::new_unchecked(fut1) }.poll(waker) { 104 | Poll::Pending => return Poll::Pending, 105 | Poll::Ready(output) => (output, data.take().unwrap()), 106 | } 107 | } 108 | Chain::Second(fut2) => { 109 | return unsafe { Pin::new_unchecked(fut2) }.poll(waker); 110 | } 111 | Chain::Empty => unreachable!() 112 | }; 113 | 114 | *this = Chain::Empty; // Drop fut1 115 | let fut2 = (f.take().unwrap())(output, data); 116 | *this = Chain::Second(fut2) 117 | } 118 | } 119 | } 120 | ``` 121 | -------------------------------------------------------------------------------- /benches/future.rs: -------------------------------------------------------------------------------- 1 | use criterion::*; 2 | use futures::executor; 3 | 4 | fn bench_ready(c: &mut Criterion) { 5 | let mut group = c.benchmark_group("future::ready"); 6 | 7 | group.bench_function("futures", |b| { 8 | b.iter(|| { 9 | executor::block_on(async { 10 | black_box(futures::future::ready(42).await); 11 | }) 12 | }) 13 | }); 14 | group.bench_function("async_combinators", |b| { 15 | b.iter(|| { 16 | executor::block_on(async { 17 | black_box(futures_async_combinators::future::ready(42).await); 18 | }) 19 | }) 20 | }); 21 | 22 | group.finish(); 23 | } 24 | 25 | fn bench_poll_fn(c: &mut Criterion) { 26 | use core::task::{Context, Poll}; 27 | 28 | fn ret_42(_cx: &mut Context<'_>) -> Poll { 29 | Poll::Ready(42) 30 | } 31 | 32 | let mut group = c.benchmark_group("future::poll_fn"); 33 | 34 | group.bench_function("futures", |b| { 35 | b.iter(|| { 36 | executor::block_on(async { 37 | black_box(futures::future::poll_fn(ret_42).await); 38 | }) 39 | }) 40 | }); 41 | group.bench_function("async_combinators", |b| { 42 | b.iter(|| { 43 | executor::block_on(async { 44 | black_box(futures_async_combinators::future::poll_fn(ret_42)).await; 45 | }) 46 | }) 47 | }); 48 | 49 | group.finish(); 50 | } 51 | 52 | fn bench_map(c: &mut Criterion) { 53 | let mut group = c.benchmark_group("future::map"); 54 | 55 | group.bench_function("futures", |b| { 56 | b.iter(|| { 57 | executor::block_on(async { 58 | use futures::future::*; 59 | let fut = ready(40); 60 | let fut = fut.map(|x| x + 2); 61 | black_box(fut.await); 62 | }) 63 | }) 64 | }); 65 | group.bench_function("async_combinators", |b| { 66 | b.iter(|| { 67 | executor::block_on(async { 68 | use futures_async_combinators::future::*; 69 | let fut = ready(40); 70 | let fut = map(fut, |x| x + 2); 71 | black_box(fut.await); 72 | }) 73 | }) 74 | }); 75 | 76 | group.finish(); 77 | } 78 | 79 | criterion_group!(benches, bench_ready, bench_poll_fn, bench_map); 80 | criterion_main!(benches); 81 | -------------------------------------------------------------------------------- /benches/stream.rs: -------------------------------------------------------------------------------- 1 | use criterion::*; 2 | use futures::executor; 3 | 4 | fn bench_stream_iter(c: &mut Criterion) { 5 | let mut group = c.benchmark_group("stream::iter"); 6 | 7 | group.bench_function("futures", |b| { 8 | b.iter(|| { 9 | executor::block_on(async { 10 | use futures::stream::{iter, StreamExt}; 11 | let mut stream = iter(1..=1000); 12 | while let Some(item) = stream.next().await { 13 | black_box(item); 14 | } 15 | }) 16 | }) 17 | }); 18 | group.bench_function("async_combinators", |b| { 19 | b.iter(|| { 20 | executor::block_on(async { 21 | use futures::stream::StreamExt; 22 | use futures_async_combinators::stream::iter; 23 | let mut stream = iter(1..=1000); 24 | while let Some(item) = stream.next().await { 25 | black_box(item); 26 | } 27 | }) 28 | }) 29 | }); 30 | 31 | group.finish(); 32 | } 33 | 34 | fn bench_stream_next(c: &mut Criterion) { 35 | let mut group = c.benchmark_group("stream::next"); 36 | 37 | group.bench_function("futures", |b| { 38 | b.iter(|| { 39 | executor::block_on(async { 40 | use futures::stream::{iter, StreamExt}; 41 | let mut stream = iter(1..=1000); 42 | while let Some(item) = stream.next().await { 43 | black_box(item); 44 | } 45 | }) 46 | }) 47 | }); 48 | group.bench_function("async_combinators", |b| { 49 | b.iter(|| { 50 | executor::block_on(async { 51 | use futures::stream::iter; 52 | use futures_async_combinators::stream::next; 53 | let mut stream = iter(1..=1000); 54 | while let Some(item) = next(&mut stream).await { 55 | black_box(item); 56 | } 57 | }) 58 | }) 59 | }); 60 | 61 | group.finish(); 62 | } 63 | 64 | fn bench_stream_collect(c: &mut Criterion) { 65 | let mut group = c.benchmark_group("stream::collect"); 66 | 67 | group.bench_function("futures", |b| { 68 | b.iter(|| { 69 | executor::block_on(async { 70 | use futures::stream::{iter, StreamExt}; 71 | let stream = iter(1..=1000); 72 | let vec: Vec<_> = stream.collect().await; 73 | black_box(vec); 74 | }) 75 | }) 76 | }); 77 | group.bench_function("async_combinators", |b| { 78 | b.iter(|| { 79 | executor::block_on(async { 80 | use futures::stream::iter; 81 | use futures_async_combinators::stream::collect; 82 | let stream = iter(1..=1000); 83 | let vec: Vec<_> = collect(stream).await; 84 | black_box(vec); 85 | }) 86 | }) 87 | }); 88 | 89 | group.finish(); 90 | } 91 | 92 | fn bench_stream_map(c: &mut Criterion) { 93 | let mut group = c.benchmark_group("stream::map"); 94 | 95 | group.bench_function("futures", |b| { 96 | b.iter(|| { 97 | executor::block_on(async { 98 | use futures::stream::{iter, StreamExt}; 99 | let stream = iter(1..=1000); 100 | let stream = stream.map(|x| x + 42); 101 | let vec: Vec<_> = stream.collect().await; 102 | black_box(vec); 103 | }) 104 | }) 105 | }); 106 | group.bench_function("async_combinators", |b| { 107 | b.iter(|| { 108 | executor::block_on(async { 109 | use futures::stream::{iter, StreamExt}; 110 | use futures_async_combinators::stream::map; 111 | let stream = iter(1..=1000); 112 | let stream = map(stream, |x| x + 42); 113 | let vec: Vec<_> = stream.collect().await; 114 | black_box(vec); 115 | }) 116 | }) 117 | }); 118 | 119 | group.finish(); 120 | } 121 | 122 | fn bench_stream_fold(c: &mut Criterion) { 123 | let mut group = c.benchmark_group("stream::fold"); 124 | 125 | group.bench_function("futures", |b| { 126 | b.iter(|| { 127 | executor::block_on(async { 128 | use futures::stream::{iter, StreamExt}; 129 | use futures_async_combinators::future::ready; 130 | let stream = iter(1..=1000); 131 | let acc = stream.fold(0, |acc, x| ready(acc + x)); 132 | black_box(acc).await; 133 | }) 134 | }) 135 | }); 136 | group.bench_function("async_combinators", |b| { 137 | b.iter(|| { 138 | executor::block_on(async { 139 | use futures::stream::iter; 140 | use futures_async_combinators::future::ready; 141 | use futures_async_combinators::stream::fold; 142 | let stream = iter(1..=1000); 143 | let acc = fold(stream, 0, |acc, x| ready(acc + x)); 144 | black_box(acc).await; 145 | }) 146 | }) 147 | }); 148 | 149 | group.finish(); 150 | } 151 | 152 | criterion_group!( 153 | benches, 154 | bench_stream_iter, 155 | bench_stream_next, 156 | bench_stream_collect, 157 | bench_stream_map, 158 | bench_stream_fold, 159 | ); 160 | criterion_main!(benches); 161 | -------------------------------------------------------------------------------- /examples/future.rs: -------------------------------------------------------------------------------- 1 | use futures::executor; 2 | use futures_async_combinators::future::*; 3 | 4 | fn main() { 5 | let future = ready(Ok::(1)); 6 | let future = and_then(future, |x| ready(Ok::(x + 3))); 7 | let future = inspect(future, |x| { 8 | dbg!(x); 9 | }); 10 | 11 | let res = executor::block_on(future); 12 | assert_eq!(res, Ok(4)); 13 | } 14 | -------------------------------------------------------------------------------- /examples/stream.rs: -------------------------------------------------------------------------------- 1 | use futures::executor; 2 | use futures_async_combinators::stream::*; 3 | 4 | fn main() { 5 | let stream = iter(1..=3); 6 | let stream = map(stream, |x| x + 1); 7 | let stream = map(stream, |x| x * 2); 8 | let stream = inspect(stream, |x| { 9 | dbg!(x); 10 | }); 11 | 12 | let collect_future = collect(stream); 13 | let collection: Vec<_> = executor::block_on(collect_future); 14 | 15 | assert_eq!(vec![4, 6, 8], collection); 16 | } 17 | -------------------------------------------------------------------------------- /src/future.rs: -------------------------------------------------------------------------------- 1 | use futures_core::future::Future; 2 | use futures_core::stream::Stream; 3 | 4 | use core::pin::Pin; 5 | use core::task::{Context, Poll}; 6 | 7 | /// Create a future that is immediately ready with a value. 8 | /// 9 | /// # Examples 10 | /// 11 | /// ``` 12 | /// # futures::executor::block_on(async { 13 | /// use futures_async_combinators::future; 14 | /// 15 | /// let a = future::ready(1); 16 | /// assert_eq!(a.await, 1); 17 | /// # }); 18 | /// ``` 19 | pub async fn ready(value: T) -> T { 20 | value 21 | } 22 | 23 | /// Map this future's output to a different type, returning a new future of 24 | /// the resulting type. 25 | /// 26 | /// This function is similar to the `Option::map` or `Iterator::map` where 27 | /// it will change the type of the underlying future. This is useful to 28 | /// chain along a computation once a future has been resolved. 29 | /// 30 | /// Note that this function consumes the receiving future and returns a 31 | /// wrapped version of it, similar to the existing `map` methods in the 32 | /// standard library. 33 | /// 34 | /// # Examples 35 | /// 36 | /// ``` 37 | /// # futures::executor::block_on(async { 38 | /// use futures_async_combinators::future::{ready, map}; 39 | /// 40 | /// let future = ready(1); 41 | /// let new_future = map(future, |x| x + 3); 42 | /// assert_eq!(new_future.await, 4); 43 | /// # }); 44 | /// ``` 45 | pub async fn map(future: Fut, f: F) -> U 46 | where 47 | F: FnOnce(Fut::Output) -> U, 48 | Fut: Future, 49 | { 50 | f(future.await) 51 | } 52 | 53 | /// Chain on a computation for when a future finished, passing the result of 54 | /// the future to the provided closure `f`. 55 | /// 56 | /// The returned value of the closure must implement the `Future` trait 57 | /// and can represent some more work to be done before the composed future 58 | /// is finished. 59 | /// 60 | /// The closure `f` is only run *after* successful completion of the `self` 61 | /// future. 62 | /// 63 | /// Note that this function consumes the receiving future and returns a 64 | /// wrapped version of it. 65 | /// 66 | /// # Examples 67 | /// 68 | /// ``` 69 | /// # futures::executor::block_on(async { 70 | /// use futures_async_combinators::future::{ready, then}; 71 | /// 72 | /// let future_of_1 = ready(1); 73 | /// let future_of_4 = then(future_of_1, |x| ready(x + 3)); 74 | /// assert_eq!(future_of_4.await, 4); 75 | /// # }); 76 | /// ``` 77 | pub async fn then(future: FutA, f: F) -> FutB::Output 78 | where 79 | F: FnOnce(FutA::Output) -> FutB, 80 | FutA: Future, 81 | FutB: Future, 82 | { 83 | let new_future = f(future.await); 84 | new_future.await 85 | } 86 | 87 | /// Executes another future after this one resolves successfully. The 88 | /// success value is passed to a closure to create this subsequent future. 89 | /// 90 | /// The provided closure `f` will only be called if this future is resolved 91 | /// to an [`Ok`]. If this future resolves to an [`Err`], panics, or is 92 | /// dropped, then the provided closure will never be invoked. The 93 | /// `Error` type of this future and the future 94 | /// returned by `f` have to match. 95 | /// 96 | /// Note that this method consumes the future it is called on and returns a 97 | /// wrapped version of it. 98 | /// 99 | /// # Examples 100 | /// 101 | /// ``` 102 | /// use futures_async_combinators::future::{ready, and_then}; 103 | /// 104 | /// # futures::executor::block_on(async { 105 | /// let future = ready(Ok::(1)); 106 | /// let future = and_then(future, |x| ready(Ok::(x + 3))); 107 | /// assert_eq!(future.await, Ok(4)); 108 | /// # }); 109 | /// ``` 110 | /// 111 | /// Calling [`and_then`] on an errored future has no 112 | /// effect: 113 | /// 114 | /// ``` 115 | /// use futures_async_combinators::future::{ready, and_then}; 116 | /// 117 | /// # futures::executor::block_on(async { 118 | /// let future = ready(Err::(1)); 119 | /// let future = and_then(future, |x| ready(Err::(x + 3))); 120 | /// assert_eq!(future.await, Err(1)); 121 | /// # }); 122 | /// ``` 123 | pub async fn and_then(future: FutA, f: F) -> Result 124 | where 125 | F: FnOnce(T) -> FutB, 126 | FutA: Future>, 127 | FutB: Future>, 128 | { 129 | match future.await { 130 | Ok(ok) => { 131 | let new_future = f(ok); 132 | new_future.await 133 | } 134 | Err(err) => Err(err), 135 | } 136 | } 137 | 138 | /// Executes another future if this one resolves to an error. The 139 | /// error value is passed to a closure to create this subsequent future. 140 | /// 141 | /// The provided closure `f` will only be called if this future is resolved 142 | /// to an [`Err`]. If this future resolves to an [`Ok`], panics, or is 143 | /// dropped, then the provided closure will never be invoked. The 144 | /// `Ok` type of this future and the future returned by `f` 145 | /// have to match. 146 | /// 147 | /// Note that this method consumes the future it is called on and returns a 148 | /// wrapped version of it. 149 | /// 150 | /// # Examples 151 | /// 152 | /// ``` 153 | /// use futures_async_combinators::future::{ready, or_else}; 154 | /// 155 | /// # futures::executor::block_on(async { 156 | /// let future = ready(Err::(1)); 157 | /// let future = or_else(future, |x| ready(Err::(x + 3))); 158 | /// assert_eq!(future.await, Err(4)); 159 | /// # }); 160 | /// ``` 161 | /// 162 | /// Calling [`or_else`] on a successful future has 163 | /// no effect: 164 | /// 165 | /// ``` 166 | /// use futures_async_combinators::future::{ready, or_else}; 167 | /// 168 | /// # futures::executor::block_on(async { 169 | /// let future = ready(Ok::(1)); 170 | /// let future = or_else(future, |x| ready(Ok::(x + 3))); 171 | /// assert_eq!(future.await, Ok(1)); 172 | /// # }); 173 | /// ``` 174 | pub async fn or_else(future: FutA, f: F) -> Result 175 | where 176 | F: FnOnce(E) -> FutB, 177 | FutA: Future>, 178 | FutB: Future>, 179 | { 180 | match future.await { 181 | Ok(ok) => Ok(ok), 182 | Err(err) => { 183 | let new_future = f(err); 184 | new_future.await 185 | } 186 | } 187 | } 188 | 189 | /// Maps this future's success value to a different value. 190 | /// 191 | /// This method can be used to change the `Ok` type of the 192 | /// future into a different type. It is similar to the [`Result::map`] 193 | /// method. You can use this method to chain along a computation once the 194 | /// future has been resolved. 195 | /// 196 | /// The provided closure `f` will only be called if this future is resolved 197 | /// to an `Ok`. If it resolves to an `Err`, panics, or is dropped, then 198 | /// the provided closure will never be invoked. 199 | /// 200 | /// Note that this method consumes the future it is called on and returns a 201 | /// wrapped version of it. 202 | /// 203 | /// # Examples 204 | /// 205 | /// ``` 206 | /// use futures_async_combinators::future::{ready, map_ok}; 207 | /// 208 | /// # futures::executor::block_on(async { 209 | /// let future = ready(Ok::(1)); 210 | /// let future = map_ok(future, |x| x + 3); 211 | /// assert_eq!(future.await, Ok(4)); 212 | /// # }); 213 | /// ``` 214 | /// 215 | /// Calling [`map_ok`] on an errored future has no 216 | /// effect: 217 | /// 218 | /// ``` 219 | /// use futures_async_combinators::future::{ready, map_ok}; 220 | /// 221 | /// # futures::executor::block_on(async { 222 | /// let future = ready(Err::(1)); 223 | /// let future = map_ok(future, |x| x + 3); 224 | /// assert_eq!(future.await, Err(1)); 225 | /// # }); 226 | /// ``` 227 | pub async fn map_ok(future: Fut, f: F) -> Result 228 | where 229 | F: FnOnce(T) -> U, 230 | Fut: Future>, 231 | { 232 | future.await.map(f) 233 | } 234 | 235 | /// Maps this future's error value to a different value. 236 | /// 237 | /// This method can be used to change the `Error` type 238 | /// of the future into a different type. It is similar to the 239 | /// [`Result::map_err`] method. You can use this method for example to 240 | /// ensure that futures have the same `Error` type when 241 | /// using `select!` or `join!`. 242 | /// 243 | /// The provided closure `f` will only be called if this future is resolved 244 | /// to an [`Err`]. If it resolves to an [`Ok`], panics, or is dropped, then 245 | /// the provided closure will never be invoked. 246 | /// 247 | /// Note that this method consumes the future it is called on and returns a 248 | /// wrapped version of it. 249 | /// 250 | /// # Examples 251 | /// 252 | /// ``` 253 | /// use futures_async_combinators::future::{ready, map_err}; 254 | /// 255 | /// # futures::executor::block_on(async { 256 | /// let future = ready(Err::(1)); 257 | /// let future = map_err(future, |x| x + 3); 258 | /// assert_eq!(future.await, Err(4)); 259 | /// # }); 260 | /// ``` 261 | /// 262 | /// Calling [`map_err`] on a successful future has 263 | /// no effect: 264 | /// 265 | /// ``` 266 | /// use futures_async_combinators::future::{ready, map_err}; 267 | /// 268 | /// # futures::executor::block_on(async { 269 | /// let future = ready(Ok::(1)); 270 | /// let future = map_err(future, |x| x + 3); 271 | /// assert_eq!(future.await, Ok(1)); 272 | /// # }); 273 | /// ``` 274 | pub async fn map_err(future: Fut, f: F) -> Result 275 | where 276 | F: FnOnce(E) -> U, 277 | Fut: Future>, 278 | { 279 | future.await.map_err(f) 280 | } 281 | 282 | /// Flatten the execution of this future when the successful result of this 283 | /// future is itself another future. 284 | /// 285 | /// This can be useful when combining futures together to flatten the 286 | /// computation out the final result. This method can only be called 287 | /// when the successful result of this future itself implements the 288 | /// `IntoFuture` trait and the error can be created from this future's error 289 | /// type. 290 | /// 291 | /// This method is roughly equivalent to `and_then(self, |x| x)`. 292 | /// 293 | /// Note that this function consumes the receiving future and returns a 294 | /// wrapped version of it. 295 | /// 296 | /// # Examples 297 | /// 298 | /// ``` 299 | /// # futures::executor::block_on(async { 300 | /// use futures_async_combinators::future::{ready, flatten}; 301 | /// 302 | /// let nested_future = ready(ready(1)); 303 | /// let future = flatten(nested_future); 304 | /// assert_eq!(future.await, 1); 305 | /// # }); 306 | /// ``` 307 | pub async fn flatten(future: Fut) -> <::Output as Future>::Output 308 | where 309 | Fut: Future, 310 | ::Output: Future 311 | { 312 | let nested_future = future.await; 313 | nested_future.await 314 | } 315 | 316 | /// Do something with the output of a future before passing it on. 317 | /// 318 | /// When using futures, you'll often chain several of them together. While 319 | /// working on such code, you might want to check out what's happening at 320 | /// various parts in the pipeline, without consuming the intermediate 321 | /// value. To do that, insert a call to `inspect`. 322 | /// 323 | /// # Examples 324 | /// 325 | /// ``` 326 | /// # futures::executor::block_on(async { 327 | /// use futures_async_combinators::future::{ready, inspect}; 328 | /// 329 | /// let future = ready(1); 330 | /// let new_future = inspect(future, |&x| println!("about to resolve: {}", x)); 331 | /// assert_eq!(new_future.await, 1); 332 | /// # }); 333 | /// ``` 334 | pub async fn inspect(future: Fut, f: F) -> Fut::Output 335 | where 336 | Fut: Future, 337 | F: FnOnce(&Fut::Output), 338 | { 339 | let future_result = future.await; 340 | f(&future_result); 341 | future_result 342 | } 343 | 344 | /// Maps this future's `Error` to a new error type 345 | /// using the [`Into`](std::convert::Into) trait. 346 | /// 347 | /// This method does for futures what the `?`-operator does for 348 | /// [`Result`]: It lets the compiler infer the type of the resulting 349 | /// error. Just as [`map_err`](map_err), this is useful for 350 | /// example to ensure that futures have the same `Error` 351 | /// type when using `select!` or `join!`. 352 | /// 353 | /// Note that this method consumes the future it is called on and returns a 354 | /// wrapped version of it. 355 | /// 356 | /// # Examples 357 | /// 358 | /// ``` 359 | /// use futures_async_combinators::future::{ready, err_into}; 360 | /// 361 | /// # futures::executor::block_on(async { 362 | /// let future_err_u8 = ready(Err::<(), u8>(1)); 363 | /// let future_err_i32 = err_into::(future_err_u8); 364 | /// # }); 365 | /// ``` 366 | pub async fn err_into(future: Fut) -> Result 367 | where 368 | Fut: Future>, 369 | E: Into, 370 | { 371 | future.await.map_err(Into::into) 372 | } 373 | 374 | /// Unwraps this future's ouput, producing a future with this future's 375 | /// `Ok` type as its [`Output`](std::future::Future::Output) type. 376 | /// 377 | /// If this future is resolved successfully, the returned future will 378 | /// contain the original future's success value as output. Otherwise, the 379 | /// closure `f` is called with the error value to produce an alternate 380 | /// success value. 381 | /// 382 | /// This method is similar to the [`Result::unwrap_or_else`] method. 383 | /// 384 | /// # Examples 385 | /// 386 | /// ``` 387 | /// use futures_async_combinators::future::{ready, unwrap_or_else}; 388 | /// 389 | /// # futures::executor::block_on(async { 390 | /// let future = ready(Err::<(), &str>("Boom!")); 391 | /// let future = unwrap_or_else(future, |_| ()); 392 | /// assert_eq!(future.await, ()); 393 | /// # }); 394 | /// ``` 395 | pub async fn unwrap_or_else(future: Fut, f: F) -> T 396 | where 397 | Fut: Future>, 398 | F: FnOnce(E) -> T, 399 | { 400 | future.await.unwrap_or_else(f) 401 | } 402 | 403 | /// Flatten the execution of this future when the successful result of this 404 | /// future is a stream. 405 | /// 406 | /// This can be useful when stream initialization is deferred, and it is 407 | /// convenient to work with that stream as if stream was available at the 408 | /// call site. 409 | /// 410 | /// Note that this function consumes this future and returns a wrapped 411 | /// version of it. 412 | /// 413 | /// # Examples 414 | /// 415 | /// ``` 416 | /// # futures::executor::block_on(async { 417 | /// use futures_async_combinators::future::{ready, flatten_stream}; 418 | /// use futures_async_combinators::stream::{collect, iter}; 419 | /// 420 | /// let stream_items = vec![17, 18, 19]; 421 | /// let future_of_a_stream = ready(iter(stream_items)); 422 | /// 423 | /// let stream = flatten_stream(future_of_a_stream); 424 | /// let list: Vec<_> = collect(stream).await; 425 | /// assert_eq!(list, vec![17, 18, 19]); 426 | /// # }); 427 | /// ``` 428 | pub fn flatten_stream(future: Fut) -> impl Stream 429 | where 430 | Fut: Future, 431 | St: Stream, 432 | { 433 | use crate::stream::next; 434 | crate::stream::unfold((Some(future), None), |(future, stream)| async move { 435 | match (future, stream) { 436 | (Some(future), None) => { 437 | let stream = future.await; 438 | let mut stream = Box::pin(stream); 439 | let item = next(&mut stream).await; 440 | item.map(|item| (item, (None, Some(stream)))) 441 | } 442 | (None, Some(mut stream)) => { 443 | let item = next(&mut stream).await; 444 | item.map(|item| (item, (None, Some(stream)))) 445 | } 446 | _ => unreachable!(), 447 | } 448 | }) 449 | } 450 | 451 | /// Convert this future into a single element stream. 452 | /// 453 | /// The returned stream contains single success if this future resolves to 454 | /// success or single error if this future resolves into error. 455 | /// 456 | /// # Examples 457 | /// 458 | /// ``` 459 | /// # futures::executor::block_on(async { 460 | /// use futures_async_combinators::future::{ready, into_stream}; 461 | /// use futures_async_combinators::stream::collect; 462 | /// 463 | /// let future = ready(17); 464 | /// let stream = into_stream(future); 465 | /// let collected: Vec<_> = collect(stream).await; 466 | /// assert_eq!(collected, vec![17]); 467 | /// # }); 468 | /// ``` 469 | pub fn into_stream(future: Fut) -> impl Stream 470 | where 471 | Fut: Future, 472 | { 473 | crate::stream::once(future) 474 | } 475 | 476 | /// Creates a new future wrapping around a function returning [`Poll`](core::task::Poll). 477 | /// 478 | /// Polling the returned future delegates to the wrapped function. 479 | /// 480 | /// # Examples 481 | /// 482 | /// ``` 483 | /// # futures::executor::block_on(async { 484 | /// use futures_async_combinators::future::poll_fn; 485 | /// use core::task::{Poll, Context}; 486 | /// 487 | /// fn read_line(_cx: &mut Context<'_>) -> Poll { 488 | /// Poll::Ready("Hello, World!".into()) 489 | /// } 490 | /// 491 | /// let read_future = poll_fn(read_line); 492 | /// assert_eq!(read_future.await, "Hello, World!".to_owned()); 493 | /// # }); 494 | /// ``` 495 | pub fn poll_fn(f: F) -> impl Future 496 | where 497 | F: FnMut(&mut Context) -> Poll, 498 | { 499 | struct PollFn { 500 | f: F, 501 | } 502 | impl Unpin for PollFn {} 503 | impl Future for PollFn 504 | where 505 | F: FnMut(&mut Context<'_>) -> Poll, 506 | { 507 | type Output = T; 508 | 509 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 510 | (&mut self.f)(cx) 511 | } 512 | } 513 | PollFn { f } 514 | } 515 | 516 | #[cfg(test)] 517 | mod tests { 518 | use crate::future::*; 519 | use futures::executor; 520 | 521 | #[test] 522 | fn test_ready() { 523 | executor::block_on(async { 524 | let future = ready(1); 525 | assert_eq!(future.await, 1); 526 | }); 527 | } 528 | 529 | #[test] 530 | fn test_map() { 531 | executor::block_on(async { 532 | let future = ready(1); 533 | let new_future = map(future, |x| x + 3); 534 | assert_eq!(new_future.await, 4); 535 | }); 536 | } 537 | 538 | #[test] 539 | fn test_then() { 540 | executor::block_on(async { 541 | let future = ready(1); 542 | let new_future = then(future, |x| ready(x + 3)); 543 | assert_eq!(new_future.await, 4); 544 | }); 545 | } 546 | 547 | #[test] 548 | fn test_and_then_ok() { 549 | executor::block_on(async { 550 | let future = ready(Ok::(1)); 551 | let new_future = and_then(future, |x| ready(Ok::(x + 3))); 552 | assert_eq!(new_future.await, Ok(4)); 553 | }); 554 | } 555 | 556 | #[test] 557 | fn test_and_then_err() { 558 | executor::block_on(async { 559 | let future = ready(Err::(1)); 560 | let new_future = and_then(future, |x| ready(Ok::(x + 3))); 561 | assert_eq!(new_future.await, Err(1)); 562 | }); 563 | } 564 | 565 | #[test] 566 | fn test_or_else() { 567 | executor::block_on(async { 568 | let future = ready(Err::(1)); 569 | let new_future = or_else(future, |x| ready(Err::(x + 3))); 570 | assert_eq!(new_future.await, Err(4)); 571 | }); 572 | } 573 | 574 | #[test] 575 | fn test_map_ok() { 576 | executor::block_on(async { 577 | let future = ready(Ok::(1)); 578 | let new_future = map_ok(future, |x| x + 3); 579 | assert_eq!(new_future.await, Ok(4)); 580 | }); 581 | } 582 | 583 | #[test] 584 | fn test_map_err() { 585 | executor::block_on(async { 586 | let future = ready(Err::(1)); 587 | let new_future = map_err(future, |x| x + 3); 588 | assert_eq!(new_future.await, Err(4)); 589 | }); 590 | } 591 | 592 | #[test] 593 | fn test_flatten() { 594 | executor::block_on(async { 595 | let nested_future = ready(ready(1)); 596 | let future = flatten(nested_future); 597 | assert_eq!(future.await, 1); 598 | }); 599 | } 600 | 601 | #[test] 602 | fn test_inspect() { 603 | executor::block_on(async { 604 | let future = ready(1); 605 | let new_future = inspect(future, |&x| assert_eq!(x, 1)); 606 | assert_eq!(new_future.await, 1); 607 | }); 608 | } 609 | 610 | #[test] 611 | fn test_err_into() { 612 | executor::block_on(async { 613 | let future_err_u8 = ready(Err::<(), u8>(1)); 614 | let future_err_i32 = err_into::(future_err_u8); 615 | 616 | assert_eq!(future_err_i32.await, Err::<(), i32>(1)); 617 | }); 618 | } 619 | 620 | #[test] 621 | fn test_unwrap_or_else() { 622 | executor::block_on(async { 623 | let future = ready(Err::("Boom!")); 624 | let new_future = unwrap_or_else(future, |_| 42); 625 | assert_eq!(new_future.await, 42); 626 | }); 627 | } 628 | 629 | #[test] 630 | fn test_flatten_stream() { 631 | use crate::stream::{collect, iter}; 632 | executor::block_on(async { 633 | let stream_items = vec![17, 18, 19]; 634 | let future_of_a_stream = ready(iter(stream_items)); 635 | 636 | let stream = flatten_stream(future_of_a_stream); 637 | let list: Vec<_> = collect(stream).await; 638 | assert_eq!(list, vec![17, 18, 19]); 639 | }); 640 | } 641 | 642 | #[test] 643 | fn test_into_stream() { 644 | use crate::stream::collect; 645 | executor::block_on(async { 646 | let future = ready(17); 647 | let stream = into_stream(future); 648 | let collected: Vec<_> = collect(stream).await; 649 | assert_eq!(collected, vec![17]); 650 | }); 651 | } 652 | 653 | #[test] 654 | fn test_poll_fn() { 655 | executor::block_on(async { 656 | let read_line = 657 | |_context: &mut Context| -> Poll { Poll::Ready("Hello, World!".into()) }; 658 | 659 | let read_future = poll_fn(read_line); 660 | assert_eq!(read_future.await, "Hello, World!".to_owned()); 661 | }); 662 | } 663 | } 664 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod future; 2 | pub mod stream; 3 | -------------------------------------------------------------------------------- /src/stream.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | pub use futures_core::stream::Stream; 3 | 4 | use core::iter::IntoIterator; 5 | use core::pin::Pin; 6 | use core::task::{Context, Poll}; 7 | 8 | use pin_utils::pin_mut; 9 | 10 | /// Creates a future that resolves to the next item in the stream. 11 | /// 12 | /// Note that because `next` doesn't take ownership over the stream, 13 | /// the [`Stream`] type must be [`Unpin`]. If you want to use `next` with a 14 | /// [`!Unpin`](Unpin) stream, you'll first have to pin the stream. This can 15 | /// be done by boxing the stream using [`Box::pin`] or 16 | /// pinning it to the stack using the `pin_mut!` macro from the `pin_utils` 17 | /// crate. 18 | /// 19 | /// # Examples 20 | /// 21 | /// ``` 22 | /// # futures::executor::block_on(async { 23 | /// use futures_async_combinators::stream::{iter, next}; 24 | /// 25 | /// let mut stream = iter(1..=3); 26 | /// 27 | /// assert_eq!(next(&mut stream).await, Some(1)); 28 | /// assert_eq!(next(&mut stream).await, Some(2)); 29 | /// assert_eq!(next(&mut stream).await, Some(3)); 30 | /// assert_eq!(next(&mut stream).await, None); 31 | /// # }); 32 | /// ``` 33 | pub fn next<'a, St>(mut stream: &'a mut St) -> impl Future> + 'a 34 | where 35 | St: Stream + Unpin, 36 | { 37 | use crate::future::poll_fn; 38 | poll_fn(move |context| Pin::new(&mut stream).poll_next(context)) 39 | } 40 | 41 | /// Creates a stream of a single element. 42 | /// 43 | /// ``` 44 | /// # futures::executor::block_on(async { 45 | /// use futures_async_combinators::stream::{once, collect}; 46 | /// 47 | /// let stream = once(async { 17 }); 48 | /// let collection: Vec = collect(stream).await; 49 | /// assert_eq!(collection, vec![17]); 50 | /// # }); 51 | /// ``` 52 | pub fn once(future: F) -> impl Stream 53 | where 54 | F: Future, 55 | { 56 | crate::stream::unfold(Some(future), |f| async { 57 | match f { 58 | Some(f) => Some((f.await, None)), 59 | None => None 60 | } 61 | }) 62 | } 63 | 64 | /// Collect all of the values of this stream into a vector, returning a 65 | /// future representing the result of that computation. 66 | /// 67 | /// The returned future will be resolved when the stream terminates. 68 | /// 69 | /// # Examples 70 | /// 71 | /// ``` 72 | /// # futures::executor::block_on(async { 73 | /// use futures_async_combinators::stream::{iter, collect}; 74 | /// 75 | /// let stream = iter(1..=5); 76 | /// 77 | /// let collection: Vec = collect(stream).await; 78 | /// assert_eq!(collection, vec![1, 2, 3, 4, 5]); 79 | /// # }); 80 | /// ``` 81 | pub async fn collect(stream: St) -> C 82 | where 83 | St: Stream, 84 | C: Default + Extend, 85 | { 86 | pin_mut!(stream); 87 | let mut collection = C::default(); 88 | while let Some(item) = next(&mut stream).await { 89 | collection.extend(Some(item)); 90 | } 91 | collection 92 | } 93 | 94 | /// Maps this stream's items to a different type, returning a new stream of 95 | /// the resulting type. 96 | /// 97 | /// The provided closure is executed over all elements of this stream as 98 | /// they are made available. It is executed inline with calls to 99 | /// [`poll_next`](Stream::poll_next). 100 | /// 101 | /// Note that this function consumes the stream passed into it and returns a 102 | /// wrapped version of it, similar to the existing `map` methods in the 103 | /// standard library. 104 | /// 105 | /// # Examples 106 | /// 107 | /// ``` 108 | /// # futures::executor::block_on(async { 109 | /// use futures_async_combinators::stream::{iter, map, collect}; 110 | /// 111 | /// let stream = iter(1..=3); 112 | /// let stream = map(stream, |x| x + 3); 113 | /// 114 | /// let result: Vec<_> = collect(stream).await; 115 | /// assert_eq!(vec![4, 5, 6], result); 116 | /// # }); 117 | /// ``` 118 | pub fn map(stream: St, f: F) -> impl Stream 119 | where 120 | St: Stream, 121 | F: FnMut(St::Item) -> U, 122 | { 123 | let stream = Box::pin(stream); 124 | crate::stream::unfold((stream, f), |(mut stream, mut f)| async { 125 | let item = next(&mut stream).await; 126 | item.map(|item| (f(item), (stream, f))) 127 | }) 128 | } 129 | 130 | /// Filters the values produced by this stream according to the provided 131 | /// asynchronous predicate. 132 | /// 133 | /// As values of this stream are made available, the provided predicate `f` 134 | /// will be run against them. If the predicate returns a `Future` which 135 | /// resolves to `true`, then the stream will yield the value, but if the 136 | /// predicate returns a `Future` which resolves to `false`, then the value 137 | /// will be discarded and the next value will be produced. 138 | /// 139 | /// Note that this function consumes the stream passed into it and returns a 140 | /// wrapped version of it, similar to the existing `filter` methods in the 141 | /// standard library. 142 | /// 143 | /// # Examples 144 | /// 145 | /// ``` 146 | /// # futures::executor::block_on(async { 147 | /// use futures_async_combinators::{future::ready, stream::{iter, filter, collect}}; 148 | /// 149 | /// let stream = iter(1..=10); 150 | /// let evens = filter(stream, |x| ready(x % 2 == 0)); 151 | /// 152 | /// let result: Vec<_> = collect(evens).await; 153 | /// assert_eq!(vec![2, 4, 6, 8, 10], result); 154 | /// # }); 155 | /// ``` 156 | pub fn filter(stream: St, f: F) -> impl Stream 157 | where 158 | St: Stream, 159 | F: FnMut(&St::Item) -> Fut, 160 | Fut: Future, 161 | { 162 | let stream = Box::pin(stream); 163 | crate::stream::unfold((stream, f), |(mut stream, mut f)| async { 164 | while let Some(item) = next(&mut stream).await { 165 | let matched = f(&item).await; 166 | if matched { 167 | return Some((item, (stream, f))); 168 | } else { 169 | continue; 170 | } 171 | } 172 | None 173 | }) 174 | } 175 | 176 | /// Filters the values produced by this stream while simultaneously mapping 177 | /// them to a different type according to the provided asynchronous closure. 178 | /// 179 | /// As values of this stream are made available, the provided function will 180 | /// be run on them. If the future returned by the predicate `f` resolves to 181 | /// [`Some(item)`](Some) then the stream will yield the value `item`, but if 182 | /// it resolves to [`None`] then the next value will be produced. 183 | /// 184 | /// Note that this function consumes the stream passed into it and returns a 185 | /// wrapped version of it, similar to the existing `filter_map` methods in 186 | /// the standard library. 187 | /// 188 | /// # Examples 189 | /// ``` 190 | /// # futures::executor::block_on(async { 191 | /// use futures_async_combinators::{future::ready, stream::{iter, filter_map, collect}}; 192 | /// 193 | /// let stream = iter(1..=10); 194 | /// let evens = filter_map(stream, |x| { 195 | /// let ret = if x % 2 == 0 { Some(x + 1) } else { None }; 196 | /// ready(ret) 197 | /// }); 198 | /// 199 | /// let result: Vec<_> = collect(evens).await; 200 | /// assert_eq!(vec![3, 5, 7, 9, 11], result); 201 | /// # }); 202 | /// ``` 203 | pub fn filter_map(stream: St, f: F) -> impl Stream 204 | where 205 | St: Stream, 206 | F: FnMut(St::Item) -> Fut, 207 | Fut: Future>, 208 | { 209 | let stream = Box::pin(stream); 210 | crate::stream::unfold((stream, f), |(mut stream, mut f)| async { 211 | while let Some(item) = next(&mut stream).await { 212 | if let Some(item) = f(item).await { 213 | return Some((item, (stream, f))); 214 | } else { 215 | continue; 216 | } 217 | } 218 | None 219 | }) 220 | } 221 | 222 | /// Do something with each item of this stream, afterwards passing it on. 223 | /// 224 | /// This is similar to the `Iterator::inspect` method in the standard 225 | /// library where it allows easily inspecting each value as it passes 226 | /// through the stream, for example to debug what's going on. 227 | pub fn inspect(stream: St, f: F) -> impl Stream 228 | where 229 | St: Stream, 230 | F: FnMut(&St::Item), 231 | { 232 | let stream = Box::pin(stream); 233 | crate::stream::unfold((stream, f), |(mut stream, mut f)| async { 234 | let item = next(&mut stream).await; 235 | item.map(|item| { 236 | f(&item); 237 | (item, (stream, f)) 238 | }) 239 | }) 240 | } 241 | 242 | /// Converts this stream into a future of `(next_item, tail_of_stream)`. 243 | /// If the stream terminates, then the next item is [`None`]. 244 | /// 245 | /// The returned future can be used to compose streams and futures together 246 | /// by placing everything into the "world of futures". 247 | /// 248 | /// Note that because `into_future` moves the stream, the [`Stream`] type 249 | /// must be [`Unpin`]. If you want to use `into_future` with a 250 | /// [`!Unpin`](Unpin) stream, you'll first have to pin the stream. This can 251 | /// be done by boxing the stream using [`Box::pin`] or 252 | /// pinning it to the stack using the `pin_mut!` macro from the `pin_utils` 253 | /// crate. 254 | /// 255 | /// # Examples 256 | /// 257 | /// ``` 258 | /// # futures::executor::block_on(async { 259 | /// use futures_async_combinators::stream::{iter, into_future}; 260 | /// 261 | /// let stream = iter(1..3); 262 | /// 263 | /// let (item, stream) = into_future(stream).await; 264 | /// assert_eq!(Some(1), item); 265 | /// 266 | /// let (item, stream) = into_future(stream).await; 267 | /// assert_eq!(Some(2), item); 268 | /// 269 | /// let (item, stream) = into_future(stream).await; 270 | /// assert_eq!(None, item); 271 | /// # }); 272 | /// ``` 273 | pub async fn into_future(stream: St) -> (Option, impl Stream) 274 | where 275 | St: Stream + Unpin, 276 | { 277 | let mut stream = stream; 278 | let next_item = next(&mut stream).await; 279 | (next_item, stream) 280 | } 281 | 282 | /// Converts an `Iterator` into a `Stream` which is always ready 283 | /// to yield the next value. 284 | /// 285 | /// Iterators in Rust don't express the ability to block, so this adapter 286 | /// simply always calls `iter.next()` and returns that. 287 | /// 288 | /// ``` 289 | /// # futures::executor::block_on(async { 290 | /// use futures_async_combinators::stream::{iter, collect}; 291 | /// 292 | /// let stream = iter(vec![17, 19]); 293 | /// let result: Vec<_> = collect(stream).await; 294 | /// assert_eq!(vec![17, 19], result); 295 | /// # }); 296 | /// ``` 297 | pub fn iter(i: I) -> impl Stream 298 | where 299 | I: IntoIterator, 300 | { 301 | let mut iter = i.into_iter(); 302 | crate::stream::poll_fn(move |_| -> Poll> { Poll::Ready(iter.next()) }) 303 | } 304 | 305 | /// Concatenate all items of a stream into a single extendable 306 | /// destination, returning a future representing the end result. 307 | /// 308 | /// This combinator will extend the first item with the contents 309 | /// of all the subsequent results of the stream. If the stream is 310 | /// empty, the default value will be returned. 311 | /// 312 | /// Works with all collections that implement the 313 | /// [`Extend`](std::iter::Extend) trait. 314 | /// 315 | /// # Examples 316 | /// 317 | /// ``` 318 | /// # futures::executor::block_on(async { 319 | /// use futures_async_combinators::stream::{iter, concat}; 320 | /// 321 | /// let stream = iter(vec![vec![1, 2], vec![3], vec![4, 5]]); 322 | /// 323 | /// let result: Vec<_> = concat(stream).await; 324 | /// assert_eq!(result, vec![1, 2, 3, 4, 5]); 325 | /// # }); 326 | /// ``` 327 | pub async fn concat(stream: St) -> St::Item 328 | where 329 | St: Stream, 330 | St::Item: Extend<::Item>, 331 | St::Item: IntoIterator, 332 | St::Item: Default, 333 | { 334 | pin_mut!(stream); 335 | let mut collection = ::default(); 336 | while let Some(item) = next(&mut stream).await { 337 | collection.extend(item); 338 | } 339 | collection 340 | } 341 | 342 | /// Runs this stream to completion, executing the provided asynchronous 343 | /// closure for each element on the stream. 344 | /// 345 | /// The closure provided will be called for each item this stream produces, 346 | /// yielding a future. That future will then be executed to completion 347 | /// before moving on to the next item. 348 | /// 349 | /// The returned value is a `Future` where the `Output` type is `()`; it is 350 | /// executed entirely for its side effects. 351 | /// 352 | /// To process each item in the stream and produce another stream instead 353 | /// of a single future, use `then` instead. 354 | /// 355 | /// # Examples 356 | /// 357 | /// ``` 358 | /// # futures::executor::block_on(async { 359 | /// use futures::future; 360 | /// use futures_async_combinators::{future::ready, stream::{repeat, take, for_each}}; 361 | /// 362 | /// let mut x = 0; 363 | /// 364 | /// { 365 | /// let stream = repeat(1); 366 | /// let stream = take(stream, 3); 367 | /// let fut = for_each(stream, |item| { 368 | /// x += item; 369 | /// ready(()) 370 | /// }); 371 | /// fut.await; 372 | /// } 373 | /// 374 | /// assert_eq!(x, 3); 375 | /// # }); 376 | /// ``` 377 | pub async fn for_each(stream: St, f: F) 378 | where 379 | St: Stream, 380 | F: FnMut(St::Item) -> Fut, 381 | Fut: Future, 382 | { 383 | pin_mut!(stream); 384 | let mut f = f; 385 | while let Some(item) = next(&mut stream).await { 386 | f(item); 387 | } 388 | } 389 | 390 | /// Creates a new stream of at most `n` items of the underlying stream. 391 | /// 392 | /// Once `n` items have been yielded from this stream then it will always 393 | /// return that the stream is done. 394 | /// 395 | /// # Examples 396 | /// 397 | /// ``` 398 | /// # futures::executor::block_on(async { 399 | /// use futures_async_combinators::stream::{iter, take, collect}; 400 | /// 401 | /// let stream = iter(1..=10); 402 | /// let stream = take(stream, 3); 403 | /// 404 | /// let result: Vec<_> = collect(stream).await; 405 | /// assert_eq!(vec![1, 2, 3], result); 406 | /// # }); 407 | /// ``` 408 | pub fn take(stream: St, n: u64) -> impl Stream 409 | where 410 | St: Stream, 411 | { 412 | let stream = Box::pin(stream); 413 | crate::stream::unfold((stream, n), |(mut stream, n)| async move { 414 | if n == 0 { 415 | return None; 416 | } 417 | if let Some(item) = next(&mut stream).await { 418 | Some((item, (stream, n - 1))) 419 | } else { 420 | None 421 | } 422 | }) 423 | } 424 | 425 | /// Create a stream which produces the same item repeatedly. 426 | /// 427 | /// The stream never terminates. Note that you likely want to avoid 428 | /// usage of `collect` or such on the returned stream as it will exhaust 429 | /// available memory as it tries to just fill up all RAM. 430 | /// 431 | /// ``` 432 | /// # futures::executor::block_on(async { 433 | /// use futures_async_combinators::stream::{repeat, take, collect}; 434 | /// 435 | /// let stream = repeat(9); 436 | /// let stream = take(stream, 3); 437 | /// 438 | /// let result: Vec<_> = collect(stream).await; 439 | /// assert_eq!(vec![9, 9, 9], result); 440 | /// # }); 441 | /// ``` 442 | pub fn repeat(item: T) -> impl Stream 443 | where 444 | T: Clone, 445 | { 446 | crate::stream::poll_fn(move |_| -> Poll> { Poll::Ready(Some(item.clone())) }) 447 | } 448 | 449 | /// Flattens a stream of streams into just one continuous stream. 450 | /// 451 | /// # Examples 452 | /// 453 | /// ``` 454 | /// # futures::executor::block_on(async { 455 | /// use futures_async_combinators::stream::{iter, flatten, collect}; 456 | /// 457 | /// let stream0 = iter(0..0); 458 | /// let stream1 = iter(1..4); 459 | /// let stream2 = iter(4..7); 460 | /// let stream3 = iter(7..10); 461 | /// let stream = iter(vec![stream0, stream1, stream2, stream3]); 462 | /// let stream = flatten(stream); 463 | /// 464 | /// let result: Vec<_> = collect(stream).await; 465 | /// assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9], result); 466 | /// # }); 467 | /// ``` 468 | pub fn flatten(stream: St) -> impl Stream 469 | where 470 | SubSt: Stream, 471 | St: Stream, 472 | { 473 | let stream = Box::pin(stream); 474 | crate::stream::unfold( 475 | (Some(stream), None), 476 | |(mut state_stream, mut state_substream)| async move { 477 | loop { 478 | if let Some(mut substream) = state_substream.take() { 479 | if let Some(item) = next(&mut substream).await { 480 | return Some((item, (state_stream, Some(substream)))); 481 | } else { 482 | continue; 483 | } 484 | } 485 | if let Some(mut stream) = state_stream.take() { 486 | if let Some(substream) = next(&mut stream).await { 487 | let substream = Box::pin(substream); 488 | state_stream = Some(stream); 489 | state_substream = Some(substream); 490 | continue; 491 | } 492 | } 493 | return None; 494 | } 495 | } 496 | ) 497 | } 498 | 499 | /// Computes from this stream's items new items of a different type using 500 | /// an asynchronous closure. 501 | /// 502 | /// The provided closure `f` will be called with an `Item` once a value is 503 | /// ready, it returns a future which will then be run to completion 504 | /// to produce the next value on this stream. 505 | /// 506 | /// Note that this function consumes the stream passed into it and returns a 507 | /// wrapped version of it. 508 | /// 509 | /// # Examples 510 | /// 511 | /// ``` 512 | /// # futures::executor::block_on(async { 513 | /// use futures_async_combinators::{future::ready, stream::{iter, then, collect}}; 514 | /// 515 | /// let stream = iter(1..=3); 516 | /// let stream = then(stream, |x| ready(x + 3)); 517 | /// 518 | /// let result: Vec<_> = collect(stream).await; 519 | /// assert_eq!(vec![4, 5, 6], result); 520 | /// # }); 521 | /// ``` 522 | pub fn then(stream: St, f: F) -> impl Stream 523 | where 524 | St: Stream, 525 | F: FnMut(St::Item) -> Fut, 526 | Fut: Future, 527 | { 528 | let stream = Box::pin(stream); 529 | crate::stream::unfold((stream, f), |(mut stream, mut f)| async { 530 | let item = next(&mut stream).await; 531 | if let Some(item) = item { 532 | let new_item = f(item).await; 533 | Some((new_item, (stream, f))) 534 | } else { 535 | None 536 | } 537 | }) 538 | } 539 | 540 | /// Creates a new stream which skips `n` items of the underlying stream. 541 | /// 542 | /// Once `n` items have been skipped from this stream then it will always 543 | /// return the remaining items on this stream. 544 | /// 545 | /// # Examples 546 | /// 547 | /// ``` 548 | /// # futures::executor::block_on(async { 549 | /// use futures_async_combinators::stream::{iter, skip, collect}; 550 | /// 551 | /// let stream = iter(1..=10); 552 | /// let stream = skip(stream, 5); 553 | /// 554 | /// let result: Vec<_> = collect(stream).await; 555 | /// assert_eq!(vec![6, 7, 8, 9, 10], result); 556 | /// # }); 557 | /// ``` 558 | pub fn skip(stream: St, n: u64) -> impl Stream 559 | where 560 | St: Stream, 561 | { 562 | let stream = Box::pin(stream); 563 | crate::stream::unfold((stream, n), |(mut stream, mut n)| async move { 564 | while n != 0 { 565 | if next(&mut stream).await.is_some() { 566 | n -= 1; 567 | continue; 568 | } else { 569 | return None; 570 | } 571 | } 572 | if let Some(item) = next(&mut stream).await { 573 | Some((item, (stream, 0))) 574 | } else { 575 | None 576 | } 577 | }) 578 | } 579 | 580 | /// An adapter for zipping two streams together. 581 | /// 582 | /// The zipped stream waits for both streams to produce an item, and then 583 | /// returns that pair. If either stream ends then the zipped stream will 584 | /// also end. 585 | /// 586 | /// # Examples 587 | /// 588 | /// ``` 589 | /// # futures::executor::block_on(async { 590 | /// use futures_async_combinators::stream::{iter, zip, collect}; 591 | /// 592 | /// let stream1 = iter(1..=3); 593 | /// let stream2 = iter(5..=10); 594 | /// 595 | /// let stream = zip(stream1, stream2); 596 | /// let result: Vec<_> = collect(stream).await; 597 | /// assert_eq!(vec![(1, 5), (2, 6), (3, 7)], result); 598 | /// # }); 599 | /// ``` 600 | /// 601 | pub fn zip(stream: St1, other: St2) -> impl Stream 602 | where 603 | St1: Stream, 604 | St2: Stream, 605 | { 606 | let stream = Box::pin(stream); 607 | let other = Box::pin(other); 608 | crate::stream::unfold((stream, other), |(mut stream, mut other)| async { 609 | let left = next(&mut stream).await; 610 | let right = next(&mut other).await; 611 | match (left, right) { 612 | (Some(left), Some(right)) => Some(((left, right), (stream, other))), 613 | _ => None, 614 | } 615 | }) 616 | } 617 | 618 | /// Adapter for chaining two stream. 619 | /// 620 | /// The resulting stream emits elements from the first stream, and when 621 | /// first stream reaches the end, emits the elements from the second stream. 622 | /// 623 | /// ``` 624 | /// # futures::executor::block_on(async { 625 | /// use futures_async_combinators::stream::{iter, chain, collect}; 626 | /// 627 | /// let stream1 = iter(vec![Ok(10), Err(false)]); 628 | /// let stream2 = iter(vec![Err(true), Ok(20)]); 629 | /// 630 | /// let stream = chain(stream1, stream2); 631 | /// 632 | /// let result: Vec<_> = collect(stream).await; 633 | /// assert_eq!(result, vec![ 634 | /// Ok(10), 635 | /// Err(false), 636 | /// Err(true), 637 | /// Ok(20), 638 | /// ]); 639 | /// # }); 640 | /// ``` 641 | pub fn chain(left: St, right: St) -> impl Stream 642 | where 643 | St: Stream, 644 | { 645 | flatten(iter( vec![left, right] )) 646 | } 647 | 648 | /// Take elements from this stream while the provided asynchronous predicate 649 | /// resolves to `true`. 650 | /// 651 | /// This function, like `Iterator::take_while`, will take elements from the 652 | /// stream until the predicate `f` resolves to `false`. Once one element 653 | /// returns false it will always return that the stream is done. 654 | /// 655 | /// # Examples 656 | /// 657 | /// ``` 658 | /// # futures::executor::block_on(async { 659 | /// use futures_async_combinators::{future::ready, stream::{iter, take_while, collect}}; 660 | /// 661 | /// let stream = iter(1..=10); 662 | /// let stream = take_while(stream, |x| ready(*x <= 5)); 663 | /// 664 | /// let result: Vec<_> = collect(stream).await; 665 | /// assert_eq!(vec![1, 2, 3, 4, 5], result); 666 | /// # }); 667 | /// ``` 668 | pub fn take_while(stream: St, f: F) -> impl Stream 669 | where 670 | St: Stream, 671 | F: FnMut(&St::Item) -> Fut, 672 | Fut: Future, 673 | { 674 | let stream = Box::pin(stream); 675 | crate::stream::unfold((stream, f), |(mut stream, mut f)| async move { 676 | if let Some(item) = next(&mut stream).await { 677 | if f(&item).await { 678 | Some((item, (stream, f))) 679 | } else { 680 | None 681 | } 682 | } else { 683 | None 684 | } 685 | }) 686 | } 687 | 688 | /// Skip elements on this stream while the provided asynchronous predicate 689 | /// resolves to `true`. 690 | /// 691 | /// This function, like `Iterator::skip_while`, will skip elements on the 692 | /// stream until the predicate `f` resolves to `false`. Once one element 693 | /// returns false all future elements will be returned from the underlying 694 | /// stream. 695 | /// 696 | /// # Examples 697 | /// 698 | /// ``` 699 | /// # futures::executor::block_on(async { 700 | /// use futures_async_combinators::{future::ready, stream::{iter, skip_while, collect}}; 701 | /// 702 | /// let stream = iter(1..=10); 703 | /// let stream = skip_while(stream, |x| ready(*x <= 5)); 704 | /// 705 | /// let result: Vec<_> = collect(stream).await; 706 | /// assert_eq!(vec![6, 7, 8, 9, 10], result); 707 | /// # }); 708 | /// ``` 709 | pub fn skip_while(stream: St, f: F) -> impl Stream 710 | where 711 | St: Stream, 712 | F: FnMut(&St::Item) -> Fut, 713 | Fut: Future, 714 | { 715 | let stream = Box::pin(stream); 716 | let should_skip = true; 717 | crate::stream::unfold( 718 | (stream, f, should_skip), 719 | |(mut stream, mut f, should_skip)| async move { 720 | if should_skip { 721 | while let Some(item) = next(&mut stream).await { 722 | if f(&item).await { 723 | continue; 724 | } else { 725 | return Some((item, (stream, f, /* should_skip */ false))); 726 | } 727 | } 728 | } 729 | if let Some(item) = next(&mut stream).await { 730 | Some((item, (stream, f, /* should_skip */ false))) 731 | } else { 732 | None 733 | } 734 | }, 735 | ) 736 | } 737 | 738 | /// Execute an accumulating asynchronous computation over a stream, 739 | /// collecting all the values into one final result. 740 | /// 741 | /// This combinator will accumulate all values returned by this stream 742 | /// according to the closure provided. The initial state is also provided to 743 | /// this method and then is returned again by each execution of the closure. 744 | /// Once the entire stream has been exhausted the returned future will 745 | /// resolve to this value. 746 | /// 747 | /// # Examples 748 | /// 749 | /// ``` 750 | /// # futures::executor::block_on(async { 751 | /// use futures_async_combinators::{future::ready, stream::{iter, fold}}; 752 | /// 753 | /// let number_stream = iter(0..6); 754 | /// let sum = fold(number_stream, 0, |acc, x| ready(acc + x)); 755 | /// assert_eq!(sum.await, 15); 756 | /// # }); 757 | /// ``` 758 | pub async fn fold(stream: St, init: T, f: F) -> T 759 | where 760 | St: Stream, 761 | F: FnMut(T, St::Item) -> Fut, 762 | Fut: Future, 763 | { 764 | pin_mut!(stream); 765 | let mut f = f; 766 | let mut acc = init; 767 | while let Some(item) = next(&mut stream).await { 768 | acc = f(acc, item).await; 769 | } 770 | acc 771 | } 772 | 773 | /// Creates a `Stream` from a seed and a closure returning a `Future`. 774 | /// 775 | /// This function is the dual for the [`fold()`] adapter: while 776 | /// [`fold()`] reduces a `Stream` to one single value, `unfold()` creates a 777 | /// `Stream` from a seed value. 778 | /// 779 | /// `unfold()` will call the provided closure with the provided seed, then wait 780 | /// for the returned `Future` to complete with `(a, b)`. It will then yield the 781 | /// value `a`, and use `b` as the next internal state. 782 | /// 783 | /// If the closure returns `None` instead of `Some(Future)`, then the `unfold()` 784 | /// will stop producing items and return `Poll::Ready(None)` in future 785 | /// calls to `poll()`. 786 | /// 787 | /// In case of error generated by the returned `Future`, the error will be 788 | /// returned by the `Stream`. The `Stream` will then yield 789 | /// `Poll::Ready(None)` in future calls to `poll()`. 790 | /// 791 | /// This function can typically be used when wanting to go from the "world of 792 | /// futures" to the "world of streams": the provided closure can build a 793 | /// `Future` using other library functions working on futures, and `unfold()` 794 | /// will turn it into a `Stream` by repeating the operation. 795 | /// 796 | /// # Example 797 | /// 798 | /// ``` 799 | /// # futures::executor::block_on(async { 800 | /// use futures_async_combinators::{future::ready, stream::{unfold, collect}}; 801 | /// 802 | /// let stream = unfold(0, |state| { 803 | /// if state <= 2 { 804 | /// let next_state = state + 1; 805 | /// let yielded = state * 2; 806 | /// ready(Some((yielded, next_state))) 807 | /// } else { 808 | /// ready(None) 809 | /// } 810 | /// }); 811 | /// 812 | /// let result: Vec<_> = collect(stream).await; 813 | /// assert_eq!(result, vec![0, 2, 4]); 814 | /// # }); 815 | /// ``` 816 | pub fn unfold(init: T, mut f: F) -> impl Stream 817 | where 818 | F: FnMut(T) -> Fut, 819 | Fut: Future>, 820 | { 821 | let mut state = Some(init); 822 | let mut running = Box::pin(None); 823 | 824 | crate::stream::poll_fn(move |context| -> Poll> { 825 | if let Some(state) = state.take() { 826 | let fut = f(state); 827 | running.set(Some(fut)); 828 | } 829 | 830 | let fut = Option::as_pin_mut(running.as_mut()).expect("this stream must not be polled any more"); 831 | let step = futures_core::ready!(fut.poll(context)); 832 | 833 | match step { 834 | None => { 835 | Poll::Ready(None) 836 | }, 837 | Some((item, new_state)) => { 838 | state = Some(new_state); 839 | running.set(None); 840 | Poll::Ready(Some(item)) 841 | }, 842 | } 843 | }) 844 | } 845 | 846 | /// Creates a new stream wrapping a function returning `Poll>`. 847 | /// 848 | /// Polling the returned stream calls the wrapped function. 849 | /// 850 | /// # Examples 851 | /// 852 | /// ``` 853 | /// use futures_async_combinators::stream::poll_fn; 854 | /// use core::task::Poll; 855 | /// 856 | /// let mut counter = 1usize; 857 | /// 858 | /// let read_stream = poll_fn(move |_| -> Poll> { 859 | /// if counter == 0 { return Poll::Ready(None); } 860 | /// counter -= 1; 861 | /// Poll::Ready(Some("Hello, World!".to_owned())) 862 | /// }); 863 | /// ``` 864 | pub fn poll_fn(f: F) -> impl Stream 865 | where 866 | F: FnMut(&mut Context<'_>) -> Poll>, 867 | { 868 | pub struct PollFn { 869 | f: F, 870 | } 871 | 872 | impl Unpin for PollFn {} 873 | 874 | impl Stream for PollFn 875 | where 876 | F: FnMut(&mut Context<'_>) -> Poll>, 877 | { 878 | type Item = T; 879 | 880 | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 881 | (&mut self.f)(cx) 882 | } 883 | } 884 | PollFn { f } 885 | } 886 | 887 | #[cfg(test)] 888 | mod tests { 889 | use crate::future::ready; 890 | use crate::stream::*; 891 | use futures::executor; 892 | 893 | #[test] 894 | fn test_next() { 895 | let mut stream = iter(1..=3); 896 | 897 | assert_eq!(executor::block_on(next(&mut stream)), Some(1)); 898 | assert_eq!(executor::block_on(next(&mut stream)), Some(2)); 899 | assert_eq!(executor::block_on(next(&mut stream)), Some(3)); 900 | assert_eq!(executor::block_on(next(&mut stream)), None); 901 | } 902 | 903 | #[test] 904 | fn test_once() { 905 | let stream = once(async { 17 }); 906 | 907 | let collection: Vec = executor::block_on(collect(stream)); 908 | assert_eq!(collection, vec![17]); 909 | } 910 | 911 | #[test] 912 | fn test_collect() { 913 | let stream = iter(1..=5); 914 | 915 | let collection: Vec = executor::block_on(collect(stream)); 916 | assert_eq!(collection, vec![1, 2, 3, 4, 5]); 917 | } 918 | 919 | #[test] 920 | fn test_map() { 921 | let stream = iter(1..=3); 922 | let stream = map(stream, |x| x * 2); 923 | 924 | assert_eq!( 925 | vec![2, 4, 6], 926 | executor::block_on(collect::<_, Vec<_>>(stream)) 927 | ); 928 | } 929 | 930 | #[test] 931 | fn test_filter() { 932 | let stream = iter(1..=10); 933 | let evens = filter(stream, |x| ready(x % 2 == 0)); 934 | 935 | assert_eq!( 936 | vec![2, 4, 6, 8, 10], 937 | executor::block_on(collect::<_, Vec<_>>(evens)) 938 | ); 939 | } 940 | 941 | #[test] 942 | fn test_filter_map() { 943 | let stream = iter(1..=10); 944 | let evens = filter_map(stream, |x| { 945 | let ret = if x % 2 == 0 { Some(x + 1) } else { None }; 946 | ready(ret) 947 | }); 948 | 949 | assert_eq!( 950 | vec![3, 5, 7, 9, 11], 951 | executor::block_on(collect::<_, Vec<_>>(evens)) 952 | ); 953 | } 954 | 955 | #[test] 956 | fn test_inspect() { 957 | let mut seen = Vec::new(); 958 | let stream = iter(1..=3); 959 | let stream = inspect(stream, |x| seen.push(*x)); 960 | 961 | assert_eq!( 962 | vec![1, 2, 3], 963 | executor::block_on(collect::<_, Vec<_>>(stream)) 964 | ); 965 | assert_eq!(seen, [1, 2, 3]); 966 | } 967 | 968 | #[test] 969 | fn test_into_future() { 970 | let stream = iter(1..=2); 971 | 972 | let (item, stream) = executor::block_on(into_future(stream)); 973 | assert_eq!(Some(1), item); 974 | 975 | let (item, stream) = executor::block_on(into_future(stream)); 976 | assert_eq!(Some(2), item); 977 | 978 | let (item, _) = executor::block_on(into_future(stream)); 979 | assert_eq!(None, item); 980 | } 981 | 982 | #[test] 983 | fn test_iter() { 984 | let stream = iter(1..=5); 985 | 986 | let collection: Vec = executor::block_on(collect(stream)); 987 | assert_eq!(collection, vec![1, 2, 3, 4, 5]); 988 | } 989 | 990 | #[test] 991 | fn test_concat() { 992 | let stream = iter(vec![vec![1, 2], vec![3], vec![4, 5]]); 993 | 994 | let collection: Vec = executor::block_on(concat(stream)); 995 | assert_eq!(collection, vec![1, 2, 3, 4, 5]); 996 | } 997 | 998 | #[test] 999 | fn test_for_each() { 1000 | let mut x = 0; 1001 | 1002 | { 1003 | let stream = iter(1..=3); 1004 | let future = for_each(stream, |item| { 1005 | x += item; 1006 | ready(()) 1007 | }); 1008 | executor::block_on(future); 1009 | } 1010 | 1011 | assert_eq!(x, 6); 1012 | } 1013 | 1014 | #[test] 1015 | fn test_take() { 1016 | let stream = iter(1..=10); 1017 | let stream = take(stream, 3); 1018 | 1019 | assert_eq!( 1020 | vec![1, 2, 3], 1021 | executor::block_on(collect::<_, Vec<_>>(stream)) 1022 | ); 1023 | } 1024 | 1025 | #[test] 1026 | fn test_take_more_than_size() { 1027 | let stream = iter(1..=3); 1028 | let stream = take(stream, 10); 1029 | 1030 | assert_eq!( 1031 | vec![1, 2, 3], 1032 | executor::block_on(collect::<_, Vec<_>>(stream)) 1033 | ); 1034 | } 1035 | 1036 | #[test] 1037 | fn test_repeat() { 1038 | let stream = repeat(9); 1039 | let stream = take(stream, 3); 1040 | 1041 | assert_eq!( 1042 | vec![9, 9, 9], 1043 | executor::block_on(collect::<_, Vec<_>>(stream)) 1044 | ); 1045 | } 1046 | 1047 | #[test] 1048 | fn test_flatten() { 1049 | let stream0 = iter(0..0); 1050 | let stream1 = iter(1..4); 1051 | let stream2 = iter(4..7); 1052 | let stream3 = iter(7..10); 1053 | let stream = iter(vec![stream0, stream1, stream2, stream3]); 1054 | let stream = flatten(stream); 1055 | 1056 | assert_eq!( 1057 | vec![1, 2, 3, 4, 5, 6, 7, 8, 9], 1058 | executor::block_on(collect::<_, Vec<_>>(stream)) 1059 | ); 1060 | } 1061 | 1062 | #[test] 1063 | fn test_then() { 1064 | let stream = iter(1..=3); 1065 | let stream = then(stream, |x| ready(x + 3)); 1066 | 1067 | assert_eq!( 1068 | vec![4, 5, 6], 1069 | executor::block_on(collect::<_, Vec<_>>(stream)) 1070 | ); 1071 | } 1072 | 1073 | #[test] 1074 | fn test_skip() { 1075 | let stream = iter(1..=10); 1076 | let stream = skip(stream, 5); 1077 | 1078 | assert_eq!( 1079 | vec![6, 7, 8, 9, 10], 1080 | executor::block_on(collect::<_, Vec<_>>(stream)) 1081 | ); 1082 | } 1083 | 1084 | #[test] 1085 | fn test_skip_more_than_size() { 1086 | let stream = iter(1..=10); 1087 | let stream = skip(stream, 15); 1088 | 1089 | assert!(executor::block_on(collect::<_, Vec<_>>(stream)).is_empty()); 1090 | } 1091 | 1092 | #[test] 1093 | fn test_zip() { 1094 | let stream1 = iter(1..=3); 1095 | let stream2 = iter(5..=10); 1096 | let stream = zip(stream1, stream2); 1097 | 1098 | assert_eq!( 1099 | vec![(1, 5), (2, 6), (3, 7)], 1100 | executor::block_on(collect::<_, Vec<_>>(stream)) 1101 | ); 1102 | } 1103 | 1104 | #[test] 1105 | fn test_chain() { 1106 | let stream1 = iter(1..=2); 1107 | let stream2 = iter(3..=4); 1108 | let stream = chain(stream1, stream2); 1109 | 1110 | assert_eq!( 1111 | vec![1, 2, 3, 4], 1112 | executor::block_on(collect::<_, Vec<_>>(stream)) 1113 | ); 1114 | } 1115 | 1116 | #[test] 1117 | fn test_take_while() { 1118 | let stream = iter(1..=10); 1119 | let stream = take_while(stream, |x| ready(*x <= 5)); 1120 | 1121 | assert_eq!( 1122 | vec![1, 2, 3, 4, 5], 1123 | executor::block_on(collect::<_, Vec<_>>(stream)) 1124 | ); 1125 | } 1126 | 1127 | #[test] 1128 | fn test_take_while_more_than_size() { 1129 | let stream = iter(1..=3); 1130 | let stream = take_while(stream, |x| ready(*x <= 5)); 1131 | 1132 | assert_eq!( 1133 | vec![1, 2, 3], 1134 | executor::block_on(collect::<_, Vec<_>>(stream)) 1135 | ); 1136 | } 1137 | 1138 | #[test] 1139 | fn test_skip_while() { 1140 | let stream = iter(1..=10); 1141 | let stream = skip_while(stream, |x| ready(*x <= 5)); 1142 | 1143 | assert_eq!( 1144 | vec![6, 7, 8, 9, 10], 1145 | executor::block_on(collect::<_, Vec<_>>(stream)) 1146 | ); 1147 | } 1148 | 1149 | #[test] 1150 | fn test_skip_while_more_than_size() { 1151 | let stream = iter(1..=3); 1152 | let stream = skip_while(stream, |x| ready(*x <= 5)); 1153 | 1154 | assert!(executor::block_on(collect::<_, Vec<_>>(stream)).is_empty()); 1155 | } 1156 | 1157 | #[test] 1158 | fn test_fold() { 1159 | let stream = iter(0..6); 1160 | let sum = fold(stream, 0, |acc, x| ready(acc + x)); 1161 | 1162 | assert_eq!(15, executor::block_on(sum)); 1163 | } 1164 | 1165 | #[test] 1166 | fn test_unfold() { 1167 | let stream = unfold(0, |state| { 1168 | if state <= 2 { 1169 | let next_state = state + 1; 1170 | let yielded = state * 2; 1171 | ready(Some((yielded, next_state))) 1172 | } else { 1173 | ready(None) 1174 | } 1175 | }); 1176 | assert_eq!( 1177 | vec![0, 2, 4], 1178 | executor::block_on(collect::<_, Vec<_>>(stream)) 1179 | ); 1180 | } 1181 | } 1182 | --------------------------------------------------------------------------------