├── .editorconfig ├── .git-blame-ignore-revs ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .rustfmt.toml ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples ├── functional │ ├── Cargo.toml │ └── src │ │ └── main.rs └── imperative │ ├── Cargo.toml │ └── src │ └── main.rs ├── futures-channel ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── sync_mpsc.rs ├── src │ ├── lib.rs │ ├── lock.rs │ ├── mpsc │ │ ├── mod.rs │ │ ├── queue.rs │ │ └── sink_impl.rs │ └── oneshot.rs └── tests │ ├── channel.rs │ ├── mpsc-close.rs │ ├── mpsc-size_hint.rs │ ├── mpsc.rs │ └── oneshot.rs ├── futures-core ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ ├── future.rs │ ├── lib.rs │ ├── stream.rs │ └── task │ ├── __internal │ ├── atomic_waker.rs │ └── mod.rs │ ├── mod.rs │ └── poll.rs ├── futures-executor ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── thread_notify.rs ├── src │ ├── enter.rs │ ├── lib.rs │ ├── local_pool.rs │ ├── thread_pool.rs │ └── unpark_mutex.rs └── tests │ └── local_pool.rs ├── futures-io ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ └── lib.rs ├── futures-macro ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT └── src │ ├── executor.rs │ ├── join.rs │ ├── lib.rs │ ├── select.rs │ └── stream_select.rs ├── futures-sink ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ └── lib.rs ├── futures-task ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ ├── arc_wake.rs │ ├── future_obj.rs │ ├── lib.rs │ ├── noop_waker.rs │ ├── spawn.rs │ ├── waker.rs │ └── waker_ref.rs ├── futures-test ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ ├── assert.rs │ ├── assert_unmoved.rs │ ├── future │ ├── mod.rs │ └── pending_once.rs │ ├── interleave_pending.rs │ ├── io │ ├── limited.rs │ ├── mod.rs │ ├── read │ │ └── mod.rs │ └── write │ │ └── mod.rs │ ├── lib.rs │ ├── sink │ └── mod.rs │ ├── stream │ └── mod.rs │ ├── task │ ├── context.rs │ ├── mod.rs │ ├── noop_spawner.rs │ ├── panic_spawner.rs │ ├── panic_waker.rs │ ├── record_spawner.rs │ └── wake_counter.rs │ └── track_closed.rs ├── futures-util ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ ├── bilock.rs │ ├── flatten_unordered.rs │ ├── futures_unordered.rs │ └── select.rs └── src │ ├── abortable.rs │ ├── async_await │ ├── join_mod.rs │ ├── mod.rs │ ├── pending.rs │ ├── poll.rs │ ├── random.rs │ ├── select_mod.rs │ └── stream_select_mod.rs │ ├── compat │ ├── compat01as03.rs │ ├── compat03as01.rs │ ├── executor.rs │ └── mod.rs │ ├── fns.rs │ ├── future │ ├── abortable.rs │ ├── always_ready.rs │ ├── either.rs │ ├── future │ │ ├── catch_unwind.rs │ │ ├── flatten.rs │ │ ├── fuse.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── remote_handle.rs │ │ └── shared.rs │ ├── join.rs │ ├── join_all.rs │ ├── lazy.rs │ ├── maybe_done.rs │ ├── mod.rs │ ├── option.rs │ ├── pending.rs │ ├── poll_fn.rs │ ├── poll_immediate.rs │ ├── ready.rs │ ├── select.rs │ ├── select_all.rs │ ├── select_ok.rs │ ├── try_future │ │ ├── into_future.rs │ │ ├── mod.rs │ │ ├── try_flatten.rs │ │ └── try_flatten_err.rs │ ├── try_join.rs │ ├── try_join_all.rs │ ├── try_maybe_done.rs │ └── try_select.rs │ ├── io │ ├── allow_std.rs │ ├── buf_reader.rs │ ├── buf_writer.rs │ ├── chain.rs │ ├── close.rs │ ├── copy.rs │ ├── copy_buf.rs │ ├── copy_buf_abortable.rs │ ├── cursor.rs │ ├── empty.rs │ ├── fill_buf.rs │ ├── flush.rs │ ├── into_sink.rs │ ├── line_writer.rs │ ├── lines.rs │ ├── mod.rs │ ├── read.rs │ ├── read_exact.rs │ ├── read_line.rs │ ├── read_to_end.rs │ ├── read_to_string.rs │ ├── read_until.rs │ ├── read_vectored.rs │ ├── repeat.rs │ ├── seek.rs │ ├── sink.rs │ ├── split.rs │ ├── take.rs │ ├── window.rs │ ├── write.rs │ ├── write_all.rs │ ├── write_all_vectored.rs │ └── write_vectored.rs │ ├── lib.rs │ ├── lock │ ├── bilock.rs │ ├── mod.rs │ └── mutex.rs │ ├── sink │ ├── buffer.rs │ ├── close.rs │ ├── drain.rs │ ├── err_into.rs │ ├── fanout.rs │ ├── feed.rs │ ├── flush.rs │ ├── map_err.rs │ ├── mod.rs │ ├── send.rs │ ├── send_all.rs │ ├── unfold.rs │ ├── with.rs │ └── with_flat_map.rs │ ├── stream │ ├── abortable.rs │ ├── empty.rs │ ├── futures_ordered.rs │ ├── futures_unordered │ │ ├── abort.rs │ │ ├── iter.rs │ │ ├── mod.rs │ │ ├── ready_to_run_queue.rs │ │ └── task.rs │ ├── iter.rs │ ├── mod.rs │ ├── once.rs │ ├── pending.rs │ ├── poll_fn.rs │ ├── poll_immediate.rs │ ├── repeat.rs │ ├── repeat_with.rs │ ├── select.rs │ ├── select_all.rs │ ├── select_with_strategy.rs │ ├── stream │ │ ├── all.rs │ │ ├── any.rs │ │ ├── buffer_unordered.rs │ │ ├── buffered.rs │ │ ├── catch_unwind.rs │ │ ├── chain.rs │ │ ├── chunks.rs │ │ ├── collect.rs │ │ ├── concat.rs │ │ ├── count.rs │ │ ├── cycle.rs │ │ ├── enumerate.rs │ │ ├── filter.rs │ │ ├── filter_map.rs │ │ ├── flatten.rs │ │ ├── flatten_unordered.rs │ │ ├── fold.rs │ │ ├── for_each.rs │ │ ├── for_each_concurrent.rs │ │ ├── forward.rs │ │ ├── fuse.rs │ │ ├── into_future.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── next.rs │ │ ├── peek.rs │ │ ├── ready_chunks.rs │ │ ├── scan.rs │ │ ├── select_next_some.rs │ │ ├── skip.rs │ │ ├── skip_while.rs │ │ ├── split.rs │ │ ├── take.rs │ │ ├── take_until.rs │ │ ├── take_while.rs │ │ ├── then.rs │ │ ├── try_fold.rs │ │ ├── try_for_each.rs │ │ ├── try_for_each_concurrent.rs │ │ ├── unzip.rs │ │ └── zip.rs │ ├── try_stream │ │ ├── and_then.rs │ │ ├── into_async_read.rs │ │ ├── into_stream.rs │ │ ├── mod.rs │ │ ├── or_else.rs │ │ ├── try_all.rs │ │ ├── try_any.rs │ │ ├── try_buffer_unordered.rs │ │ ├── try_buffered.rs │ │ ├── try_chunks.rs │ │ ├── try_collect.rs │ │ ├── try_concat.rs │ │ ├── try_filter.rs │ │ ├── try_filter_map.rs │ │ ├── try_flatten.rs │ │ ├── try_flatten_unordered.rs │ │ ├── try_forward.rs │ │ ├── try_next.rs │ │ ├── try_ready_chunks.rs │ │ ├── try_skip_while.rs │ │ ├── try_take_while.rs │ │ └── try_unfold.rs │ └── unfold.rs │ ├── task │ ├── mod.rs │ └── spawn.rs │ └── unfold_state.rs ├── futures ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── src │ └── lib.rs ├── tests │ ├── _require_features.rs │ ├── async_await_macros.rs │ ├── auto_traits.rs │ ├── bilock.rs │ ├── compat.rs │ ├── eager_drop.rs │ ├── eventual.rs │ ├── future_abortable.rs │ ├── future_basic_combinators.rs │ ├── future_fuse.rs │ ├── future_inspect.rs │ ├── future_join.rs │ ├── future_join_all.rs │ ├── future_obj.rs │ ├── future_select_all.rs │ ├── future_select_ok.rs │ ├── future_shared.rs │ ├── future_try_flatten_stream.rs │ ├── future_try_join_all.rs │ ├── io_buf_reader.rs │ ├── io_buf_writer.rs │ ├── io_cursor.rs │ ├── io_line_writer.rs │ ├── io_lines.rs │ ├── io_read.rs │ ├── io_read_exact.rs │ ├── io_read_line.rs │ ├── io_read_to_end.rs │ ├── io_read_to_string.rs │ ├── io_read_until.rs │ ├── io_window.rs │ ├── io_write.rs │ ├── lock_mutex.rs │ ├── macro-reexport │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── macro-tests │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── macro_comma_support.rs │ ├── no-std │ │ ├── Cargo.toml │ │ ├── build.rs │ │ └── src │ │ │ └── lib.rs │ ├── object_safety.rs │ ├── oneshot.rs │ ├── ready_queue.rs │ ├── recurse.rs │ ├── sink.rs │ ├── sink_fanout.rs │ ├── stream.rs │ ├── stream_abortable.rs │ ├── stream_buffer_unordered.rs │ ├── stream_catch_unwind.rs │ ├── stream_futures_ordered.rs │ ├── stream_futures_unordered.rs │ ├── stream_into_async_read.rs │ ├── stream_peekable.rs │ ├── stream_select_all.rs │ ├── stream_select_next_some.rs │ ├── stream_split.rs │ ├── stream_try_stream.rs │ ├── stream_unfold.rs │ ├── task_arc_wake.rs │ ├── task_atomic_waker.rs │ ├── test_macro.rs │ └── try_join.rs └── tests_disabled │ ├── all.rs │ └── stream.rs └── triagebot.toml /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.rs] 2 | end_of_line = lf 3 | insert_final_newline = true 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Cargo fmt all code 2 | dd019055ef5bf4309f15db934407e202caf52e14 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | commit-message: 8 | prefix: '' 9 | labels: [] 10 | - package-ecosystem: github-actions 11 | directory: / 12 | schedule: 13 | interval: weekly 14 | commit-message: 15 | prefix: '' 16 | labels: [] 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | **/*.rs.bk 3 | Cargo.lock 4 | _site 5 | .sass-cache 6 | .idea 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | use_small_heuristics = "Max" 2 | edition = "2018" 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "futures", 4 | "futures-core", 5 | "futures-channel", 6 | "futures-executor", 7 | "futures-io", 8 | "futures-macro", 9 | "futures-sink", 10 | "futures-task", 11 | "futures-util", 12 | "futures-test", 13 | 14 | "futures/tests/macro-tests", 15 | "futures/tests/macro-reexport", 16 | "futures/tests/no-std", 17 | 18 | "examples/functional", 19 | "examples/imperative", 20 | ] 21 | 22 | [workspace.lints.rust] 23 | missing_debug_implementations = "warn" 24 | rust_2018_idioms = "warn" 25 | single_use_lifetimes = "warn" 26 | unexpected_cfgs = { level = "warn", check-cfg = [ 27 | 'cfg(futures_sanitizer)', 28 | ] } 29 | unreachable_pub = "warn" 30 | # unsafe_op_in_unsafe_fn = "warn" # Set at crate-level instead since https://github.com/rust-lang/rust/pull/100081 is not available on MSRV 31 | [workspace.lints.clippy] 32 | incompatible_msrv = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/12273, https://github.com/rust-lang/rust-clippy/issues/12257 33 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Alex Crichton 2 | Copyright (c) 2017 The Tokio Authors 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | futures-rs 3 |

4 | 5 |

6 | Zero-cost asynchronous programming in Rust 7 |

8 | 9 |

10 | 11 | Build Status 12 | 13 | 14 | 15 | crates.io 16 | 17 |

18 | 19 |

20 | 21 | Documentation 22 | | 23 | Website 24 | 25 |

26 | 27 | `futures-rs` is a library providing the foundations for asynchronous programming in Rust. 28 | It includes key trait definitions like `Stream`, as well as utilities like `join!`, 29 | `select!`, and various futures combinator methods which enable expressive asynchronous 30 | control flow. 31 | 32 | ## Usage 33 | 34 | Add this to your `Cargo.toml`: 35 | 36 | ```toml 37 | [dependencies] 38 | futures = "0.3" 39 | ``` 40 | 41 | The current `futures` requires Rust 1.68 or later. 42 | 43 | ### Feature `std` 44 | 45 | Futures-rs works without the standard library, such as in bare metal environments. 46 | However, it has a significantly reduced API surface. To use futures-rs in 47 | a `#[no_std]` environment, use: 48 | 49 | ```toml 50 | [dependencies] 51 | futures = { version = "0.3", default-features = false } 52 | ``` 53 | 54 | ## License 55 | 56 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 57 | [MIT license](LICENSE-MIT) at your option. 58 | 59 | Unless you explicitly state otherwise, any contribution intentionally submitted 60 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 61 | be dual licensed as above, without any additional terms or conditions. 62 | -------------------------------------------------------------------------------- /examples/functional/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-example-functional" 3 | version = "0.0.0" 4 | edition = "2018" 5 | publish = false 6 | 7 | [dependencies] 8 | futures = { path = "../../futures", features = ["thread-pool"] } 9 | 10 | [lints] 11 | workspace = true 12 | -------------------------------------------------------------------------------- /examples/functional/src/main.rs: -------------------------------------------------------------------------------- 1 | use futures::channel::mpsc; 2 | use futures::executor; //standard executors to provide a context for futures and streams 3 | use futures::executor::ThreadPool; 4 | use futures::StreamExt; 5 | 6 | fn main() { 7 | let pool = ThreadPool::new().expect("Failed to build pool"); 8 | let (tx, rx) = mpsc::unbounded::(); 9 | 10 | // Create a future by an async block, where async is responsible for an 11 | // implementation of Future. At this point no executor has been provided 12 | // to this future, so it will not be running. 13 | let fut_values = async { 14 | // Create another async block, again where the Future implementation 15 | // is generated by async. Since this is inside of a parent async block, 16 | // it will be provided with the executor of the parent block when the parent 17 | // block is executed. 18 | // 19 | // This executor chaining is done by Future::poll whose second argument 20 | // is a std::task::Context. This represents our executor, and the Future 21 | // implemented by this async block can be polled using the parent async 22 | // block's executor. 23 | let fut_tx_result = async move { 24 | (0..100).for_each(|v| { 25 | tx.unbounded_send(v).expect("Failed to send"); 26 | }) 27 | }; 28 | 29 | // Use the provided thread pool to spawn the generated future 30 | // responsible for transmission 31 | pool.spawn_ok(fut_tx_result); 32 | 33 | let fut_values = rx.map(|v| v * 2).collect(); 34 | 35 | // Use the executor provided to this async block to wait for the 36 | // future to complete. 37 | fut_values.await 38 | }; 39 | 40 | // Actually execute the above future, which will invoke Future::poll and 41 | // subsequently chain appropriate Future::poll and methods needing executors 42 | // to drive all futures. Eventually fut_values will be driven to completion. 43 | let values: Vec = executor::block_on(fut_values); 44 | 45 | println!("Values={values:?}"); 46 | } 47 | -------------------------------------------------------------------------------- /examples/imperative/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-example-imperative" 3 | version = "0.0.0" 4 | edition = "2018" 5 | publish = false 6 | 7 | [dependencies] 8 | futures = { path = "../../futures", features = ["thread-pool"] } 9 | 10 | [lints] 11 | workspace = true 12 | -------------------------------------------------------------------------------- /examples/imperative/src/main.rs: -------------------------------------------------------------------------------- 1 | use futures::channel::mpsc; 2 | use futures::executor; //standard executors to provide a context for futures and streams 3 | use futures::executor::ThreadPool; 4 | use futures::StreamExt; 5 | 6 | fn main() { 7 | let pool = ThreadPool::new().expect("Failed to build pool"); 8 | let (tx, mut rx) = mpsc::unbounded::(); 9 | 10 | // Create a future by an async block, where async is responsible for generating 11 | // an implementation of Future. At this point no executor has been provided 12 | // to this future, so it will not be running. 13 | let fut_values = async { 14 | // Create another async block, again where Future is implemented by 15 | // async. Since this is inside of a parent async block, it will be 16 | // provided with the executor of the parent block when the parent 17 | // block is executed. 18 | // 19 | // This executor chaining is done by Future::poll whose second argument 20 | // is a std::task::Context. This represents our executor, and the Future 21 | // implemented by this async block can be polled using the parent async 22 | // block's executor. 23 | let fut_tx_result = async move { 24 | (0..100).for_each(|v| { 25 | tx.unbounded_send(v).expect("Failed to send"); 26 | }) 27 | }; 28 | 29 | // Use the provided thread pool to spawn the transmission 30 | pool.spawn_ok(fut_tx_result); 31 | 32 | let mut pending = vec![]; 33 | // Use the provided executor to wait for the next value 34 | // of the stream to be available. 35 | while let Some(v) = rx.next().await { 36 | pending.push(v * 2); 37 | } 38 | 39 | pending 40 | }; 41 | 42 | // Actually execute the above future, which will invoke Future::poll and 43 | // subsequently chain appropriate Future::poll and methods needing executors 44 | // to drive all futures. Eventually fut_values will be driven to completion. 45 | let values: Vec = executor::block_on(fut_values); 46 | 47 | println!("Values={values:?}"); 48 | } 49 | -------------------------------------------------------------------------------- /futures-channel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-channel" 3 | version = "0.4.0-alpha.0" 4 | edition = "2018" 5 | rust-version = "1.68" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rust-lang/futures-rs" 8 | homepage = "https://rust-lang.github.io/futures-rs" 9 | description = """ 10 | Channels for asynchronous communication using futures-rs. 11 | """ 12 | 13 | [features] 14 | default = ["std"] 15 | std = ["alloc", "futures-core/std"] 16 | alloc = ["futures-core/alloc"] 17 | sink = ["futures-sink"] 18 | 19 | [dependencies] 20 | futures-core = { path = "../futures-core", version = "=1.0.0-alpha.0", default-features = false } 21 | futures-sink = { path = "../futures-sink", version = "=0.4.0-alpha.0", default-features = false, optional = true } 22 | 23 | [dev-dependencies] 24 | futures = { path = "../futures", default-features = true } 25 | futures-test = { path = "../futures-test", default-features = true } 26 | 27 | [package.metadata.docs.rs] 28 | all-features = true 29 | rustdoc-args = ["--cfg", "docsrs"] 30 | 31 | [lints] 32 | workspace = true 33 | -------------------------------------------------------------------------------- /futures-channel/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-channel/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-channel/README.md: -------------------------------------------------------------------------------- 1 | # futures-channel 2 | 3 | Channels for asynchronous communication using futures-rs. 4 | 5 | ## Usage 6 | 7 | Add this to your `Cargo.toml`: 8 | 9 | ```toml 10 | [dependencies] 11 | futures-channel = "0.3" 12 | ``` 13 | 14 | The current `futures-channel` requires Rust 1.68 or later. 15 | 16 | ## License 17 | 18 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 19 | [MIT license](LICENSE-MIT) at your option. 20 | 21 | Unless you explicitly state otherwise, any contribution intentionally submitted 22 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 23 | be dual licensed as above, without any additional terms or conditions. 24 | -------------------------------------------------------------------------------- /futures-channel/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Asynchronous channels. 2 | //! 3 | //! Like threads, concurrent tasks sometimes need to communicate with each 4 | //! other. This module contains two basic abstractions for doing so: 5 | //! 6 | //! - [oneshot], a way of sending a single value from one task to another. 7 | //! - [mpsc], a multi-producer, single-consumer channel for sending values 8 | //! between tasks, analogous to the similarly-named structure in the standard 9 | //! library. 10 | //! 11 | //! All items are only available when the `std` or `alloc` feature of this 12 | //! library is activated, and it is activated by default. 13 | 14 | #![no_std] 15 | #![doc(test( 16 | no_crate_inject, 17 | attr( 18 | deny(warnings, rust_2018_idioms, single_use_lifetimes), 19 | allow(dead_code, unused_assignments, unused_variables) 20 | ) 21 | ))] 22 | #![warn(missing_docs, unsafe_op_in_unsafe_fn)] 23 | 24 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 25 | #[cfg(feature = "alloc")] 26 | extern crate alloc; 27 | #[cfg(feature = "std")] 28 | extern crate std; 29 | 30 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 31 | #[cfg(feature = "alloc")] 32 | mod lock; 33 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 34 | #[cfg(feature = "std")] 35 | pub mod mpsc; 36 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 37 | #[cfg(feature = "alloc")] 38 | pub mod oneshot; 39 | -------------------------------------------------------------------------------- /futures-channel/tests/channel.rs: -------------------------------------------------------------------------------- 1 | use futures::channel::mpsc; 2 | use futures::executor::block_on; 3 | use futures::future::poll_fn; 4 | use futures::sink::SinkExt; 5 | use futures::stream::StreamExt; 6 | use std::sync::atomic::{AtomicUsize, Ordering}; 7 | use std::thread; 8 | 9 | #[test] 10 | fn sequence() { 11 | let (tx, rx) = mpsc::channel(1); 12 | 13 | let amt = 20; 14 | let t = thread::spawn(move || block_on(send_sequence(amt, tx))); 15 | let list: Vec<_> = block_on(rx.collect()); 16 | let mut list = list.into_iter(); 17 | for i in (1..=amt).rev() { 18 | assert_eq!(list.next(), Some(i)); 19 | } 20 | assert_eq!(list.next(), None); 21 | 22 | t.join().unwrap(); 23 | } 24 | 25 | async fn send_sequence(n: u32, mut sender: mpsc::Sender) { 26 | for x in 0..n { 27 | sender.send(n - x).await.unwrap(); 28 | } 29 | } 30 | 31 | #[test] 32 | fn drop_sender() { 33 | let (tx, mut rx) = mpsc::channel::(1); 34 | drop(tx); 35 | let f = poll_fn(|cx| rx.poll_next_unpin(cx)); 36 | assert_eq!(block_on(f), None) 37 | } 38 | 39 | #[test] 40 | fn drop_rx() { 41 | let (mut tx, rx) = mpsc::channel::(1); 42 | block_on(tx.send(1)).unwrap(); 43 | drop(rx); 44 | assert!(block_on(tx.send(1)).is_err()); 45 | } 46 | 47 | #[test] 48 | fn drop_order() { 49 | static DROPS: AtomicUsize = AtomicUsize::new(0); 50 | let (mut tx, rx) = mpsc::channel(1); 51 | 52 | struct A; 53 | 54 | impl Drop for A { 55 | fn drop(&mut self) { 56 | DROPS.fetch_add(1, Ordering::SeqCst); 57 | } 58 | } 59 | 60 | block_on(tx.send(A)).unwrap(); 61 | assert_eq!(DROPS.load(Ordering::SeqCst), 0); 62 | drop(rx); 63 | assert_eq!(DROPS.load(Ordering::SeqCst), 1); 64 | assert!(block_on(tx.send(A)).is_err()); 65 | assert_eq!(DROPS.load(Ordering::SeqCst), 2); 66 | } 67 | -------------------------------------------------------------------------------- /futures-channel/tests/mpsc-size_hint.rs: -------------------------------------------------------------------------------- 1 | use futures::channel::mpsc; 2 | use futures::stream::Stream; 3 | 4 | #[test] 5 | fn unbounded_size_hint() { 6 | let (tx, mut rx) = mpsc::unbounded::(); 7 | assert_eq!((0, None), rx.size_hint()); 8 | tx.unbounded_send(1).unwrap(); 9 | assert_eq!((1, None), rx.size_hint()); 10 | rx.try_recv().unwrap(); 11 | assert_eq!((0, None), rx.size_hint()); 12 | tx.unbounded_send(2).unwrap(); 13 | tx.unbounded_send(3).unwrap(); 14 | assert_eq!((2, None), rx.size_hint()); 15 | drop(tx); 16 | assert_eq!((2, Some(2)), rx.size_hint()); 17 | rx.try_recv().unwrap(); 18 | assert_eq!((1, Some(1)), rx.size_hint()); 19 | rx.try_recv().unwrap(); 20 | assert_eq!((0, Some(0)), rx.size_hint()); 21 | } 22 | 23 | #[test] 24 | fn channel_size_hint() { 25 | let (mut tx, mut rx) = mpsc::channel::(10); 26 | assert_eq!((0, None), rx.size_hint()); 27 | tx.try_send(1).unwrap(); 28 | assert_eq!((1, None), rx.size_hint()); 29 | rx.try_recv().unwrap(); 30 | assert_eq!((0, None), rx.size_hint()); 31 | tx.try_send(2).unwrap(); 32 | tx.try_send(3).unwrap(); 33 | assert_eq!((2, None), rx.size_hint()); 34 | drop(tx); 35 | assert_eq!((2, Some(2)), rx.size_hint()); 36 | rx.try_recv().unwrap(); 37 | assert_eq!((1, Some(1)), rx.size_hint()); 38 | rx.try_recv().unwrap(); 39 | assert_eq!((0, Some(0)), rx.size_hint()); 40 | } 41 | -------------------------------------------------------------------------------- /futures-core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-core" 3 | version = "1.0.0-alpha.0" 4 | edition = "2018" 5 | rust-version = "1.36" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rust-lang/futures-rs" 8 | homepage = "https://rust-lang.github.io/futures-rs" 9 | description = """ 10 | The core traits and types in for the `futures` library. 11 | """ 12 | 13 | [features] 14 | default = ["std"] 15 | std = ["alloc"] 16 | alloc = [] 17 | 18 | [dependencies] 19 | portable-atomic = { version = "1.3", optional = true, default-features = false, features = ["require-cas"] } 20 | 21 | [dev-dependencies] 22 | futures = { path = "../futures" } 23 | 24 | [package.metadata.docs.rs] 25 | all-features = true 26 | rustdoc-args = ["--cfg", "docsrs"] 27 | 28 | [lints] 29 | workspace = true 30 | -------------------------------------------------------------------------------- /futures-core/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-core/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-core/README.md: -------------------------------------------------------------------------------- 1 | # futures-core 2 | 3 | The core traits and types in for the `futures` library. 4 | 5 | ## Usage 6 | 7 | Add this to your `Cargo.toml`: 8 | 9 | ```toml 10 | [dependencies] 11 | futures-core = "0.3" 12 | ``` 13 | 14 | The current `futures-core` requires Rust 1.36 or later. 15 | 16 | ## License 17 | 18 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 19 | [MIT license](LICENSE-MIT) at your option. 20 | 21 | Unless you explicitly state otherwise, any contribution intentionally submitted 22 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 23 | be dual licensed as above, without any additional terms or conditions. 24 | -------------------------------------------------------------------------------- /futures-core/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Core traits and types for asynchronous operations in Rust. 2 | 3 | #![no_std] 4 | #![doc(test( 5 | no_crate_inject, 6 | attr( 7 | deny(warnings, rust_2018_idioms, single_use_lifetimes), 8 | allow(dead_code, unused_assignments, unused_variables) 9 | ) 10 | ))] 11 | #![warn(missing_docs, /* unsafe_op_in_unsafe_fn */)] // unsafe_op_in_unsafe_fn requires Rust 1.52 12 | 13 | #[cfg(feature = "alloc")] 14 | extern crate alloc; 15 | #[cfg(feature = "std")] 16 | extern crate std; 17 | 18 | pub mod future; 19 | #[doc(no_inline)] 20 | pub use self::future::{FusedFuture, Future, TryFuture}; 21 | 22 | pub mod stream; 23 | #[doc(no_inline)] 24 | pub use self::stream::{FusedStream, Stream, TryStream}; 25 | 26 | #[macro_use] 27 | pub mod task; 28 | -------------------------------------------------------------------------------- /futures-core/src/task/__internal/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg_attr(target_os = "none", cfg(any(target_has_atomic = "ptr", feature = "portable-atomic")))] 2 | mod atomic_waker; 3 | #[cfg_attr( 4 | target_os = "none", 5 | cfg(any(target_has_atomic = "ptr", feature = "portable-atomic")) 6 | )] 7 | pub use self::atomic_waker::AtomicWaker; 8 | -------------------------------------------------------------------------------- /futures-core/src/task/mod.rs: -------------------------------------------------------------------------------- 1 | //! Task notification. 2 | 3 | #[macro_use] 4 | mod poll; 5 | 6 | #[doc(hidden)] 7 | pub mod __internal; 8 | 9 | #[doc(no_inline)] 10 | pub use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; 11 | -------------------------------------------------------------------------------- /futures-core/src/task/poll.rs: -------------------------------------------------------------------------------- 1 | /// Extracts the successful type of `Poll`. 2 | /// 3 | /// This macro bakes in propagation of `Pending` signals by returning early. 4 | /// 5 | /// **Note:** Since Rust 1.64, this macro is soft-deprecated in favor of 6 | /// [`ready!`](core::task::ready) macro in the standard library. 7 | #[macro_export] 8 | macro_rules! ready { 9 | ($e:expr $(,)?) => { 10 | match $e { 11 | $crate::task::Poll::Ready(t) => t, 12 | $crate::task::Poll::Pending => return $crate::task::Poll::Pending, 13 | } 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /futures-executor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-executor" 3 | version = "0.4.0-alpha.0" 4 | edition = "2018" 5 | rust-version = "1.68" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rust-lang/futures-rs" 8 | homepage = "https://rust-lang.github.io/futures-rs" 9 | description = """ 10 | Executors for asynchronous tasks based on the futures-rs library. 11 | """ 12 | 13 | [features] 14 | default = ["std"] 15 | std = ["futures-core/std", "futures-task/std", "futures-util/std"] 16 | thread-pool = ["std"] 17 | 18 | [dependencies] 19 | futures-core = { path = "../futures-core", version = "=1.0.0-alpha.0", default-features = false } 20 | futures-task = { path = "../futures-task", version = "=0.4.0-alpha.0", default-features = false } 21 | futures-util = { path = "../futures-util", version = "=0.4.0-alpha.0", default-features = false } 22 | 23 | [dev-dependencies] 24 | futures = { path = "../futures", features = ["thread-pool"] } 25 | 26 | [package.metadata.docs.rs] 27 | all-features = true 28 | rustdoc-args = ["--cfg", "docsrs"] 29 | 30 | [lints] 31 | workspace = true 32 | -------------------------------------------------------------------------------- /futures-executor/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-executor/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-executor/README.md: -------------------------------------------------------------------------------- 1 | # futures-executor 2 | 3 | Executors for asynchronous tasks based on the futures-rs library. 4 | 5 | ## Usage 6 | 7 | Add this to your `Cargo.toml`: 8 | 9 | ```toml 10 | [dependencies] 11 | futures-executor = "0.3" 12 | ``` 13 | 14 | The current `futures-executor` requires Rust 1.68 or later. 15 | 16 | ## License 17 | 18 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 19 | [MIT license](LICENSE-MIT) at your option. 20 | 21 | Unless you explicitly state otherwise, any contribution intentionally submitted 22 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 23 | be dual licensed as above, without any additional terms or conditions. 24 | -------------------------------------------------------------------------------- /futures-io/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-io" 3 | version = "0.3.31" 4 | edition = "2018" 5 | rust-version = "1.36" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rust-lang/futures-rs" 8 | homepage = "https://rust-lang.github.io/futures-rs" 9 | description = """ 10 | The `AsyncRead`, `AsyncWrite`, `AsyncSeek`, and `AsyncBufRead` traits for the futures-rs library. 11 | """ 12 | 13 | [features] 14 | default = ["std"] 15 | std = [] 16 | 17 | # Unstable features 18 | # These features are outside of the normal semver guarantees and require the 19 | # `unstable` feature as an explicit opt-in to unstable API. 20 | unstable = [] 21 | 22 | [dependencies] 23 | 24 | [package.metadata.docs.rs] 25 | all-features = true 26 | rustdoc-args = ["--cfg", "docsrs"] 27 | 28 | [lints] 29 | workspace = true 30 | -------------------------------------------------------------------------------- /futures-io/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-io/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-io/README.md: -------------------------------------------------------------------------------- 1 | # futures-io 2 | 3 | The `AsyncRead`, `AsyncWrite`, `AsyncSeek`, and `AsyncBufRead` traits for the futures-rs library. 4 | 5 | ## Usage 6 | 7 | Add this to your `Cargo.toml`: 8 | 9 | ```toml 10 | [dependencies] 11 | futures-io = "0.3" 12 | ``` 13 | 14 | The current `futures-io` requires Rust 1.36 or later. 15 | 16 | ## License 17 | 18 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 19 | [MIT license](LICENSE-MIT) at your option. 20 | 21 | Unless you explicitly state otherwise, any contribution intentionally submitted 22 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 23 | be dual licensed as above, without any additional terms or conditions. 24 | -------------------------------------------------------------------------------- /futures-macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-macro" 3 | version = "0.4.0-alpha.0" 4 | edition = "2018" 5 | rust-version = "1.68" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rust-lang/futures-rs" 8 | homepage = "https://rust-lang.github.io/futures-rs" 9 | description = """ 10 | The futures-rs procedural macro implementations. 11 | """ 12 | 13 | [lib] 14 | proc-macro = true 15 | 16 | [features] 17 | 18 | [dependencies] 19 | proc-macro2 = "1.0.60" 20 | quote = "1.0" 21 | syn = { version = "2.0.52", features = ["full"] } 22 | 23 | [lints] 24 | workspace = true 25 | -------------------------------------------------------------------------------- /futures-macro/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-macro/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-macro/src/executor.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | use proc_macro2::Span; 3 | use quote::{quote, quote_spanned, ToTokens}; 4 | 5 | pub(crate) fn test(args: TokenStream, item: TokenStream) -> TokenStream { 6 | if !args.is_empty() { 7 | return syn::Error::new_spanned(proc_macro2::TokenStream::from(args), "invalid argument") 8 | .to_compile_error() 9 | .into(); 10 | } 11 | 12 | let mut input = syn::parse_macro_input!(item as syn::ItemFn); 13 | 14 | if input.sig.asyncness.take().is_none() { 15 | return syn::Error::new_spanned(input.sig.fn_token, "Only async functions are supported") 16 | .to_compile_error() 17 | .into(); 18 | } 19 | 20 | // If type mismatch occurs, the current rustc points to the last statement. 21 | let (last_stmt_start_span, last_stmt_end_span) = { 22 | let mut last_stmt = input 23 | .block 24 | .stmts 25 | .last() 26 | .map(ToTokens::into_token_stream) 27 | .unwrap_or_default() 28 | .into_iter(); 29 | // `Span` on stable Rust has a limitation that only points to the first 30 | // token, not the whole tokens. We can work around this limitation by 31 | // using the first/last span of the tokens like 32 | // `syn::Error::new_spanned` does. 33 | let start = last_stmt.next().map_or_else(Span::call_site, |t| t.span()); 34 | let end = last_stmt.last().map_or(start, |t| t.span()); 35 | (start, end) 36 | }; 37 | 38 | let path = quote_spanned! {last_stmt_start_span=> 39 | ::futures_test::__private 40 | }; 41 | let body = &input.block; 42 | input.block.stmts = vec![syn::Stmt::Expr( 43 | syn::parse2(quote_spanned! {last_stmt_end_span=> 44 | #path::block_on(async #body) 45 | }) 46 | .unwrap(), 47 | None, 48 | )]; 49 | 50 | let gen = quote! { 51 | #[::core::prelude::v1::test] 52 | #input 53 | }; 54 | 55 | gen.into() 56 | } 57 | -------------------------------------------------------------------------------- /futures-macro/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! The futures-rs procedural macro implementations. 2 | 3 | #![doc(test( 4 | no_crate_inject, 5 | attr( 6 | deny(warnings, rust_2018_idioms, single_use_lifetimes), 7 | allow(dead_code, unused_assignments, unused_variables) 8 | ) 9 | ))] 10 | 11 | use proc_macro::TokenStream; 12 | 13 | mod executor; 14 | mod join; 15 | mod select; 16 | mod stream_select; 17 | 18 | /// The `join!` macro. 19 | #[proc_macro] 20 | pub fn join_internal(input: TokenStream) -> TokenStream { 21 | crate::join::join(input) 22 | } 23 | 24 | /// The `try_join!` macro. 25 | #[proc_macro] 26 | pub fn try_join_internal(input: TokenStream) -> TokenStream { 27 | crate::join::try_join(input) 28 | } 29 | 30 | /// The `select!` macro. 31 | #[proc_macro] 32 | pub fn select_internal(input: TokenStream) -> TokenStream { 33 | crate::select::select(input) 34 | } 35 | 36 | /// The `select_biased!` macro. 37 | #[proc_macro] 38 | pub fn select_biased_internal(input: TokenStream) -> TokenStream { 39 | crate::select::select_biased(input) 40 | } 41 | 42 | // TODO: Change this to doc comment once rustdoc bug fixed: https://github.com/rust-lang/futures-rs/pull/2435 43 | // The `test` attribute. 44 | #[proc_macro_attribute] 45 | pub fn test_internal(input: TokenStream, item: TokenStream) -> TokenStream { 46 | crate::executor::test(input, item) 47 | } 48 | 49 | /// The `stream_select!` macro. 50 | #[proc_macro] 51 | pub fn stream_select_internal(input: TokenStream) -> TokenStream { 52 | crate::stream_select::stream_select(input.into()) 53 | .unwrap_or_else(syn::Error::into_compile_error) 54 | .into() 55 | } 56 | -------------------------------------------------------------------------------- /futures-sink/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-sink" 3 | version = "0.4.0-alpha.0" 4 | edition = "2018" 5 | rust-version = "1.36" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rust-lang/futures-rs" 8 | homepage = "https://rust-lang.github.io/futures-rs" 9 | description = """ 10 | The asynchronous `Sink` trait for the futures-rs library. 11 | """ 12 | 13 | [features] 14 | default = ["std"] 15 | std = ["alloc"] 16 | alloc = [] 17 | 18 | [dependencies] 19 | 20 | [package.metadata.docs.rs] 21 | all-features = true 22 | 23 | [lints] 24 | workspace = true 25 | -------------------------------------------------------------------------------- /futures-sink/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-sink/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-sink/README.md: -------------------------------------------------------------------------------- 1 | # futures-sink 2 | 3 | The asynchronous `Sink` trait for the futures-rs library. 4 | 5 | ## Usage 6 | 7 | Add this to your `Cargo.toml`: 8 | 9 | ```toml 10 | [dependencies] 11 | futures-sink = "0.3" 12 | ``` 13 | 14 | The current `futures-sink` requires Rust 1.36 or later. 15 | 16 | ## License 17 | 18 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 19 | [MIT license](LICENSE-MIT) at your option. 20 | 21 | Unless you explicitly state otherwise, any contribution intentionally submitted 22 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 23 | be dual licensed as above, without any additional terms or conditions. 24 | -------------------------------------------------------------------------------- /futures-task/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-task" 3 | version = "0.4.0-alpha.0" 4 | edition = "2018" 5 | rust-version = "1.68" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rust-lang/futures-rs" 8 | homepage = "https://rust-lang.github.io/futures-rs" 9 | description = """ 10 | Tools for working with tasks. 11 | """ 12 | 13 | [features] 14 | default = ["std"] 15 | std = ["alloc"] 16 | alloc = [] 17 | 18 | [dependencies] 19 | 20 | [dev-dependencies] 21 | futures = { path = "../futures" } 22 | 23 | [package.metadata.docs.rs] 24 | all-features = true 25 | 26 | [lints] 27 | workspace = true 28 | -------------------------------------------------------------------------------- /futures-task/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-task/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-task/README.md: -------------------------------------------------------------------------------- 1 | # futures-task 2 | 3 | Tools for working with tasks. 4 | 5 | ## Usage 6 | 7 | Add this to your `Cargo.toml`: 8 | 9 | ```toml 10 | [dependencies] 11 | futures-task = "0.3" 12 | ``` 13 | 14 | The current `futures-task` requires Rust 1.68 or later. 15 | 16 | ## License 17 | 18 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 19 | [MIT license](LICENSE-MIT) at your option. 20 | 21 | Unless you explicitly state otherwise, any contribution intentionally submitted 22 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 23 | be dual licensed as above, without any additional terms or conditions. 24 | -------------------------------------------------------------------------------- /futures-task/src/arc_wake.rs: -------------------------------------------------------------------------------- 1 | use alloc::sync::Arc; 2 | 3 | /// A way of waking up a specific task. 4 | /// 5 | /// By implementing this trait, types that are expected to be wrapped in an `Arc` 6 | /// can be converted into [`Waker`] objects. 7 | /// Those Wakers can be used to signal executors that a task it owns 8 | /// is ready to be `poll`ed again. 9 | /// 10 | /// Currently, there are two ways to convert `ArcWake` into [`Waker`]: 11 | /// 12 | /// * [`waker`](super::waker()) converts `Arc` into [`Waker`]. 13 | /// * [`waker_ref`](super::waker_ref()) converts `&Arc` into [`WakerRef`] that 14 | /// provides access to a [`&Waker`][`Waker`]. 15 | /// 16 | /// [`Waker`]: std::task::Waker 17 | /// [`WakerRef`]: super::WakerRef 18 | // Note: Send + Sync required because `Arc` doesn't automatically imply 19 | // those bounds, but `Waker` implements them. 20 | pub trait ArcWake: Send + Sync { 21 | /// Indicates that the associated task is ready to make progress and should 22 | /// be `poll`ed. 23 | /// 24 | /// This function can be called from an arbitrary thread, including threads which 25 | /// did not create the `ArcWake` based [`Waker`]. 26 | /// 27 | /// Executors generally maintain a queue of "ready" tasks; `wake` should place 28 | /// the associated task onto this queue. 29 | /// 30 | /// [`Waker`]: std::task::Waker 31 | fn wake(self: Arc) { 32 | Self::wake_by_ref(&self) 33 | } 34 | 35 | /// Indicates that the associated task is ready to make progress and should 36 | /// be `poll`ed. 37 | /// 38 | /// This function can be called from an arbitrary thread, including threads which 39 | /// did not create the `ArcWake` based [`Waker`]. 40 | /// 41 | /// Executors generally maintain a queue of "ready" tasks; `wake_by_ref` should place 42 | /// the associated task onto this queue. 43 | /// 44 | /// This function is similar to [`wake`](ArcWake::wake), but must not consume the provided data 45 | /// pointer. 46 | /// 47 | /// [`Waker`]: std::task::Waker 48 | fn wake_by_ref(arc_self: &Arc); 49 | } 50 | -------------------------------------------------------------------------------- /futures-task/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Tools for working with tasks. 2 | 3 | #![no_std] 4 | #![doc(test( 5 | no_crate_inject, 6 | attr( 7 | deny(warnings, rust_2018_idioms, single_use_lifetimes), 8 | allow(dead_code, unused_assignments, unused_variables) 9 | ) 10 | ))] 11 | #![warn(missing_docs, unsafe_op_in_unsafe_fn)] 12 | 13 | #[cfg(feature = "alloc")] 14 | extern crate alloc; 15 | #[cfg(feature = "std")] 16 | extern crate std; 17 | 18 | mod spawn; 19 | pub use crate::spawn::{LocalSpawn, Spawn, SpawnError}; 20 | 21 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 22 | #[cfg(feature = "alloc")] 23 | mod arc_wake; 24 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 25 | #[cfg(feature = "alloc")] 26 | pub use crate::arc_wake::ArcWake; 27 | 28 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 29 | #[cfg(feature = "alloc")] 30 | mod waker; 31 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 32 | #[cfg(feature = "alloc")] 33 | pub use crate::waker::waker; 34 | 35 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 36 | #[cfg(feature = "alloc")] 37 | mod waker_ref; 38 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 39 | #[cfg(feature = "alloc")] 40 | pub use crate::waker_ref::{waker_ref, WakerRef}; 41 | 42 | mod future_obj; 43 | pub use crate::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj}; 44 | 45 | mod noop_waker; 46 | pub use crate::noop_waker::noop_waker; 47 | pub use crate::noop_waker::noop_waker_ref; 48 | 49 | #[doc(no_inline)] 50 | pub use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; 51 | -------------------------------------------------------------------------------- /futures-task/src/noop_waker.rs: -------------------------------------------------------------------------------- 1 | //! Utilities for creating zero-cost wakers that don't do anything. 2 | 3 | use core::ptr::null; 4 | use core::task::{RawWaker, RawWakerVTable, Waker}; 5 | 6 | unsafe fn noop_clone(_data: *const ()) -> RawWaker { 7 | noop_raw_waker() 8 | } 9 | 10 | unsafe fn noop(_data: *const ()) {} 11 | 12 | const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop); 13 | 14 | const fn noop_raw_waker() -> RawWaker { 15 | RawWaker::new(null(), &NOOP_WAKER_VTABLE) 16 | } 17 | 18 | /// Create a new [`Waker`] which does 19 | /// nothing when `wake()` is called on it. 20 | /// 21 | /// # Examples 22 | /// 23 | /// ``` 24 | /// use futures::task::noop_waker; 25 | /// let waker = noop_waker(); 26 | /// waker.wake(); 27 | /// ``` 28 | #[inline] 29 | pub fn noop_waker() -> Waker { 30 | // FIXME: Since 1.46.0 we can use transmute in consts, allowing this function to be const. 31 | unsafe { Waker::from_raw(noop_raw_waker()) } 32 | } 33 | 34 | /// Get a static reference to a [`Waker`] which 35 | /// does nothing when `wake()` is called on it. 36 | /// 37 | /// # Examples 38 | /// 39 | /// ``` 40 | /// use futures::task::noop_waker_ref; 41 | /// let waker = noop_waker_ref(); 42 | /// waker.wake_by_ref(); 43 | /// ``` 44 | #[inline] 45 | pub fn noop_waker_ref() -> &'static Waker { 46 | struct SyncRawWaker(RawWaker); 47 | unsafe impl Sync for SyncRawWaker {} 48 | 49 | static NOOP_WAKER_INSTANCE: SyncRawWaker = SyncRawWaker(noop_raw_waker()); 50 | 51 | // SAFETY: `Waker` is #[repr(transparent)] over its `RawWaker`. 52 | unsafe { &*(&NOOP_WAKER_INSTANCE.0 as *const RawWaker as *const Waker) } 53 | } 54 | 55 | #[cfg(test)] 56 | mod tests { 57 | #[test] 58 | #[cfg(feature = "std")] 59 | fn issue_2091_cross_thread_segfault() { 60 | let waker = std::thread::spawn(super::noop_waker_ref).join().unwrap(); 61 | waker.wake_by_ref(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /futures-task/src/waker.rs: -------------------------------------------------------------------------------- 1 | use super::arc_wake::ArcWake; 2 | use alloc::sync::Arc; 3 | use core::mem; 4 | use core::task::{RawWaker, RawWakerVTable, Waker}; 5 | 6 | pub(super) fn waker_vtable() -> &'static RawWakerVTable { 7 | &RawWakerVTable::new( 8 | clone_arc_raw::, 9 | wake_arc_raw::, 10 | wake_by_ref_arc_raw::, 11 | drop_arc_raw::, 12 | ) 13 | } 14 | 15 | /// Creates a [`Waker`] from an `Arc`. 16 | /// 17 | /// The returned [`Waker`] will call 18 | /// [`ArcWake.wake()`](ArcWake::wake) if awoken. 19 | pub fn waker(wake: Arc) -> Waker 20 | where 21 | W: ArcWake + 'static, 22 | { 23 | let ptr = Arc::into_raw(wake).cast::<()>(); 24 | 25 | unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::())) } 26 | } 27 | 28 | // FIXME: panics on Arc::clone / refcount changes could wreak havoc on the 29 | // code here. We should guard against this by aborting. 30 | 31 | unsafe fn increase_refcount(data: *const ()) { 32 | // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop 33 | let arc = mem::ManuallyDrop::new(unsafe { Arc::::from_raw(data.cast::()) }); 34 | // Now increase refcount, but don't drop new refcount either 35 | let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); 36 | } 37 | 38 | // used by `waker_ref` 39 | #[inline(always)] 40 | unsafe fn clone_arc_raw(data: *const ()) -> RawWaker { 41 | unsafe { increase_refcount::(data) } 42 | RawWaker::new(data, waker_vtable::()) 43 | } 44 | 45 | unsafe fn wake_arc_raw(data: *const ()) { 46 | let arc: Arc = unsafe { Arc::from_raw(data.cast::()) }; 47 | ArcWake::wake(arc); 48 | } 49 | 50 | // used by `waker_ref` 51 | unsafe fn wake_by_ref_arc_raw(data: *const ()) { 52 | // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop 53 | let arc = mem::ManuallyDrop::new(unsafe { Arc::::from_raw(data.cast::()) }); 54 | ArcWake::wake_by_ref(&arc); 55 | } 56 | 57 | unsafe fn drop_arc_raw(data: *const ()) { 58 | drop(unsafe { Arc::::from_raw(data.cast::()) }) 59 | } 60 | -------------------------------------------------------------------------------- /futures-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "futures-test" 3 | version = "0.4.0-alpha.0" 4 | edition = "2018" 5 | rust-version = "1.68" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rust-lang/futures-rs" 8 | homepage = "https://rust-lang.github.io/futures-rs" 9 | description = """ 10 | Common utilities for testing components built off futures-rs. 11 | """ 12 | 13 | [dependencies] 14 | futures-core = { version = "=1.0.0-alpha.0", path = "../futures-core", default-features = false } 15 | futures-task = { version = "=0.4.0-alpha.0", path = "../futures-task", default-features = false } 16 | futures-io = { version = "0.3.31", path = "../futures-io", default-features = false } 17 | futures-util = { version = "=0.4.0-alpha.0", path = "../futures-util", default-features = false } 18 | futures-executor = { version = "=0.4.0-alpha.0", path = "../futures-executor", default-features = false } 19 | futures-sink = { version = "=0.4.0-alpha.0", path = "../futures-sink", default-features = false } 20 | futures-macro = { version = "=0.4.0-alpha.0", path = "../futures-macro", default-features = false } 21 | pin-project = "1.0.11" 22 | 23 | [dev-dependencies] 24 | futures = { path = "../futures", default-features = false, features = ["std", "executor"] } 25 | 26 | [features] 27 | default = ["std"] 28 | std = ["futures-core/std", "futures-task/std", "futures-io/std", "futures-util/std", "futures-util/io", "futures-executor/std"] 29 | 30 | [package.metadata.docs.rs] 31 | all-features = true 32 | 33 | [lints] 34 | workspace = true 35 | -------------------------------------------------------------------------------- /futures-test/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-test/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-test/README.md: -------------------------------------------------------------------------------- 1 | # futures-test 2 | 3 | Common utilities for testing components built off futures-rs. 4 | 5 | ## Usage 6 | 7 | Add this to your `Cargo.toml`: 8 | 9 | ```toml 10 | [dependencies] 11 | futures-test = "0.3" 12 | ``` 13 | 14 | The current `futures-test` requires Rust 1.68 or later. 15 | 16 | ## License 17 | 18 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 19 | [MIT license](LICENSE-MIT) at your option. 20 | 21 | Unless you explicitly state otherwise, any contribution intentionally submitted 22 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 23 | be dual licensed as above, without any additional terms or conditions. 24 | -------------------------------------------------------------------------------- /futures-test/src/future/pending_once.rs: -------------------------------------------------------------------------------- 1 | use futures_core::future::{FusedFuture, Future}; 2 | use futures_core::task::{Context, Poll}; 3 | use pin_project::pin_project; 4 | use std::pin::Pin; 5 | 6 | /// Combinator that guarantees one [`Poll::Pending`] before polling its inner 7 | /// future. 8 | /// 9 | /// This is created by the 10 | /// [`FutureTestExt::pending_once`](super::FutureTestExt::pending_once) 11 | /// method. 12 | #[pin_project] 13 | #[derive(Debug, Clone)] 14 | #[must_use = "futures do nothing unless you `.await` or poll them"] 15 | pub struct PendingOnce { 16 | #[pin] 17 | future: Fut, 18 | polled_before: bool, 19 | } 20 | 21 | impl PendingOnce { 22 | pub(super) fn new(future: Fut) -> Self { 23 | Self { future, polled_before: false } 24 | } 25 | } 26 | 27 | impl Future for PendingOnce { 28 | type Output = Fut::Output; 29 | 30 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 31 | let this = self.project(); 32 | if *this.polled_before { 33 | this.future.poll(cx) 34 | } else { 35 | *this.polled_before = true; 36 | cx.waker().wake_by_ref(); 37 | Poll::Pending 38 | } 39 | } 40 | } 41 | 42 | impl FusedFuture for PendingOnce { 43 | fn is_terminated(&self) -> bool { 44 | self.polled_before && self.future.is_terminated() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /futures-test/src/io/mod.rs: -------------------------------------------------------------------------------- 1 | //! Additional combinators for testing async IO. 2 | 3 | mod limited; 4 | 5 | pub mod read; 6 | pub use read::AsyncReadTestExt; 7 | 8 | pub mod write; 9 | pub use write::AsyncWriteTestExt; 10 | -------------------------------------------------------------------------------- /futures-test/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Utilities to make testing [`Future`s](futures_core::future::Future) easier 2 | 3 | #![doc(test( 4 | no_crate_inject, 5 | attr( 6 | deny(warnings, rust_2018_idioms, single_use_lifetimes), 7 | allow(dead_code, unused_assignments, unused_variables) 8 | ) 9 | ))] 10 | #![warn(missing_docs, unsafe_op_in_unsafe_fn)] 11 | #![allow(clippy::test_attr_in_doctest)] 12 | 13 | #[cfg(not(feature = "std"))] 14 | compile_error!( 15 | "`futures-test` must have the `std` feature activated, this is a default-active feature" 16 | ); 17 | 18 | // Not public API. 19 | #[doc(hidden)] 20 | #[cfg(feature = "std")] 21 | pub mod __private { 22 | pub use futures_core::{future, stream, task}; 23 | pub use futures_executor::block_on; 24 | pub use std::{ 25 | option::Option::{None, Some}, 26 | pin::Pin, 27 | result::Result::{Err, Ok}, 28 | }; 29 | 30 | pub mod assert { 31 | pub use crate::assert::*; 32 | } 33 | } 34 | 35 | #[macro_use] 36 | #[cfg(feature = "std")] 37 | mod assert; 38 | 39 | #[cfg(feature = "std")] 40 | pub mod task; 41 | 42 | #[cfg(feature = "std")] 43 | pub mod future; 44 | 45 | #[cfg(feature = "std")] 46 | pub mod stream; 47 | 48 | #[cfg(feature = "std")] 49 | pub mod sink; 50 | 51 | #[cfg(feature = "std")] 52 | pub mod io; 53 | 54 | mod assert_unmoved; 55 | mod interleave_pending; 56 | mod track_closed; 57 | 58 | /// Enables an `async` test function. The generated future will be run to completion with 59 | /// [`futures_executor::block_on`]. 60 | /// 61 | /// ``` 62 | /// #[futures_test::test] 63 | /// async fn my_test() { 64 | /// let fut = async { true }; 65 | /// assert!(fut.await); 66 | /// } 67 | /// ``` 68 | /// 69 | /// This is equivalent to the following code: 70 | /// 71 | /// ``` 72 | /// #[test] 73 | /// fn my_test() { 74 | /// futures::executor::block_on(async move { 75 | /// let fut = async { true }; 76 | /// assert!(fut.await); 77 | /// }) 78 | /// } 79 | /// ``` 80 | #[cfg(feature = "std")] 81 | pub use futures_macro::test_internal as test; 82 | -------------------------------------------------------------------------------- /futures-test/src/stream/mod.rs: -------------------------------------------------------------------------------- 1 | //! Additional combinators for testing streams. 2 | 3 | use futures_core::stream::Stream; 4 | 5 | pub use crate::assert_unmoved::AssertUnmoved; 6 | pub use crate::interleave_pending::InterleavePending; 7 | 8 | /// Additional combinators for testing streams. 9 | pub trait StreamTestExt: Stream { 10 | /// Asserts that the given is not moved after being polled. 11 | /// 12 | /// A check for movement is performed each time the stream is polled 13 | /// and when `Drop` is called. 14 | /// 15 | /// Aside from keeping track of the location at which the stream was first 16 | /// polled and providing assertions, this stream adds no runtime behavior 17 | /// and simply delegates to the child stream. 18 | fn assert_unmoved(self) -> AssertUnmoved 19 | where 20 | Self: Sized, 21 | { 22 | AssertUnmoved::new(self) 23 | } 24 | 25 | /// Introduces an extra [`Poll::Pending`](futures_core::task::Poll::Pending) 26 | /// in between each item of the stream. 27 | /// 28 | /// # Examples 29 | /// 30 | /// ``` 31 | /// use core::pin::pin; 32 | /// 33 | /// use futures::task::Poll; 34 | /// use futures::stream::{self, Stream}; 35 | /// use futures_test::task::noop_context; 36 | /// use futures_test::stream::StreamTestExt; 37 | /// 38 | /// let stream = stream::iter(vec![1, 2]).interleave_pending(); 39 | /// let mut stream = pin!(stream); 40 | /// 41 | /// let mut cx = noop_context(); 42 | /// 43 | /// assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Pending); 44 | /// assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Ready(Some(1))); 45 | /// assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Pending); 46 | /// assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Ready(Some(2))); 47 | /// assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Pending); 48 | /// assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Ready(None)); 49 | /// ``` 50 | fn interleave_pending(self) -> InterleavePending 51 | where 52 | Self: Sized, 53 | { 54 | InterleavePending::new(self) 55 | } 56 | } 57 | 58 | impl StreamTestExt for St where St: Stream {} 59 | -------------------------------------------------------------------------------- /futures-test/src/task/context.rs: -------------------------------------------------------------------------------- 1 | use crate::task::{noop_waker_ref, panic_waker_ref}; 2 | use futures_core::task::Context; 3 | 4 | /// Create a new [`Context`](core::task::Context) where the 5 | /// [waker](core::task::Context::waker) will panic if used. 6 | /// 7 | /// # Examples 8 | /// 9 | /// ```should_panic 10 | /// use futures_test::task::panic_context; 11 | /// 12 | /// let cx = panic_context(); 13 | /// cx.waker().wake_by_ref(); // Will panic 14 | /// ``` 15 | pub fn panic_context() -> Context<'static> { 16 | Context::from_waker(panic_waker_ref()) 17 | } 18 | 19 | /// Create a new [`Context`](core::task::Context) where the 20 | /// [waker](core::task::Context::waker) will ignore any uses. 21 | /// 22 | /// # Examples 23 | /// 24 | /// ``` 25 | /// use core::pin::pin; 26 | /// 27 | /// use futures::future::Future; 28 | /// use futures::task::Poll; 29 | /// use futures_test::task::noop_context; 30 | /// 31 | /// let future = async { 5 }; 32 | /// let future = pin!(future); 33 | /// 34 | /// assert_eq!(future.poll(&mut noop_context()), Poll::Ready(5)); 35 | /// ``` 36 | pub fn noop_context() -> Context<'static> { 37 | Context::from_waker(noop_waker_ref()) 38 | } 39 | -------------------------------------------------------------------------------- /futures-test/src/task/noop_spawner.rs: -------------------------------------------------------------------------------- 1 | use futures_task::{FutureObj, Spawn, SpawnError}; 2 | 3 | /// An implementation of [`Spawn`](futures_task::Spawn) that 4 | /// discards spawned futures when used. 5 | /// 6 | /// # Examples 7 | /// 8 | /// ``` 9 | /// use futures::task::SpawnExt; 10 | /// use futures_test::task::NoopSpawner; 11 | /// 12 | /// let spawner = NoopSpawner::new(); 13 | /// spawner.spawn(async { }).unwrap(); 14 | /// ``` 15 | #[derive(Debug)] 16 | pub struct NoopSpawner { 17 | _reserved: (), 18 | } 19 | 20 | impl NoopSpawner { 21 | /// Create a new instance 22 | pub fn new() -> Self { 23 | Self { _reserved: () } 24 | } 25 | } 26 | 27 | impl Spawn for NoopSpawner { 28 | fn spawn_obj(&self, _future: FutureObj<'static, ()>) -> Result<(), SpawnError> { 29 | Ok(()) 30 | } 31 | } 32 | 33 | impl Default for NoopSpawner { 34 | fn default() -> Self { 35 | Self::new() 36 | } 37 | } 38 | 39 | /// Get a reference to a singleton instance of [`NoopSpawner`]. 40 | /// 41 | /// # Examples 42 | /// 43 | /// ``` 44 | /// use futures::task::SpawnExt; 45 | /// use futures_test::task::noop_spawner_mut; 46 | /// 47 | /// let spawner = noop_spawner_mut(); 48 | /// spawner.spawn(async { }).unwrap(); 49 | /// ``` 50 | pub fn noop_spawner_mut() -> &'static mut NoopSpawner { 51 | Box::leak(Box::new(NoopSpawner::new())) 52 | } 53 | -------------------------------------------------------------------------------- /futures-test/src/task/panic_spawner.rs: -------------------------------------------------------------------------------- 1 | use futures_task::{FutureObj, Spawn, SpawnError}; 2 | 3 | /// An implementation of [`Spawn`](futures_task::Spawn) that panics 4 | /// when used. 5 | /// 6 | /// # Examples 7 | /// 8 | /// ```should_panic 9 | /// use futures::task::SpawnExt; 10 | /// use futures_test::task::PanicSpawner; 11 | /// 12 | /// let spawn = PanicSpawner::new(); 13 | /// spawn.spawn(async { })?; // Will panic 14 | /// # Ok::<(), Box>(()) 15 | /// ``` 16 | #[derive(Debug)] 17 | pub struct PanicSpawner { 18 | _reserved: (), 19 | } 20 | 21 | impl PanicSpawner { 22 | /// Create a new instance 23 | pub fn new() -> Self { 24 | Self { _reserved: () } 25 | } 26 | } 27 | 28 | impl Spawn for PanicSpawner { 29 | fn spawn_obj(&self, _future: FutureObj<'static, ()>) -> Result<(), SpawnError> { 30 | panic!("should not spawn") 31 | } 32 | } 33 | 34 | impl Default for PanicSpawner { 35 | fn default() -> Self { 36 | Self::new() 37 | } 38 | } 39 | 40 | /// Get a reference to a singleton instance of [`PanicSpawner`]. 41 | /// 42 | /// # Examples 43 | /// 44 | /// ```should_panic 45 | /// use futures::task::SpawnExt; 46 | /// use futures_test::task::panic_spawner_mut; 47 | /// 48 | /// let spawner = panic_spawner_mut(); 49 | /// spawner.spawn(async { })?; // Will panic 50 | /// # Ok::<(), Box>(()) 51 | /// ``` 52 | pub fn panic_spawner_mut() -> &'static mut PanicSpawner { 53 | Box::leak(Box::new(PanicSpawner::new())) 54 | } 55 | -------------------------------------------------------------------------------- /futures-test/src/task/record_spawner.rs: -------------------------------------------------------------------------------- 1 | use futures_task::{FutureObj, Spawn, SpawnError}; 2 | use std::cell::{Ref, RefCell}; 3 | 4 | /// An implementation of [`Spawn`](futures_task::Spawn) that records 5 | /// any [`Future`](futures_core::future::Future)s spawned on it. 6 | /// 7 | /// # Examples 8 | /// 9 | /// ``` 10 | /// use futures::task::SpawnExt; 11 | /// use futures_test::task::RecordSpawner; 12 | /// 13 | /// let recorder = RecordSpawner::new(); 14 | /// recorder.spawn(async { }).unwrap(); 15 | /// assert_eq!(recorder.spawned().len(), 1); 16 | /// ``` 17 | #[derive(Debug, Default)] 18 | pub struct RecordSpawner { 19 | spawned: RefCell>>, 20 | } 21 | 22 | impl RecordSpawner { 23 | /// Create a new instance 24 | pub fn new() -> Self { 25 | Default::default() 26 | } 27 | 28 | /// Inspect any futures that were spawned onto this [`Spawn`]. 29 | pub fn spawned(&self) -> Ref<'_, Vec>> { 30 | self.spawned.borrow() 31 | } 32 | } 33 | 34 | impl Spawn for RecordSpawner { 35 | fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { 36 | self.spawned.borrow_mut().push(future); 37 | Ok(()) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /futures-test/src/task/wake_counter.rs: -------------------------------------------------------------------------------- 1 | use futures_core::task::Waker; 2 | use futures_util::task::{self, ArcWake}; 3 | use std::sync::atomic::{AtomicUsize, Ordering}; 4 | use std::sync::Arc; 5 | 6 | /// Number of times the waker was awoken. 7 | /// 8 | /// See [`new_count_waker`] for usage. 9 | #[derive(Debug)] 10 | pub struct AwokenCount { 11 | inner: Arc, 12 | } 13 | 14 | impl AwokenCount { 15 | /// Get the current count. 16 | pub fn get(&self) -> usize { 17 | self.inner.count.load(Ordering::SeqCst) 18 | } 19 | } 20 | 21 | impl PartialEq for AwokenCount { 22 | fn eq(&self, other: &usize) -> bool { 23 | self.get() == *other 24 | } 25 | } 26 | 27 | #[derive(Debug)] 28 | struct WakerInner { 29 | count: AtomicUsize, 30 | } 31 | 32 | impl ArcWake for WakerInner { 33 | fn wake_by_ref(arc_self: &Arc) { 34 | let _ = arc_self.count.fetch_add(1, Ordering::SeqCst); 35 | } 36 | } 37 | 38 | /// Create a new [`Waker`] that counts the number of times it's awoken. 39 | /// 40 | /// [`Waker`]: futures_core::task::Waker 41 | /// 42 | /// # Examples 43 | /// 44 | /// ``` 45 | /// use futures_test::task::new_count_waker; 46 | /// 47 | /// let (waker, count) = new_count_waker(); 48 | /// 49 | /// assert_eq!(count, 0); 50 | /// 51 | /// waker.wake_by_ref(); 52 | /// waker.wake(); 53 | /// 54 | /// assert_eq!(count, 2); 55 | /// ``` 56 | pub fn new_count_waker() -> (Waker, AwokenCount) { 57 | let inner = Arc::new(WakerInner { count: AtomicUsize::new(0) }); 58 | (task::waker(inner.clone()), AwokenCount { inner }) 59 | } 60 | -------------------------------------------------------------------------------- /futures-util/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures-util/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures-util/README.md: -------------------------------------------------------------------------------- 1 | # futures-util 2 | 3 | Common utilities and extension traits for the futures-rs library. 4 | 5 | ## Usage 6 | 7 | Add this to your `Cargo.toml`: 8 | 9 | ```toml 10 | [dependencies] 11 | futures-util = "0.3" 12 | ``` 13 | 14 | The current `futures-util` requires Rust 1.68 or later. 15 | 16 | ## License 17 | 18 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 19 | [MIT license](LICENSE-MIT) at your option. 20 | 21 | Unless you explicitly state otherwise, any contribution intentionally submitted 22 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 23 | be dual licensed as above, without any additional terms or conditions. 24 | -------------------------------------------------------------------------------- /futures-util/benches/bilock.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | #![cfg(feature = "bilock")] 3 | 4 | extern crate test; 5 | 6 | use futures::task::Poll; 7 | use futures_test::task::noop_context; 8 | use futures_util::lock::BiLock; 9 | 10 | use crate::test::Bencher; 11 | 12 | #[bench] 13 | fn contended(b: &mut Bencher) { 14 | let mut context = noop_context(); 15 | 16 | b.iter(|| { 17 | let (x, y) = BiLock::new(1); 18 | 19 | for _ in 0..1000 { 20 | let x_guard = match x.poll_lock(&mut context) { 21 | Poll::Ready(guard) => guard, 22 | _ => panic!(), 23 | }; 24 | 25 | // Try poll second lock while first lock still holds the lock 26 | match y.poll_lock(&mut context) { 27 | Poll::Pending => (), 28 | _ => panic!(), 29 | }; 30 | 31 | drop(x_guard); 32 | 33 | let y_guard = match y.poll_lock(&mut context) { 34 | Poll::Ready(guard) => guard, 35 | _ => panic!(), 36 | }; 37 | 38 | drop(y_guard); 39 | } 40 | (x, y) 41 | }); 42 | } 43 | 44 | #[bench] 45 | fn lock_unlock(b: &mut Bencher) { 46 | let mut context = noop_context(); 47 | 48 | b.iter(|| { 49 | let (x, y) = BiLock::new(1); 50 | 51 | for _ in 0..1000 { 52 | let x_guard = match x.poll_lock(&mut context) { 53 | Poll::Ready(guard) => guard, 54 | _ => panic!(), 55 | }; 56 | 57 | drop(x_guard); 58 | 59 | let y_guard = match y.poll_lock(&mut context) { 60 | Poll::Ready(guard) => guard, 61 | _ => panic!(), 62 | }; 63 | 64 | drop(y_guard); 65 | } 66 | (x, y) 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /futures-util/benches/flatten_unordered.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | use crate::test::Bencher; 5 | 6 | use futures::channel::oneshot; 7 | use futures::executor::block_on; 8 | use futures::future; 9 | use futures::stream::{self, StreamExt}; 10 | use futures::task::Poll; 11 | use futures_util::FutureExt; 12 | use std::collections::VecDeque; 13 | use std::thread; 14 | 15 | #[bench] 16 | fn oneshot_streams(b: &mut Bencher) { 17 | const STREAM_COUNT: usize = 10_000; 18 | const STREAM_ITEM_COUNT: usize = 1; 19 | 20 | b.iter(|| { 21 | let mut txs = VecDeque::with_capacity(STREAM_COUNT); 22 | let mut rxs = Vec::new(); 23 | 24 | for _ in 0..STREAM_COUNT { 25 | let (tx, rx) = oneshot::channel(); 26 | txs.push_back(tx); 27 | rxs.push(rx); 28 | } 29 | 30 | thread::spawn(move || { 31 | let mut last = 1; 32 | while let Some(tx) = txs.pop_front() { 33 | let _ = tx.send(stream::iter(last..last + STREAM_ITEM_COUNT)); 34 | last += STREAM_ITEM_COUNT; 35 | } 36 | }); 37 | 38 | let mut flatten = stream::iter(rxs) 39 | .map(|recv| recv.into_stream().map(|val| val.unwrap()).flatten()) 40 | .flatten_unordered(None); 41 | 42 | block_on(future::poll_fn(move |cx| { 43 | let mut count = 0; 44 | loop { 45 | match flatten.poll_next_unpin(cx) { 46 | Poll::Ready(None) => break, 47 | Poll::Ready(Some(_)) => { 48 | count += 1; 49 | } 50 | _ => {} 51 | } 52 | } 53 | assert_eq!(count, STREAM_COUNT * STREAM_ITEM_COUNT); 54 | 55 | Poll::Ready(()) 56 | })) 57 | }); 58 | } 59 | -------------------------------------------------------------------------------- /futures-util/benches/futures_unordered.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | use crate::test::Bencher; 5 | 6 | use futures::channel::oneshot; 7 | use futures::executor::block_on; 8 | use futures::future; 9 | use futures::stream::{FuturesUnordered, StreamExt}; 10 | use futures::task::Poll; 11 | use std::collections::VecDeque; 12 | use std::thread; 13 | 14 | #[bench] 15 | fn oneshots(b: &mut Bencher) { 16 | const NUM: usize = 10_000; 17 | 18 | b.iter(|| { 19 | let mut txs = VecDeque::with_capacity(NUM); 20 | let mut rxs = FuturesUnordered::new(); 21 | 22 | for _ in 0..NUM { 23 | let (tx, rx) = oneshot::channel(); 24 | txs.push_back(tx); 25 | rxs.push(rx); 26 | } 27 | 28 | thread::spawn(move || { 29 | while let Some(tx) = txs.pop_front() { 30 | let _ = tx.send("hello"); 31 | } 32 | }); 33 | 34 | block_on(future::poll_fn(move |cx| { 35 | loop { 36 | if let Poll::Ready(None) = rxs.poll_next_unpin(cx) { 37 | break; 38 | } 39 | } 40 | Poll::Ready(()) 41 | })) 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /futures-util/benches/select.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | use crate::test::Bencher; 5 | 6 | use futures::executor::block_on; 7 | use futures::stream::{repeat, select, StreamExt}; 8 | 9 | #[bench] 10 | fn select_streams(b: &mut Bencher) { 11 | const STREAM_COUNT: usize = 10_000; 12 | 13 | b.iter(|| { 14 | let stream1 = repeat(1).take(STREAM_COUNT); 15 | let stream2 = repeat(2).take(STREAM_COUNT); 16 | let stream3 = repeat(3).take(STREAM_COUNT); 17 | let stream4 = repeat(4).take(STREAM_COUNT); 18 | let stream5 = repeat(5).take(STREAM_COUNT); 19 | let stream6 = repeat(6).take(STREAM_COUNT); 20 | let stream7 = repeat(7).take(STREAM_COUNT); 21 | let count = block_on( 22 | select( 23 | stream1, 24 | select( 25 | stream2, 26 | select(stream3, select(stream4, select(stream5, select(stream6, stream7)))), 27 | ), 28 | ) 29 | .count(), 30 | ); 31 | assert_eq!(count, STREAM_COUNT * 7); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /futures-util/src/async_await/mod.rs: -------------------------------------------------------------------------------- 1 | //! Await 2 | //! 3 | //! This module contains a number of functions and combinators for working 4 | //! with `async`/`await` code. 5 | 6 | use futures_core::future::{FusedFuture, Future}; 7 | use futures_core::stream::{FusedStream, Stream}; 8 | 9 | #[macro_use] 10 | mod poll; 11 | pub use self::poll::*; 12 | 13 | #[macro_use] 14 | mod pending; 15 | pub use self::pending::*; 16 | 17 | // Primary export is a macro 18 | #[cfg(feature = "async-await-macro")] 19 | mod join_mod; 20 | #[cfg(feature = "async-await-macro")] 21 | pub use self::join_mod::*; 22 | 23 | // Primary export is a macro 24 | #[cfg(feature = "async-await-macro")] 25 | mod select_mod; 26 | #[cfg(feature = "async-await-macro")] 27 | pub use self::select_mod::*; 28 | 29 | // Primary export is a macro 30 | #[cfg(feature = "std")] 31 | #[cfg(feature = "async-await-macro")] 32 | mod stream_select_mod; 33 | #[cfg(feature = "std")] 34 | #[cfg(feature = "async-await-macro")] 35 | pub use self::stream_select_mod::*; 36 | 37 | #[cfg(feature = "std")] 38 | #[cfg(feature = "async-await-macro")] 39 | mod random; 40 | #[cfg(feature = "std")] 41 | #[cfg(feature = "async-await-macro")] 42 | pub use self::random::*; 43 | 44 | #[doc(hidden)] 45 | #[inline(always)] 46 | pub fn assert_unpin(_: &T) {} 47 | 48 | #[doc(hidden)] 49 | #[inline(always)] 50 | pub fn assert_fused_future(_: &T) {} 51 | 52 | #[doc(hidden)] 53 | #[inline(always)] 54 | pub fn assert_fused_stream(_: &T) {} 55 | -------------------------------------------------------------------------------- /futures-util/src/async_await/pending.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::future::Future; 3 | use futures_core::task::{Context, Poll}; 4 | 5 | /// A macro which yields to the event loop once. 6 | /// 7 | /// This is equivalent to returning [`Poll::Pending`](futures_core::task::Poll) 8 | /// from a [`Future::poll`](futures_core::future::Future::poll) implementation. 9 | /// Similarly, when using this macro, it must be ensured that [`wake`](std::task::Waker::wake) 10 | /// is called somewhere when further progress can be made. 11 | /// 12 | /// This macro is only usable inside of async functions, closures, and blocks. 13 | /// It is also gated behind the `async-await` feature of this library, which is 14 | /// activated by default. 15 | #[macro_export] 16 | macro_rules! pending { 17 | () => { 18 | $crate::__private::async_await::pending_once().await 19 | }; 20 | } 21 | 22 | #[doc(hidden)] 23 | pub fn pending_once() -> PendingOnce { 24 | PendingOnce { is_ready: false } 25 | } 26 | 27 | #[allow(missing_debug_implementations)] 28 | #[doc(hidden)] 29 | pub struct PendingOnce { 30 | is_ready: bool, 31 | } 32 | 33 | impl Future for PendingOnce { 34 | type Output = (); 35 | fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { 36 | if self.is_ready { 37 | Poll::Ready(()) 38 | } else { 39 | self.is_ready = true; 40 | Poll::Pending 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /futures-util/src/async_await/poll.rs: -------------------------------------------------------------------------------- 1 | use crate::future::FutureExt; 2 | use core::pin::Pin; 3 | use futures_core::future::Future; 4 | use futures_core::task::{Context, Poll}; 5 | 6 | /// A macro which returns the result of polling a future once within the 7 | /// current `async` context. 8 | /// 9 | /// This macro is only usable inside of `async` functions, closures, and blocks. 10 | /// It is also gated behind the `async-await` feature of this library, which is 11 | /// activated by default. 12 | /// 13 | /// If you need the result of polling a [`Stream`](crate::stream::Stream), 14 | /// you can use this macro with the [`next`](crate::stream::StreamExt::next) method: 15 | /// `poll!(stream.next())`. 16 | #[macro_export] 17 | macro_rules! poll { 18 | ($x:expr $(,)?) => { 19 | $crate::__private::async_await::poll($x).await 20 | }; 21 | } 22 | 23 | #[doc(hidden)] 24 | pub fn poll(future: F) -> PollOnce { 25 | PollOnce { future } 26 | } 27 | 28 | #[allow(missing_debug_implementations)] 29 | #[doc(hidden)] 30 | pub struct PollOnce { 31 | future: F, 32 | } 33 | 34 | impl Future for PollOnce { 35 | type Output = Poll; 36 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 37 | Poll::Ready(self.future.poll_unpin(cx)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /futures-util/src/async_await/random.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | cell::Cell, 3 | collections::hash_map::DefaultHasher, 4 | hash::Hasher, 5 | num::Wrapping, 6 | sync::atomic::{AtomicUsize, Ordering}, 7 | }; 8 | 9 | // Based on [Fisher–Yates shuffle]. 10 | // 11 | // [Fisher–Yates shuffle]: https://en.wikipedia.org/wiki/Fisher–Yates_shuffle 12 | #[doc(hidden)] 13 | pub fn shuffle(slice: &mut [T]) { 14 | for i in (1..slice.len()).rev() { 15 | slice.swap(i, gen_index(i + 1)); 16 | } 17 | } 18 | 19 | /// Return a value from `0..n`. 20 | fn gen_index(n: usize) -> usize { 21 | (random() % n as u64) as usize 22 | } 23 | 24 | /// Pseudorandom number generator based on [xorshift*]. 25 | /// 26 | /// [xorshift*]: https://en.wikipedia.org/wiki/Xorshift#xorshift* 27 | fn random() -> u64 { 28 | std::thread_local! { 29 | static RNG: Cell> = Cell::new(Wrapping(prng_seed())); 30 | } 31 | 32 | fn prng_seed() -> u64 { 33 | static COUNTER: AtomicUsize = AtomicUsize::new(0); 34 | 35 | // Any non-zero seed will do 36 | let mut seed = 0; 37 | while seed == 0 { 38 | let mut hasher = DefaultHasher::new(); 39 | hasher.write_usize(COUNTER.fetch_add(1, Ordering::Relaxed)); 40 | seed = hasher.finish(); 41 | } 42 | seed 43 | } 44 | 45 | RNG.with(|rng| { 46 | let mut x = rng.get(); 47 | debug_assert_ne!(x.0, 0); 48 | x ^= x >> 12; 49 | x ^= x << 25; 50 | x ^= x >> 27; 51 | rng.set(x); 52 | x.0.wrapping_mul(0x2545_f491_4f6c_dd1d) 53 | }) 54 | } 55 | -------------------------------------------------------------------------------- /futures-util/src/async_await/stream_select_mod.rs: -------------------------------------------------------------------------------- 1 | //! The `stream_select` macro. 2 | 3 | #[doc(hidden)] 4 | pub use futures_macro::stream_select_internal; 5 | 6 | #[allow(clippy::too_long_first_doc_paragraph)] 7 | /// Combines several streams, all producing the same `Item` type, into one stream. 8 | /// This is similar to `select_all` but does not require the streams to all be the same type. 9 | /// It also keeps the streams inline, and does not require `Box`s to be allocated. 10 | /// Streams passed to this macro must be `Unpin`. 11 | /// 12 | /// If multiple streams are ready, one will be pseudo randomly selected at runtime. 13 | /// 14 | /// # Examples 15 | /// 16 | /// ``` 17 | /// # futures::executor::block_on(async { 18 | /// use futures::{stream, StreamExt, stream_select}; 19 | /// let endless_ints = |i| stream::iter(vec![i].into_iter().cycle()).fuse(); 20 | /// 21 | /// let mut endless_numbers = stream_select!(endless_ints(1i32), endless_ints(2), endless_ints(3)); 22 | /// match endless_numbers.next().await { 23 | /// Some(1) => println!("Got a 1"), 24 | /// Some(2) => println!("Got a 2"), 25 | /// Some(3) => println!("Got a 3"), 26 | /// _ => unreachable!(), 27 | /// } 28 | /// # }); 29 | /// ``` 30 | #[macro_export] 31 | macro_rules! stream_select { 32 | ($($tokens:tt)*) => {{ 33 | use $crate::__private as __futures_crate; 34 | $crate::stream_select_internal! { 35 | $( $tokens )* 36 | } 37 | }} 38 | } 39 | -------------------------------------------------------------------------------- /futures-util/src/compat/mod.rs: -------------------------------------------------------------------------------- 1 | //! Interop between `futures` 0.1 and 0.3. 2 | //! 3 | //! This module is only available when the `compat` feature of this 4 | //! library is activated. 5 | 6 | mod executor; 7 | pub use self::executor::{Executor01As03, Executor01CompatExt, Executor01Future}; 8 | 9 | mod compat01as03; 10 | #[cfg(feature = "io-compat")] 11 | #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] 12 | pub use self::compat01as03::{AsyncRead01CompatExt, AsyncWrite01CompatExt}; 13 | pub use self::compat01as03::{Compat01As03, Future01CompatExt, Stream01CompatExt}; 14 | #[cfg(feature = "sink")] 15 | #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] 16 | pub use self::compat01as03::{Compat01As03Sink, Sink01CompatExt}; 17 | 18 | mod compat03as01; 19 | pub use self::compat03as01::Compat; 20 | #[cfg(feature = "sink")] 21 | #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] 22 | pub use self::compat03as01::CompatSink; 23 | -------------------------------------------------------------------------------- /futures-util/src/future/abortable.rs: -------------------------------------------------------------------------------- 1 | use super::assert_future; 2 | use crate::future::{AbortHandle, Abortable, Aborted}; 3 | use futures_core::future::Future; 4 | 5 | /// Creates a new `Abortable` future and an `AbortHandle` which can be used to stop it. 6 | /// 7 | /// This function is a convenient (but less flexible) alternative to calling 8 | /// `AbortHandle::new` and `Abortable::new` manually. 9 | /// 10 | /// This function is only available when the `std` or `alloc` feature of this 11 | /// library is activated, and it is activated by default. 12 | pub fn abortable(future: Fut) -> (Abortable, AbortHandle) 13 | where 14 | Fut: Future, 15 | { 16 | let (handle, reg) = AbortHandle::new_pair(); 17 | let abortable = assert_future::, _>(Abortable::new(future, reg)); 18 | (abortable, handle) 19 | } 20 | -------------------------------------------------------------------------------- /futures-util/src/future/always_ready.rs: -------------------------------------------------------------------------------- 1 | use super::assert_future; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::task::{Context, Poll}; 5 | 6 | /// Future for the [`always_ready`](always_ready()) function. 7 | #[must_use = "futures do nothing unless you `.await` or poll them"] 8 | pub struct AlwaysReady T>(F); 9 | 10 | impl T> core::fmt::Debug for AlwaysReady { 11 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 12 | f.debug_tuple("AlwaysReady").finish() 13 | } 14 | } 15 | 16 | impl T + Clone> Clone for AlwaysReady { 17 | fn clone(&self) -> Self { 18 | Self(self.0.clone()) 19 | } 20 | } 21 | 22 | impl T + Copy> Copy for AlwaysReady {} 23 | 24 | impl T> Unpin for AlwaysReady {} 25 | 26 | impl T> FusedFuture for AlwaysReady { 27 | fn is_terminated(&self) -> bool { 28 | false 29 | } 30 | } 31 | 32 | impl T> Future for AlwaysReady { 33 | type Output = T; 34 | 35 | #[inline] 36 | fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { 37 | Poll::Ready(self.0()) 38 | } 39 | } 40 | 41 | /// Creates a future that is always immediately ready with a value. 42 | /// 43 | /// This is particularly useful in avoiding a heap allocation when an API needs [`Box>`], 44 | /// as [`AlwaysReady`] does not have to store a boolean for `is_finished`. 45 | /// 46 | /// # Examples 47 | /// 48 | /// ``` 49 | /// # futures::executor::block_on(async { 50 | /// use std::mem::size_of_val; 51 | /// 52 | /// use futures::future; 53 | /// 54 | /// let a = future::always_ready(|| 1); 55 | /// assert_eq!(size_of_val(&a), 0); 56 | /// assert_eq!(a.await, 1); 57 | /// assert_eq!(a.await, 1); 58 | /// # }); 59 | /// ``` 60 | pub fn always_ready T>(prod: F) -> AlwaysReady { 61 | assert_future::(AlwaysReady(prod)) 62 | } 63 | -------------------------------------------------------------------------------- /futures-util/src/future/future/catch_unwind.rs: -------------------------------------------------------------------------------- 1 | use core::any::Any; 2 | use core::pin::Pin; 3 | use std::boxed::Box; 4 | use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe}; 5 | 6 | use futures_core::future::Future; 7 | use futures_core::task::{Context, Poll}; 8 | use pin_project_lite::pin_project; 9 | 10 | pin_project! { 11 | /// Future for the [`catch_unwind`](super::FutureExt::catch_unwind) method. 12 | #[derive(Debug)] 13 | #[must_use = "futures do nothing unless you `.await` or poll them"] 14 | pub struct CatchUnwind { 15 | #[pin] 16 | future: Fut, 17 | } 18 | } 19 | 20 | impl CatchUnwind 21 | where 22 | Fut: Future + UnwindSafe, 23 | { 24 | pub(super) fn new(future: Fut) -> Self { 25 | Self { future } 26 | } 27 | } 28 | 29 | impl Future for CatchUnwind 30 | where 31 | Fut: Future + UnwindSafe, 32 | { 33 | type Output = Result>; 34 | 35 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 36 | let f = self.project().future; 37 | catch_unwind(AssertUnwindSafe(|| f.poll(cx)))?.map(Ok) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /futures-util/src/future/future/map.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::future::{FusedFuture, Future}; 3 | use futures_core::ready; 4 | use futures_core::task::{Context, Poll}; 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::fns::FnOnce1; 8 | 9 | pin_project! { 10 | /// Internal Map future 11 | #[project = MapProj] 12 | #[project_replace = MapProjReplace] 13 | #[derive(Debug)] 14 | #[must_use = "futures do nothing unless you `.await` or poll them"] 15 | pub enum Map { 16 | Incomplete { 17 | #[pin] 18 | future: Fut, 19 | f: F, 20 | }, 21 | Complete, 22 | } 23 | } 24 | 25 | impl Map { 26 | /// Creates a new Map. 27 | pub(crate) fn new(future: Fut, f: F) -> Self { 28 | Self::Incomplete { future, f } 29 | } 30 | } 31 | 32 | impl FusedFuture for Map 33 | where 34 | Fut: Future, 35 | F: FnOnce1, 36 | { 37 | fn is_terminated(&self) -> bool { 38 | match self { 39 | Self::Incomplete { .. } => false, 40 | Self::Complete => true, 41 | } 42 | } 43 | } 44 | 45 | impl Future for Map 46 | where 47 | Fut: Future, 48 | F: FnOnce1, 49 | { 50 | type Output = T; 51 | 52 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 53 | match self.as_mut().project() { 54 | MapProj::Incomplete { future, .. } => { 55 | let output = ready!(future.poll(cx)); 56 | match self.project_replace(Self::Complete) { 57 | MapProjReplace::Incomplete { f, .. } => Poll::Ready(f.call_once(output)), 58 | MapProjReplace::Complete => unreachable!(), 59 | } 60 | } 61 | MapProj::Complete => { 62 | panic!("Map must not be polled after it returned `Poll::Ready`") 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /futures-util/src/future/lazy.rs: -------------------------------------------------------------------------------- 1 | use super::assert_future; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::task::{Context, Poll}; 5 | 6 | /// Future for the [`lazy`] function. 7 | #[derive(Debug)] 8 | #[must_use = "futures do nothing unless you `.await` or poll them"] 9 | pub struct Lazy { 10 | f: Option, 11 | } 12 | 13 | // safe because we never generate `Pin<&mut F>` 14 | impl Unpin for Lazy {} 15 | 16 | /// Creates a new future that allows delayed execution of a closure. 17 | /// 18 | /// The provided closure is only run once the future is polled. 19 | /// 20 | /// # Examples 21 | /// 22 | /// ``` 23 | /// # futures::executor::block_on(async { 24 | /// use futures::future; 25 | /// 26 | /// let a = future::lazy(|_| 1); 27 | /// assert_eq!(a.await, 1); 28 | /// 29 | /// let b = future::lazy(|_| -> i32 { 30 | /// panic!("oh no!") 31 | /// }); 32 | /// drop(b); // closure is never run 33 | /// # }); 34 | /// ``` 35 | pub fn lazy(f: F) -> Lazy 36 | where 37 | F: FnOnce(&mut Context<'_>) -> R, 38 | { 39 | assert_future::(Lazy { f: Some(f) }) 40 | } 41 | 42 | impl FusedFuture for Lazy 43 | where 44 | F: FnOnce(&mut Context<'_>) -> R, 45 | { 46 | fn is_terminated(&self) -> bool { 47 | self.f.is_none() 48 | } 49 | } 50 | 51 | impl Future for Lazy 52 | where 53 | F: FnOnce(&mut Context<'_>) -> R, 54 | { 55 | type Output = R; 56 | 57 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 58 | Poll::Ready((self.f.take().expect("Lazy polled after completion"))(cx)) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /futures-util/src/future/option.rs: -------------------------------------------------------------------------------- 1 | //! Definition of the `Option` (optional step) combinator 2 | 3 | use core::pin::Pin; 4 | use futures_core::future::{FusedFuture, Future}; 5 | use futures_core::task::{Context, Poll}; 6 | use pin_project_lite::pin_project; 7 | 8 | pin_project! { 9 | /// A future representing a value which may or may not be present. 10 | /// 11 | /// Created by the [`From`] implementation for [`Option`](std::option::Option). 12 | /// 13 | /// # Examples 14 | /// 15 | /// ``` 16 | /// # futures::executor::block_on(async { 17 | /// use futures::future::OptionFuture; 18 | /// 19 | /// let mut a: OptionFuture<_> = Some(async { 123 }).into(); 20 | /// assert_eq!(a.await, Some(123)); 21 | /// 22 | /// a = None.into(); 23 | /// assert_eq!(a.await, None); 24 | /// # }); 25 | /// ``` 26 | #[derive(Debug, Clone)] 27 | #[must_use = "futures do nothing unless you `.await` or poll them"] 28 | pub struct OptionFuture { 29 | #[pin] 30 | inner: Option, 31 | } 32 | } 33 | 34 | impl Default for OptionFuture { 35 | fn default() -> Self { 36 | Self { inner: None } 37 | } 38 | } 39 | 40 | impl Future for OptionFuture { 41 | type Output = Option; 42 | 43 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 44 | match self.project().inner.as_pin_mut() { 45 | Some(x) => x.poll(cx).map(Some), 46 | None => Poll::Ready(None), 47 | } 48 | } 49 | } 50 | 51 | impl FusedFuture for OptionFuture { 52 | fn is_terminated(&self) -> bool { 53 | match &self.inner { 54 | Some(x) => x.is_terminated(), 55 | None => true, 56 | } 57 | } 58 | } 59 | 60 | impl From> for OptionFuture { 61 | fn from(option: Option) -> Self { 62 | Self { inner: option } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /futures-util/src/future/pending.rs: -------------------------------------------------------------------------------- 1 | use super::assert_future; 2 | use core::marker; 3 | use core::pin::Pin; 4 | use futures_core::future::{FusedFuture, Future}; 5 | use futures_core::task::{Context, Poll}; 6 | 7 | /// Future for the [`pending()`] function. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Pending { 11 | _data: marker::PhantomData, 12 | } 13 | 14 | impl FusedFuture for Pending { 15 | fn is_terminated(&self) -> bool { 16 | true 17 | } 18 | } 19 | 20 | /// Creates a future which never resolves, representing a computation that never 21 | /// finishes. 22 | /// 23 | /// The returned future will forever return [`Poll::Pending`]. 24 | /// 25 | /// # Examples 26 | /// 27 | /// ```ignore 28 | /// # futures::executor::block_on(async { 29 | /// use futures::future; 30 | /// 31 | /// let future = future::pending(); 32 | /// let () = future.await; 33 | /// unreachable!(); 34 | /// # }); 35 | /// ``` 36 | #[cfg_attr(docsrs, doc(alias = "never"))] 37 | pub fn pending() -> Pending { 38 | assert_future::(Pending { _data: marker::PhantomData }) 39 | } 40 | 41 | impl Future for Pending { 42 | type Output = T; 43 | 44 | fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { 45 | Poll::Pending 46 | } 47 | } 48 | 49 | impl Unpin for Pending {} 50 | 51 | impl Clone for Pending { 52 | fn clone(&self) -> Self { 53 | pending() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /futures-util/src/future/poll_fn.rs: -------------------------------------------------------------------------------- 1 | //! Definition of the `PollFn` adapter combinator 2 | 3 | use super::assert_future; 4 | use core::fmt; 5 | use core::pin::Pin; 6 | use futures_core::future::Future; 7 | use futures_core::task::{Context, Poll}; 8 | 9 | /// Future for the [`poll_fn`] function. 10 | #[must_use = "futures do nothing unless you `.await` or poll them"] 11 | pub struct PollFn { 12 | f: F, 13 | } 14 | 15 | impl Unpin for PollFn {} 16 | 17 | /// Creates a new future wrapping around a function returning [`Poll`]. 18 | /// 19 | /// Polling the returned future delegates to the wrapped function. 20 | /// 21 | /// # Examples 22 | /// 23 | /// ``` 24 | /// # futures::executor::block_on(async { 25 | /// use futures::future::poll_fn; 26 | /// use futures::task::{Context, Poll}; 27 | /// 28 | /// fn read_line(_cx: &mut Context<'_>) -> Poll { 29 | /// Poll::Ready("Hello, World!".into()) 30 | /// } 31 | /// 32 | /// let read_future = poll_fn(read_line); 33 | /// assert_eq!(read_future.await, "Hello, World!".to_owned()); 34 | /// # }); 35 | /// ``` 36 | pub fn poll_fn(f: F) -> PollFn 37 | where 38 | F: FnMut(&mut Context<'_>) -> Poll, 39 | { 40 | assert_future::(PollFn { f }) 41 | } 42 | 43 | impl fmt::Debug for PollFn { 44 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 45 | f.debug_struct("PollFn").finish() 46 | } 47 | } 48 | 49 | impl Future for PollFn 50 | where 51 | F: FnMut(&mut Context<'_>) -> Poll, 52 | { 53 | type Output = T; 54 | 55 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 56 | (&mut self.f)(cx) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /futures-util/src/future/ready.rs: -------------------------------------------------------------------------------- 1 | use super::assert_future; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::task::{Context, Poll}; 5 | 6 | /// Future for the [`ready`](ready()) function. 7 | #[derive(Debug, Clone)] 8 | #[must_use = "futures do nothing unless you `.await` or poll them"] 9 | pub struct Ready(Option); 10 | 11 | impl Ready { 12 | /// Unwraps the value from this immediately ready future. 13 | #[inline] 14 | pub fn into_inner(mut self) -> T { 15 | self.0.take().unwrap() 16 | } 17 | } 18 | 19 | impl Unpin for Ready {} 20 | 21 | impl FusedFuture for Ready { 22 | fn is_terminated(&self) -> bool { 23 | self.0.is_none() 24 | } 25 | } 26 | 27 | impl Future for Ready { 28 | type Output = T; 29 | 30 | #[inline] 31 | fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { 32 | Poll::Ready(self.0.take().expect("Ready polled after completion")) 33 | } 34 | } 35 | 36 | /// Creates a future that is immediately ready with a value. 37 | /// 38 | /// # Examples 39 | /// 40 | /// ``` 41 | /// # futures::executor::block_on(async { 42 | /// use futures::future; 43 | /// 44 | /// let a = future::ready(1); 45 | /// assert_eq!(a.await, 1); 46 | /// # }); 47 | /// ``` 48 | pub fn ready(t: T) -> Ready { 49 | assert_future::(Ready(Some(t))) 50 | } 51 | 52 | /// Create a future that is immediately ready with a success value. 53 | /// 54 | /// # Examples 55 | /// 56 | /// ``` 57 | /// # futures::executor::block_on(async { 58 | /// use futures::future; 59 | /// 60 | /// let a = future::ok::(1); 61 | /// assert_eq!(a.await, Ok(1)); 62 | /// # }); 63 | /// ``` 64 | pub fn ok(t: T) -> Ready> { 65 | Ready(Some(Ok(t))) 66 | } 67 | 68 | /// Create a future that is immediately ready with an error value. 69 | /// 70 | /// # Examples 71 | /// 72 | /// ``` 73 | /// # futures::executor::block_on(async { 74 | /// use futures::future; 75 | /// 76 | /// let a = future::err::(1); 77 | /// assert_eq!(a.await, Err(1)); 78 | /// # }); 79 | /// ``` 80 | pub fn err(err: E) -> Ready> { 81 | Ready(Some(Err(err))) 82 | } 83 | -------------------------------------------------------------------------------- /futures-util/src/future/try_future/into_future.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::future::{FusedFuture, Future, TryFuture}; 3 | use futures_core::task::{Context, Poll}; 4 | use pin_project_lite::pin_project; 5 | 6 | pin_project! { 7 | /// Future for the [`into_future`](super::TryFutureExt::into_future) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct IntoFuture { 11 | #[pin] 12 | future: Fut, 13 | } 14 | } 15 | 16 | impl IntoFuture { 17 | #[inline] 18 | pub(crate) fn new(future: Fut) -> Self { 19 | Self { future } 20 | } 21 | } 22 | 23 | impl FusedFuture for IntoFuture { 24 | fn is_terminated(&self) -> bool { 25 | self.future.is_terminated() 26 | } 27 | } 28 | 29 | impl Future for IntoFuture { 30 | type Output = Result; 31 | 32 | #[inline] 33 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 34 | self.project().future.try_poll(cx) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /futures-util/src/future/try_future/try_flatten_err.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::future::{FusedFuture, Future, TryFuture}; 3 | use futures_core::ready; 4 | use futures_core::task::{Context, Poll}; 5 | use pin_project_lite::pin_project; 6 | 7 | pin_project! { 8 | #[project = TryFlattenErrProj] 9 | #[derive(Debug)] 10 | pub enum TryFlattenErr { 11 | First { #[pin] f: Fut1 }, 12 | Second { #[pin] f: Fut2 }, 13 | Empty, 14 | } 15 | } 16 | 17 | impl TryFlattenErr { 18 | pub(crate) fn new(future: Fut1) -> Self { 19 | Self::First { f: future } 20 | } 21 | } 22 | 23 | impl FusedFuture for TryFlattenErr 24 | where 25 | Fut: TryFuture, 26 | Fut::Error: TryFuture, 27 | { 28 | fn is_terminated(&self) -> bool { 29 | matches!(self, Self::Empty) 30 | } 31 | } 32 | 33 | impl Future for TryFlattenErr 34 | where 35 | Fut: TryFuture, 36 | Fut::Error: TryFuture, 37 | { 38 | type Output = Result::Error>; 39 | 40 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 41 | Poll::Ready(loop { 42 | match self.as_mut().project() { 43 | TryFlattenErrProj::First { f } => match ready!(f.try_poll(cx)) { 44 | Err(f) => self.set(Self::Second { f }), 45 | Ok(e) => { 46 | self.set(Self::Empty); 47 | break Ok(e); 48 | } 49 | }, 50 | TryFlattenErrProj::Second { f } => { 51 | let output = ready!(f.try_poll(cx)); 52 | self.set(Self::Empty); 53 | break output; 54 | } 55 | TryFlattenErrProj::Empty => panic!("TryFlattenErr polled after completion"), 56 | } 57 | }) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /futures-util/src/io/close.rs: -------------------------------------------------------------------------------- 1 | use futures_core::future::Future; 2 | use futures_core::task::{Context, Poll}; 3 | use futures_io::AsyncWrite; 4 | use std::io; 5 | use std::pin::Pin; 6 | 7 | /// Future for the [`close`](super::AsyncWriteExt::close) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Close<'a, W: ?Sized> { 11 | writer: &'a mut W, 12 | } 13 | 14 | impl Unpin for Close<'_, W> {} 15 | 16 | impl<'a, W: AsyncWrite + ?Sized + Unpin> Close<'a, W> { 17 | pub(super) fn new(writer: &'a mut W) -> Self { 18 | Self { writer } 19 | } 20 | } 21 | 22 | impl Future for Close<'_, W> { 23 | type Output = io::Result<()>; 24 | 25 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 26 | Pin::new(&mut *self.writer).poll_close(cx) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /futures-util/src/io/copy.rs: -------------------------------------------------------------------------------- 1 | use super::{copy_buf, BufReader, CopyBuf}; 2 | use futures_core::future::Future; 3 | use futures_core::task::{Context, Poll}; 4 | use futures_io::{AsyncRead, AsyncWrite}; 5 | use pin_project_lite::pin_project; 6 | use std::io; 7 | use std::pin::Pin; 8 | 9 | /// Creates a future which copies all the bytes from one object to another. 10 | /// 11 | /// The returned future will copy all the bytes read from this `AsyncRead` into the 12 | /// `writer` specified. This future will only complete once the `reader` has hit 13 | /// EOF and all bytes have been written to and flushed from the `writer` 14 | /// provided. 15 | /// 16 | /// On success the number of bytes is returned. 17 | /// 18 | /// # Examples 19 | /// 20 | /// ``` 21 | /// # futures::executor::block_on(async { 22 | /// use futures::io::{self, AsyncWriteExt, Cursor}; 23 | /// 24 | /// let reader = Cursor::new([1, 2, 3, 4]); 25 | /// let mut writer = Cursor::new(vec![0u8; 5]); 26 | /// 27 | /// let bytes = io::copy(reader, &mut writer).await?; 28 | /// writer.close().await?; 29 | /// 30 | /// assert_eq!(bytes, 4); 31 | /// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]); 32 | /// # Ok::<(), Box>(()) }).unwrap(); 33 | /// ``` 34 | pub fn copy(reader: R, writer: &mut W) -> Copy<'_, R, W> 35 | where 36 | R: AsyncRead, 37 | W: AsyncWrite + Unpin + ?Sized, 38 | { 39 | Copy { inner: copy_buf(BufReader::new(reader), writer) } 40 | } 41 | 42 | pin_project! { 43 | /// Future for the [`copy()`] function. 44 | #[derive(Debug)] 45 | #[must_use = "futures do nothing unless you `.await` or poll them"] 46 | pub struct Copy<'a, R, W: ?Sized> { 47 | #[pin] 48 | inner: CopyBuf<'a, BufReader, W>, 49 | } 50 | } 51 | 52 | impl Future for Copy<'_, R, W> { 53 | type Output = io::Result; 54 | 55 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 56 | self.project().inner.poll(cx) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /futures-util/src/io/empty.rs: -------------------------------------------------------------------------------- 1 | use futures_core::task::{Context, Poll}; 2 | use futures_io::{AsyncBufRead, AsyncRead}; 3 | use std::fmt; 4 | use std::io; 5 | use std::pin::Pin; 6 | 7 | /// Reader for the [`empty()`] function. 8 | #[must_use = "readers do nothing unless polled"] 9 | pub struct Empty { 10 | _priv: (), 11 | } 12 | 13 | /// Constructs a new handle to an empty reader. 14 | /// 15 | /// All reads from the returned reader will return `Poll::Ready(Ok(0))`. 16 | /// 17 | /// # Examples 18 | /// 19 | /// A slightly sad example of not reading anything into a buffer: 20 | /// 21 | /// ``` 22 | /// # futures::executor::block_on(async { 23 | /// use futures::io::{self, AsyncReadExt}; 24 | /// 25 | /// let mut buffer = String::new(); 26 | /// let mut reader = io::empty(); 27 | /// reader.read_to_string(&mut buffer).await?; 28 | /// assert!(buffer.is_empty()); 29 | /// # Ok::<(), Box>(()) }).unwrap(); 30 | /// ``` 31 | pub fn empty() -> Empty { 32 | Empty { _priv: () } 33 | } 34 | 35 | impl AsyncRead for Empty { 36 | #[inline] 37 | fn poll_read( 38 | self: Pin<&mut Self>, 39 | _: &mut Context<'_>, 40 | _: &mut [u8], 41 | ) -> Poll> { 42 | Poll::Ready(Ok(0)) 43 | } 44 | } 45 | 46 | impl AsyncBufRead for Empty { 47 | #[inline] 48 | fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 49 | Poll::Ready(Ok(&[])) 50 | } 51 | #[inline] 52 | fn consume(self: Pin<&mut Self>, _: usize) {} 53 | } 54 | 55 | impl fmt::Debug for Empty { 56 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 57 | f.pad("Empty { .. }") 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /futures-util/src/io/fill_buf.rs: -------------------------------------------------------------------------------- 1 | use futures_core::future::Future; 2 | use futures_core::task::{Context, Poll}; 3 | use futures_io::AsyncBufRead; 4 | use std::io; 5 | use std::pin::Pin; 6 | use std::slice; 7 | 8 | /// Future for the [`fill_buf`](super::AsyncBufReadExt::fill_buf) method. 9 | #[derive(Debug)] 10 | #[must_use = "futures do nothing unless you `.await` or poll them"] 11 | pub struct FillBuf<'a, R: ?Sized> { 12 | reader: Option<&'a mut R>, 13 | } 14 | 15 | impl Unpin for FillBuf<'_, R> {} 16 | 17 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> FillBuf<'a, R> { 18 | pub(super) fn new(reader: &'a mut R) -> Self { 19 | Self { reader: Some(reader) } 20 | } 21 | } 22 | 23 | impl<'a, R> Future for FillBuf<'a, R> 24 | where 25 | R: AsyncBufRead + ?Sized + Unpin, 26 | { 27 | type Output = io::Result<&'a [u8]>; 28 | 29 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 30 | let this = &mut *self; 31 | let reader = this.reader.take().expect("Polled FillBuf after completion"); 32 | 33 | match Pin::new(&mut *reader).poll_fill_buf(cx) { 34 | Poll::Ready(Ok(slice)) => { 35 | // With polonius it is possible to remove this lifetime transmutation and just have 36 | // the correct lifetime of the reference inferred based on which branch is taken 37 | let slice: &'a [u8] = unsafe { slice::from_raw_parts(slice.as_ptr(), slice.len()) }; 38 | Poll::Ready(Ok(slice)) 39 | } 40 | Poll::Ready(Err(err)) => Poll::Ready(Err(err)), 41 | Poll::Pending => { 42 | this.reader = Some(reader); 43 | Poll::Pending 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /futures-util/src/io/flush.rs: -------------------------------------------------------------------------------- 1 | use futures_core::future::Future; 2 | use futures_core::task::{Context, Poll}; 3 | use futures_io::AsyncWrite; 4 | use std::io; 5 | use std::pin::Pin; 6 | 7 | /// Future for the [`flush`](super::AsyncWriteExt::flush) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Flush<'a, W: ?Sized> { 11 | writer: &'a mut W, 12 | } 13 | 14 | impl Unpin for Flush<'_, W> {} 15 | 16 | impl<'a, W: AsyncWrite + ?Sized + Unpin> Flush<'a, W> { 17 | pub(super) fn new(writer: &'a mut W) -> Self { 18 | Self { writer } 19 | } 20 | } 21 | 22 | impl Future for Flush<'_, W> 23 | where 24 | W: AsyncWrite + ?Sized + Unpin, 25 | { 26 | type Output = io::Result<()>; 27 | 28 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 29 | Pin::new(&mut *self.writer).poll_flush(cx) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /futures-util/src/io/lines.rs: -------------------------------------------------------------------------------- 1 | use super::read_line::read_line_internal; 2 | use futures_core::ready; 3 | use futures_core::stream::Stream; 4 | use futures_core::task::{Context, Poll}; 5 | use futures_io::AsyncBufRead; 6 | use pin_project_lite::pin_project; 7 | use std::io; 8 | use std::mem; 9 | use std::pin::Pin; 10 | use std::string::String; 11 | use std::vec::Vec; 12 | 13 | pin_project! { 14 | /// Stream for the [`lines`](super::AsyncBufReadExt::lines) method. 15 | #[derive(Debug)] 16 | #[must_use = "streams do nothing unless polled"] 17 | pub struct Lines { 18 | #[pin] 19 | reader: R, 20 | buf: String, 21 | bytes: Vec, 22 | read: usize, 23 | } 24 | } 25 | 26 | impl Lines { 27 | pub(super) fn new(reader: R) -> Self { 28 | Self { reader, buf: String::new(), bytes: Vec::new(), read: 0 } 29 | } 30 | } 31 | 32 | impl Stream for Lines { 33 | type Item = io::Result; 34 | 35 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 36 | let this = self.project(); 37 | let n = ready!(read_line_internal(this.reader, cx, this.buf, this.bytes, this.read))?; 38 | *this.read = 0; 39 | if n == 0 && this.buf.is_empty() { 40 | return Poll::Ready(None); 41 | } 42 | if this.buf.ends_with('\n') { 43 | this.buf.pop(); 44 | if this.buf.ends_with('\r') { 45 | this.buf.pop(); 46 | } 47 | } 48 | Poll::Ready(Some(Ok(mem::take(this.buf)))) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /futures-util/src/io/read.rs: -------------------------------------------------------------------------------- 1 | use crate::io::AsyncRead; 2 | use futures_core::future::Future; 3 | use futures_core::task::{Context, Poll}; 4 | use std::io; 5 | use std::pin::Pin; 6 | 7 | /// Future for the [`read`](super::AsyncReadExt::read) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Read<'a, R: ?Sized> { 11 | reader: &'a mut R, 12 | buf: &'a mut [u8], 13 | } 14 | 15 | impl Unpin for Read<'_, R> {} 16 | 17 | impl<'a, R: AsyncRead + ?Sized + Unpin> Read<'a, R> { 18 | pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { 19 | Self { reader, buf } 20 | } 21 | } 22 | 23 | impl Future for Read<'_, R> { 24 | type Output = io::Result; 25 | 26 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 27 | let this = &mut *self; 28 | Pin::new(&mut this.reader).poll_read(cx, this.buf) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /futures-util/src/io/read_exact.rs: -------------------------------------------------------------------------------- 1 | use crate::io::AsyncRead; 2 | use futures_core::future::Future; 3 | use futures_core::ready; 4 | use futures_core::task::{Context, Poll}; 5 | use std::io; 6 | use std::mem; 7 | use std::pin::Pin; 8 | 9 | /// Future for the [`read_exact`](super::AsyncReadExt::read_exact) method. 10 | #[derive(Debug)] 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] 12 | pub struct ReadExact<'a, R: ?Sized> { 13 | reader: &'a mut R, 14 | buf: &'a mut [u8], 15 | } 16 | 17 | impl Unpin for ReadExact<'_, R> {} 18 | 19 | impl<'a, R: AsyncRead + ?Sized + Unpin> ReadExact<'a, R> { 20 | pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { 21 | Self { reader, buf } 22 | } 23 | } 24 | 25 | impl Future for ReadExact<'_, R> { 26 | type Output = io::Result<()>; 27 | 28 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 29 | let this = &mut *self; 30 | while !this.buf.is_empty() { 31 | let n = ready!(Pin::new(&mut this.reader).poll_read(cx, this.buf))?; 32 | { 33 | let (_, rest) = mem::take(&mut this.buf).split_at_mut(n); 34 | this.buf = rest; 35 | } 36 | if n == 0 { 37 | return Poll::Ready(Err(io::ErrorKind::UnexpectedEof.into())); 38 | } 39 | } 40 | Poll::Ready(Ok(())) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /futures-util/src/io/read_to_string.rs: -------------------------------------------------------------------------------- 1 | use super::read_to_end::read_to_end_internal; 2 | use futures_core::future::Future; 3 | use futures_core::ready; 4 | use futures_core::task::{Context, Poll}; 5 | use futures_io::AsyncRead; 6 | use std::pin::Pin; 7 | use std::string::String; 8 | use std::vec::Vec; 9 | use std::{io, mem, str}; 10 | 11 | /// Future for the [`read_to_string`](super::AsyncReadExt::read_to_string) method. 12 | #[derive(Debug)] 13 | #[must_use = "futures do nothing unless you `.await` or poll them"] 14 | pub struct ReadToString<'a, R: ?Sized> { 15 | reader: &'a mut R, 16 | buf: &'a mut String, 17 | bytes: Vec, 18 | start_len: usize, 19 | } 20 | 21 | impl Unpin for ReadToString<'_, R> {} 22 | 23 | impl<'a, R: AsyncRead + ?Sized + Unpin> ReadToString<'a, R> { 24 | pub(super) fn new(reader: &'a mut R, buf: &'a mut String) -> Self { 25 | let start_len = buf.len(); 26 | Self { reader, bytes: mem::take(buf).into_bytes(), buf, start_len } 27 | } 28 | } 29 | 30 | fn read_to_string_internal( 31 | reader: Pin<&mut R>, 32 | cx: &mut Context<'_>, 33 | buf: &mut String, 34 | bytes: &mut Vec, 35 | start_len: usize, 36 | ) -> Poll> { 37 | let ret = ready!(read_to_end_internal(reader, cx, bytes, start_len)); 38 | if str::from_utf8(bytes).is_err() { 39 | Poll::Ready(ret.and_then(|_| { 40 | Err(io::Error::new(io::ErrorKind::InvalidData, "stream did not contain valid UTF-8")) 41 | })) 42 | } else { 43 | debug_assert!(buf.is_empty()); 44 | // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. 45 | mem::swap(unsafe { buf.as_mut_vec() }, bytes); 46 | Poll::Ready(ret) 47 | } 48 | } 49 | 50 | impl Future for ReadToString<'_, A> 51 | where 52 | A: AsyncRead + ?Sized + Unpin, 53 | { 54 | type Output = io::Result; 55 | 56 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 57 | let Self { reader, buf, bytes, start_len } = &mut *self; 58 | read_to_string_internal(Pin::new(reader), cx, buf, bytes, *start_len) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /futures-util/src/io/read_until.rs: -------------------------------------------------------------------------------- 1 | use futures_core::future::Future; 2 | use futures_core::ready; 3 | use futures_core::task::{Context, Poll}; 4 | use futures_io::AsyncBufRead; 5 | use std::io; 6 | use std::pin::Pin; 7 | use std::vec::Vec; 8 | 9 | /// Future for the [`read_until`](super::AsyncBufReadExt::read_until) method. 10 | #[derive(Debug)] 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] 12 | pub struct ReadUntil<'a, R: ?Sized> { 13 | reader: &'a mut R, 14 | byte: u8, 15 | buf: &'a mut Vec, 16 | read: usize, 17 | } 18 | 19 | impl Unpin for ReadUntil<'_, R> {} 20 | 21 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadUntil<'a, R> { 22 | pub(super) fn new(reader: &'a mut R, byte: u8, buf: &'a mut Vec) -> Self { 23 | Self { reader, byte, buf, read: 0 } 24 | } 25 | } 26 | 27 | pub(super) fn read_until_internal( 28 | mut reader: Pin<&mut R>, 29 | cx: &mut Context<'_>, 30 | byte: u8, 31 | buf: &mut Vec, 32 | read: &mut usize, 33 | ) -> Poll> { 34 | loop { 35 | let (done, used) = { 36 | let available = ready!(reader.as_mut().poll_fill_buf(cx))?; 37 | if let Some(i) = memchr::memchr(byte, available) { 38 | buf.extend_from_slice(&available[..=i]); 39 | (true, i + 1) 40 | } else { 41 | buf.extend_from_slice(available); 42 | (false, available.len()) 43 | } 44 | }; 45 | reader.as_mut().consume(used); 46 | *read += used; 47 | if done || used == 0 { 48 | return Poll::Ready(Ok(*read)); 49 | } 50 | } 51 | } 52 | 53 | impl Future for ReadUntil<'_, R> { 54 | type Output = io::Result; 55 | 56 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 57 | let Self { reader, byte, buf, read } = &mut *self; 58 | read_until_internal(Pin::new(reader), cx, *byte, buf, read) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /futures-util/src/io/read_vectored.rs: -------------------------------------------------------------------------------- 1 | use crate::io::AsyncRead; 2 | use futures_core::future::Future; 3 | use futures_core::task::{Context, Poll}; 4 | use std::io::{self, IoSliceMut}; 5 | use std::pin::Pin; 6 | 7 | /// Future for the [`read_vectored`](super::AsyncReadExt::read_vectored) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct ReadVectored<'a, 'b, R: ?Sized> { 11 | reader: &'a mut R, 12 | bufs: &'a mut [IoSliceMut<'b>], 13 | } 14 | 15 | impl Unpin for ReadVectored<'_, '_, R> {} 16 | 17 | impl<'a, 'b, R: AsyncRead + ?Sized + Unpin> ReadVectored<'a, 'b, R> { 18 | pub(super) fn new(reader: &'a mut R, bufs: &'a mut [IoSliceMut<'b>]) -> Self { 19 | Self { reader, bufs } 20 | } 21 | } 22 | 23 | impl Future for ReadVectored<'_, '_, R> { 24 | type Output = io::Result; 25 | 26 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 27 | let this = &mut *self; 28 | Pin::new(&mut this.reader).poll_read_vectored(cx, this.bufs) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /futures-util/src/io/repeat.rs: -------------------------------------------------------------------------------- 1 | use futures_core::ready; 2 | use futures_core::task::{Context, Poll}; 3 | use futures_io::{AsyncRead, IoSliceMut}; 4 | use std::fmt; 5 | use std::io; 6 | use std::pin::Pin; 7 | 8 | /// Reader for the [`repeat()`] function. 9 | #[must_use = "readers do nothing unless polled"] 10 | pub struct Repeat { 11 | byte: u8, 12 | } 13 | 14 | /// Creates an instance of a reader that infinitely repeats one byte. 15 | /// 16 | /// All reads from this reader will succeed by filling the specified buffer with 17 | /// the given byte. 18 | /// 19 | /// # Examples 20 | /// 21 | /// ``` 22 | /// # futures::executor::block_on(async { 23 | /// use futures::io::{self, AsyncReadExt}; 24 | /// 25 | /// let mut buffer = [0; 3]; 26 | /// let mut reader = io::repeat(0b101); 27 | /// reader.read_exact(&mut buffer).await.unwrap(); 28 | /// assert_eq!(buffer, [0b101, 0b101, 0b101]); 29 | /// # Ok::<(), Box>(()) }).unwrap(); 30 | /// ``` 31 | pub fn repeat(byte: u8) -> Repeat { 32 | Repeat { byte } 33 | } 34 | 35 | impl AsyncRead for Repeat { 36 | #[inline] 37 | fn poll_read( 38 | self: Pin<&mut Self>, 39 | _: &mut Context<'_>, 40 | buf: &mut [u8], 41 | ) -> Poll> { 42 | for slot in &mut *buf { 43 | *slot = self.byte; 44 | } 45 | Poll::Ready(Ok(buf.len())) 46 | } 47 | 48 | #[inline] 49 | fn poll_read_vectored( 50 | mut self: Pin<&mut Self>, 51 | cx: &mut Context<'_>, 52 | bufs: &mut [IoSliceMut<'_>], 53 | ) -> Poll> { 54 | let mut nwritten = 0; 55 | for buf in bufs { 56 | nwritten += ready!(self.as_mut().poll_read(cx, buf))?; 57 | } 58 | Poll::Ready(Ok(nwritten)) 59 | } 60 | } 61 | 62 | impl fmt::Debug for Repeat { 63 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 64 | f.pad("Repeat { .. }") 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /futures-util/src/io/seek.rs: -------------------------------------------------------------------------------- 1 | use crate::io::{AsyncSeek, SeekFrom}; 2 | use futures_core::future::Future; 3 | use futures_core::task::{Context, Poll}; 4 | use std::io; 5 | use std::pin::Pin; 6 | 7 | /// Future for the [`seek`](crate::io::AsyncSeekExt::seek) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Seek<'a, S: ?Sized> { 11 | seek: &'a mut S, 12 | pos: SeekFrom, 13 | } 14 | 15 | impl Unpin for Seek<'_, S> {} 16 | 17 | impl<'a, S: AsyncSeek + ?Sized + Unpin> Seek<'a, S> { 18 | pub(super) fn new(seek: &'a mut S, pos: SeekFrom) -> Self { 19 | Self { seek, pos } 20 | } 21 | } 22 | 23 | impl Future for Seek<'_, S> { 24 | type Output = io::Result; 25 | 26 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 27 | let this = &mut *self; 28 | Pin::new(&mut this.seek).poll_seek(cx, this.pos) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /futures-util/src/io/sink.rs: -------------------------------------------------------------------------------- 1 | use futures_core::task::{Context, Poll}; 2 | use futures_io::{AsyncWrite, IoSlice}; 3 | use std::fmt; 4 | use std::io; 5 | use std::pin::Pin; 6 | 7 | /// Writer for the [`sink()`] function. 8 | #[must_use = "writers do nothing unless polled"] 9 | pub struct Sink { 10 | _priv: (), 11 | } 12 | 13 | /// Creates an instance of a writer which will successfully consume all data. 14 | /// 15 | /// All calls to `poll_write` on the returned instance will return `Poll::Ready(Ok(buf.len()))` 16 | /// and the contents of the buffer will not be inspected. 17 | /// 18 | /// # Examples 19 | /// 20 | /// ```rust 21 | /// # futures::executor::block_on(async { 22 | /// use futures::io::{self, AsyncWriteExt}; 23 | /// 24 | /// let buffer = vec![1, 2, 3, 5, 8]; 25 | /// let mut writer = io::sink(); 26 | /// let num_bytes = writer.write(&buffer).await?; 27 | /// assert_eq!(num_bytes, 5); 28 | /// # Ok::<(), Box>(()) }).unwrap(); 29 | /// ``` 30 | pub fn sink() -> Sink { 31 | Sink { _priv: () } 32 | } 33 | 34 | impl AsyncWrite for Sink { 35 | #[inline] 36 | fn poll_write( 37 | self: Pin<&mut Self>, 38 | _: &mut Context<'_>, 39 | buf: &[u8], 40 | ) -> Poll> { 41 | Poll::Ready(Ok(buf.len())) 42 | } 43 | 44 | #[inline] 45 | fn poll_write_vectored( 46 | self: Pin<&mut Self>, 47 | _: &mut Context<'_>, 48 | bufs: &[IoSlice<'_>], 49 | ) -> Poll> { 50 | Poll::Ready(Ok(bufs.iter().map(|b| b.len()).sum())) 51 | } 52 | 53 | #[inline] 54 | fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 55 | Poll::Ready(Ok(())) 56 | } 57 | #[inline] 58 | fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 59 | Poll::Ready(Ok(())) 60 | } 61 | } 62 | 63 | impl fmt::Debug for Sink { 64 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 65 | f.pad("Sink { .. }") 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /futures-util/src/io/write.rs: -------------------------------------------------------------------------------- 1 | use crate::io::AsyncWrite; 2 | use futures_core::future::Future; 3 | use futures_core::task::{Context, Poll}; 4 | use std::io; 5 | use std::pin::Pin; 6 | 7 | /// Future for the [`write`](super::AsyncWriteExt::write) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Write<'a, W: ?Sized> { 11 | writer: &'a mut W, 12 | buf: &'a [u8], 13 | } 14 | 15 | impl Unpin for Write<'_, W> {} 16 | 17 | impl<'a, W: AsyncWrite + ?Sized + Unpin> Write<'a, W> { 18 | pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { 19 | Self { writer, buf } 20 | } 21 | } 22 | 23 | impl Future for Write<'_, W> { 24 | type Output = io::Result; 25 | 26 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 27 | let this = &mut *self; 28 | Pin::new(&mut this.writer).poll_write(cx, this.buf) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /futures-util/src/io/write_all.rs: -------------------------------------------------------------------------------- 1 | use futures_core::future::Future; 2 | use futures_core::ready; 3 | use futures_core::task::{Context, Poll}; 4 | use futures_io::AsyncWrite; 5 | use std::io; 6 | use std::mem; 7 | use std::pin::Pin; 8 | 9 | /// Future for the [`write_all`](super::AsyncWriteExt::write_all) method. 10 | #[derive(Debug)] 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] 12 | pub struct WriteAll<'a, W: ?Sized> { 13 | writer: &'a mut W, 14 | buf: &'a [u8], 15 | } 16 | 17 | impl Unpin for WriteAll<'_, W> {} 18 | 19 | impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAll<'a, W> { 20 | pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { 21 | Self { writer, buf } 22 | } 23 | } 24 | 25 | impl Future for WriteAll<'_, W> { 26 | type Output = io::Result<()>; 27 | 28 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 29 | let this = &mut *self; 30 | while !this.buf.is_empty() { 31 | let n = ready!(Pin::new(&mut this.writer).poll_write(cx, this.buf))?; 32 | { 33 | let (_, rest) = mem::take(&mut this.buf).split_at(n); 34 | this.buf = rest; 35 | } 36 | if n == 0 { 37 | return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); 38 | } 39 | } 40 | 41 | Poll::Ready(Ok(())) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /futures-util/src/io/write_vectored.rs: -------------------------------------------------------------------------------- 1 | use crate::io::AsyncWrite; 2 | use futures_core::future::Future; 3 | use futures_core::task::{Context, Poll}; 4 | use std::io::{self, IoSlice}; 5 | use std::pin::Pin; 6 | 7 | /// Future for the [`write_vectored`](super::AsyncWriteExt::write_vectored) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct WriteVectored<'a, 'b, W: ?Sized> { 11 | writer: &'a mut W, 12 | bufs: &'a [IoSlice<'b>], 13 | } 14 | 15 | impl Unpin for WriteVectored<'_, '_, W> {} 16 | 17 | impl<'a, 'b, W: AsyncWrite + ?Sized + Unpin> WriteVectored<'a, 'b, W> { 18 | pub(super) fn new(writer: &'a mut W, bufs: &'a [IoSlice<'b>]) -> Self { 19 | Self { writer, bufs } 20 | } 21 | } 22 | 23 | impl Future for WriteVectored<'_, '_, W> { 24 | type Output = io::Result; 25 | 26 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 27 | let this = &mut *self; 28 | Pin::new(&mut this.writer).poll_write_vectored(cx, this.bufs) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /futures-util/src/lock/mod.rs: -------------------------------------------------------------------------------- 1 | //! Futures-powered synchronization primitives. 2 | //! 3 | //! This module is only available when the `std` or `alloc` feature of this 4 | //! library is activated, and it is activated by default. 5 | 6 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 7 | #[cfg(any(feature = "sink", feature = "io"))] 8 | #[cfg(not(feature = "bilock"))] 9 | pub(crate) use self::bilock::BiLock; 10 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 11 | #[cfg(feature = "bilock")] 12 | #[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] 13 | pub use self::bilock::{BiLock, BiLockAcquire, BiLockGuard, ReuniteError}; 14 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 15 | #[cfg(feature = "std")] 16 | pub use self::mutex::{ 17 | MappedMutexGuard, Mutex, MutexGuard, MutexLockFuture, OwnedMutexGuard, OwnedMutexLockFuture, 18 | }; 19 | 20 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 21 | #[cfg(any(feature = "bilock", feature = "sink", feature = "io"))] 22 | #[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] 23 | #[cfg_attr(not(feature = "bilock"), allow(unreachable_pub))] 24 | mod bilock; 25 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 26 | #[cfg(feature = "std")] 27 | mod mutex; 28 | -------------------------------------------------------------------------------- /futures-util/src/sink/close.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use core::pin::Pin; 3 | use futures_core::future::Future; 4 | use futures_core::task::{Context, Poll}; 5 | use futures_sink::Sink; 6 | 7 | /// Future for the [`close`](super::SinkExt::close) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Close<'a, Si: ?Sized, Item> { 11 | sink: &'a mut Si, 12 | _phantom: PhantomData, 13 | } 14 | 15 | impl Unpin for Close<'_, Si, Item> {} 16 | 17 | /// A future that completes when the sink has finished closing. 18 | /// 19 | /// The sink itself is returned after closing is complete. 20 | impl<'a, Si: Sink + Unpin + ?Sized, Item> Close<'a, Si, Item> { 21 | pub(super) fn new(sink: &'a mut Si) -> Self { 22 | Self { sink, _phantom: PhantomData } 23 | } 24 | } 25 | 26 | impl + Unpin + ?Sized, Item> Future for Close<'_, Si, Item> { 27 | type Output = Result<(), Si::Error>; 28 | 29 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 30 | Pin::new(&mut self.sink).poll_close(cx) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /futures-util/src/sink/drain.rs: -------------------------------------------------------------------------------- 1 | use super::assert_sink; 2 | use core::convert::Infallible; 3 | use core::marker::PhantomData; 4 | use core::pin::Pin; 5 | use futures_core::task::{Context, Poll}; 6 | use futures_sink::Sink; 7 | 8 | /// Sink for the [`drain`] function. 9 | #[derive(Debug)] 10 | #[must_use = "sinks do nothing unless polled"] 11 | pub struct Drain { 12 | marker: PhantomData, 13 | } 14 | 15 | /// Create a sink that will just discard all items given to it. 16 | /// 17 | /// Similar to [`io::Sink`](::std::io::Sink). 18 | /// 19 | /// # Examples 20 | /// 21 | /// ``` 22 | /// # futures::executor::block_on(async { 23 | /// use futures::sink::{self, SinkExt}; 24 | /// 25 | /// let mut drain = sink::drain(); 26 | /// drain.send(5).await?; 27 | /// # Ok::<(), std::convert::Infallible>(()) }).unwrap(); 28 | /// ``` 29 | pub fn drain() -> Drain { 30 | assert_sink::(Drain { marker: PhantomData }) 31 | } 32 | 33 | impl Unpin for Drain {} 34 | 35 | impl Clone for Drain { 36 | fn clone(&self) -> Self { 37 | drain() 38 | } 39 | } 40 | 41 | impl Sink for Drain { 42 | type Error = Infallible; 43 | 44 | fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { 45 | Poll::Ready(Ok(())) 46 | } 47 | 48 | fn start_send(self: Pin<&mut Self>, _item: T) -> Result<(), Self::Error> { 49 | Ok(()) 50 | } 51 | 52 | fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { 53 | Poll::Ready(Ok(())) 54 | } 55 | 56 | fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { 57 | Poll::Ready(Ok(())) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /futures-util/src/sink/err_into.rs: -------------------------------------------------------------------------------- 1 | use crate::sink::{SinkExt, SinkMapErr}; 2 | use futures_core::stream::{FusedStream, Stream}; 3 | use futures_sink::Sink; 4 | use pin_project_lite::pin_project; 5 | 6 | pin_project! { 7 | /// Sink for the [`sink_err_into`](super::SinkExt::sink_err_into) method. 8 | #[derive(Debug)] 9 | #[must_use = "sinks do nothing unless polled"] 10 | pub struct SinkErrInto, Item, E> { 11 | #[pin] 12 | sink: SinkMapErr E>, 13 | } 14 | } 15 | 16 | impl SinkErrInto 17 | where 18 | Si: Sink, 19 | Si::Error: Into, 20 | { 21 | pub(super) fn new(sink: Si) -> Self { 22 | Self { sink: SinkExt::sink_map_err(sink, Into::into) } 23 | } 24 | 25 | delegate_access_inner!(sink, Si, (.)); 26 | } 27 | 28 | impl Sink for SinkErrInto 29 | where 30 | Si: Sink, 31 | Si::Error: Into, 32 | { 33 | type Error = E; 34 | 35 | delegate_sink!(sink, Item); 36 | } 37 | 38 | // Forwarding impl of Stream from the underlying sink 39 | impl Stream for SinkErrInto 40 | where 41 | S: Sink + Stream, 42 | S::Error: Into, 43 | { 44 | type Item = S::Item; 45 | 46 | delegate_stream!(sink); 47 | } 48 | 49 | impl FusedStream for SinkErrInto 50 | where 51 | S: Sink + FusedStream, 52 | S::Error: Into, 53 | { 54 | fn is_terminated(&self) -> bool { 55 | self.sink.is_terminated() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /futures-util/src/sink/feed.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::future::Future; 3 | use futures_core::ready; 4 | use futures_core::task::{Context, Poll}; 5 | use futures_sink::Sink; 6 | 7 | /// Future for the [`feed`](super::SinkExt::feed) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Feed<'a, Si: ?Sized, Item> { 11 | sink: &'a mut Si, 12 | item: Option, 13 | } 14 | 15 | // Pinning is never projected to children 16 | impl Unpin for Feed<'_, Si, Item> {} 17 | 18 | impl<'a, Si: Sink + Unpin + ?Sized, Item> Feed<'a, Si, Item> { 19 | pub(super) fn new(sink: &'a mut Si, item: Item) -> Self { 20 | Feed { sink, item: Some(item) } 21 | } 22 | 23 | pub(super) fn sink_pin_mut(&mut self) -> Pin<&mut Si> { 24 | Pin::new(self.sink) 25 | } 26 | 27 | pub(super) fn is_item_pending(&self) -> bool { 28 | self.item.is_some() 29 | } 30 | } 31 | 32 | impl + Unpin + ?Sized, Item> Future for Feed<'_, Si, Item> { 33 | type Output = Result<(), Si::Error>; 34 | 35 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 36 | let this = self.get_mut(); 37 | let mut sink = Pin::new(&mut this.sink); 38 | ready!(sink.as_mut().poll_ready(cx))?; 39 | let item = this.item.take().expect("polled Feed after completion"); 40 | sink.as_mut().start_send(item)?; 41 | Poll::Ready(Ok(())) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /futures-util/src/sink/flush.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use core::pin::Pin; 3 | use futures_core::future::Future; 4 | use futures_core::task::{Context, Poll}; 5 | use futures_sink::Sink; 6 | 7 | /// Future for the [`flush`](super::SinkExt::flush) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Flush<'a, Si: ?Sized, Item> { 11 | sink: &'a mut Si, 12 | _phantom: PhantomData, 13 | } 14 | 15 | // Pin is never projected to a field. 16 | impl Unpin for Flush<'_, Si, Item> {} 17 | 18 | /// A future that completes when the sink has finished processing all 19 | /// pending requests. 20 | /// 21 | /// The sink itself is returned after flushing is complete; this adapter is 22 | /// intended to be used when you want to stop sending to the sink until 23 | /// all current requests are processed. 24 | impl<'a, Si: Sink + Unpin + ?Sized, Item> Flush<'a, Si, Item> { 25 | pub(super) fn new(sink: &'a mut Si) -> Self { 26 | Self { sink, _phantom: PhantomData } 27 | } 28 | } 29 | 30 | impl + Unpin + ?Sized, Item> Future for Flush<'_, Si, Item> { 31 | type Output = Result<(), Si::Error>; 32 | 33 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 34 | Pin::new(&mut self.sink).poll_flush(cx) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /futures-util/src/sink/map_err.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::stream::{FusedStream, Stream}; 3 | use futures_core::task::{Context, Poll}; 4 | use futures_sink::Sink; 5 | use pin_project_lite::pin_project; 6 | 7 | pin_project! { 8 | /// Sink for the [`sink_map_err`](super::SinkExt::sink_map_err) method. 9 | #[derive(Debug, Clone)] 10 | #[must_use = "sinks do nothing unless polled"] 11 | pub struct SinkMapErr { 12 | #[pin] 13 | sink: Si, 14 | f: Option, 15 | } 16 | } 17 | 18 | impl SinkMapErr { 19 | pub(super) fn new(sink: Si, f: F) -> Self { 20 | Self { sink, f: Some(f) } 21 | } 22 | 23 | delegate_access_inner!(sink, Si, ()); 24 | 25 | fn take_f(self: Pin<&mut Self>) -> F { 26 | self.project().f.take().expect("polled MapErr after completion") 27 | } 28 | } 29 | 30 | impl Sink for SinkMapErr 31 | where 32 | Si: Sink, 33 | F: FnOnce(Si::Error) -> E, 34 | { 35 | type Error = E; 36 | 37 | fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 38 | self.as_mut().project().sink.poll_ready(cx).map_err(|e| self.as_mut().take_f()(e)) 39 | } 40 | 41 | fn start_send(mut self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { 42 | self.as_mut().project().sink.start_send(item).map_err(|e| self.as_mut().take_f()(e)) 43 | } 44 | 45 | fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 46 | self.as_mut().project().sink.poll_flush(cx).map_err(|e| self.as_mut().take_f()(e)) 47 | } 48 | 49 | fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 50 | self.as_mut().project().sink.poll_close(cx).map_err(|e| self.as_mut().take_f()(e)) 51 | } 52 | } 53 | 54 | // Forwarding impl of Stream from the underlying sink 55 | impl Stream for SinkMapErr { 56 | type Item = S::Item; 57 | 58 | delegate_stream!(sink); 59 | } 60 | 61 | impl FusedStream for SinkMapErr { 62 | fn is_terminated(&self) -> bool { 63 | self.sink.is_terminated() 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /futures-util/src/sink/send.rs: -------------------------------------------------------------------------------- 1 | use super::Feed; 2 | use core::pin::Pin; 3 | use futures_core::future::Future; 4 | use futures_core::ready; 5 | use futures_core::task::{Context, Poll}; 6 | use futures_sink::Sink; 7 | 8 | /// Future for the [`send`](super::SinkExt::send) method. 9 | #[derive(Debug)] 10 | #[must_use = "futures do nothing unless you `.await` or poll them"] 11 | pub struct Send<'a, Si: ?Sized, Item> { 12 | feed: Feed<'a, Si, Item>, 13 | } 14 | 15 | // Pinning is never projected to children 16 | impl Unpin for Send<'_, Si, Item> {} 17 | 18 | impl<'a, Si: Sink + Unpin + ?Sized, Item> Send<'a, Si, Item> { 19 | pub(super) fn new(sink: &'a mut Si, item: Item) -> Self { 20 | Self { feed: Feed::new(sink, item) } 21 | } 22 | } 23 | 24 | impl + Unpin + ?Sized, Item> Future for Send<'_, Si, Item> { 25 | type Output = Result<(), Si::Error>; 26 | 27 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 28 | let this = &mut *self; 29 | 30 | if this.feed.is_item_pending() { 31 | ready!(Pin::new(&mut this.feed).poll(cx))?; 32 | debug_assert!(!this.feed.is_item_pending()); 33 | } 34 | 35 | // we're done sending the item, but want to block on flushing the 36 | // sink 37 | ready!(this.feed.sink_pin_mut().poll_flush(cx))?; 38 | 39 | Poll::Ready(Ok(())) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /futures-util/src/stream/abortable.rs: -------------------------------------------------------------------------------- 1 | use super::assert_stream; 2 | use crate::stream::{AbortHandle, Abortable}; 3 | use crate::Stream; 4 | 5 | /// Creates a new `Abortable` stream and an `AbortHandle` which can be used to stop it. 6 | /// 7 | /// This function is a convenient (but less flexible) alternative to calling 8 | /// `AbortHandle::new` and `Abortable::new` manually. 9 | /// 10 | /// This function is only available when the `std` or `alloc` feature of this 11 | /// library is activated, and it is activated by default. 12 | pub fn abortable(stream: St) -> (Abortable, AbortHandle) 13 | where 14 | St: Stream, 15 | { 16 | let (handle, reg) = AbortHandle::new_pair(); 17 | let abortable = assert_stream::(Abortable::new(stream, reg)); 18 | (abortable, handle) 19 | } 20 | -------------------------------------------------------------------------------- /futures-util/src/stream/empty.rs: -------------------------------------------------------------------------------- 1 | use super::assert_stream; 2 | use core::marker::PhantomData; 3 | use core::pin::Pin; 4 | use futures_core::stream::{FusedStream, Stream}; 5 | use futures_core::task::{Context, Poll}; 6 | 7 | /// Stream for the [`empty`] function. 8 | #[derive(Debug)] 9 | #[must_use = "streams do nothing unless polled"] 10 | pub struct Empty { 11 | _phantom: PhantomData, 12 | } 13 | 14 | /// Creates a stream which contains no elements. 15 | /// 16 | /// The returned stream will always return `Ready(None)` when polled. 17 | pub fn empty() -> Empty { 18 | assert_stream::(Empty { _phantom: PhantomData }) 19 | } 20 | 21 | impl Unpin for Empty {} 22 | 23 | impl FusedStream for Empty { 24 | fn is_terminated(&self) -> bool { 25 | true 26 | } 27 | } 28 | 29 | impl Stream for Empty { 30 | type Item = T; 31 | 32 | fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 33 | Poll::Ready(None) 34 | } 35 | 36 | fn size_hint(&self) -> (usize, Option) { 37 | (0, Some(0)) 38 | } 39 | } 40 | 41 | impl Clone for Empty { 42 | fn clone(&self) -> Self { 43 | empty() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /futures-util/src/stream/futures_unordered/abort.rs: -------------------------------------------------------------------------------- 1 | pub(super) fn abort(s: &str) -> ! { 2 | struct DoublePanic; 3 | 4 | impl Drop for DoublePanic { 5 | fn drop(&mut self) { 6 | panic!("panicking twice to abort the program"); 7 | } 8 | } 9 | 10 | let _bomb = DoublePanic; 11 | panic!("{}", s); 12 | } 13 | -------------------------------------------------------------------------------- /futures-util/src/stream/iter.rs: -------------------------------------------------------------------------------- 1 | use super::assert_stream; 2 | use core::pin::Pin; 3 | use futures_core::stream::Stream; 4 | use futures_core::task::{Context, Poll}; 5 | 6 | /// Stream for the [`iter`] function. 7 | #[derive(Debug, Clone)] 8 | #[must_use = "streams do nothing unless polled"] 9 | pub struct Iter { 10 | iter: I, 11 | } 12 | 13 | impl Iter { 14 | /// Acquires a reference to the underlying iterator that this stream is pulling from. 15 | pub fn get_ref(&self) -> &I { 16 | &self.iter 17 | } 18 | 19 | /// Acquires a mutable reference to the underlying iterator that this stream is pulling from. 20 | pub fn get_mut(&mut self) -> &mut I { 21 | &mut self.iter 22 | } 23 | 24 | /// Consumes this stream, returning the underlying iterator. 25 | pub fn into_inner(self) -> I { 26 | self.iter 27 | } 28 | } 29 | 30 | impl Unpin for Iter {} 31 | 32 | /// Converts an `Iterator` into a `Stream` which is always ready 33 | /// to yield the next value. 34 | /// 35 | /// Iterators in Rust don't express the ability to block, so this adapter 36 | /// simply always calls `iter.next()` and returns that. 37 | /// 38 | /// ``` 39 | /// # futures::executor::block_on(async { 40 | /// use futures::stream::{self, StreamExt}; 41 | /// 42 | /// let stream = stream::iter(vec![17, 19]); 43 | /// assert_eq!(vec![17, 19], stream.collect::>().await); 44 | /// # }); 45 | /// ``` 46 | pub fn iter(i: I) -> Iter 47 | where 48 | I: IntoIterator, 49 | { 50 | assert_stream::(Iter { iter: i.into_iter() }) 51 | } 52 | 53 | impl Stream for Iter 54 | where 55 | I: Iterator, 56 | { 57 | type Item = I::Item; 58 | 59 | fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 60 | Poll::Ready(self.iter.next()) 61 | } 62 | 63 | fn size_hint(&self) -> (usize, Option) { 64 | self.iter.size_hint() 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /futures-util/src/stream/once.rs: -------------------------------------------------------------------------------- 1 | use super::assert_stream; 2 | use core::pin::Pin; 3 | use futures_core::future::Future; 4 | use futures_core::ready; 5 | use futures_core::stream::{FusedStream, Stream}; 6 | use futures_core::task::{Context, Poll}; 7 | use pin_project_lite::pin_project; 8 | 9 | /// Creates a stream of a single element. 10 | /// 11 | /// ``` 12 | /// # futures::executor::block_on(async { 13 | /// use futures::stream::{self, StreamExt}; 14 | /// 15 | /// let stream = stream::once(async { 17 }); 16 | /// let collected = stream.collect::>().await; 17 | /// assert_eq!(collected, vec![17]); 18 | /// # }); 19 | /// ``` 20 | pub fn once(future: Fut) -> Once { 21 | assert_stream::(Once::new(future)) 22 | } 23 | 24 | pin_project! { 25 | /// A stream which emits single element and then EOF. 26 | #[derive(Debug)] 27 | #[must_use = "streams do nothing unless polled"] 28 | pub struct Once { 29 | #[pin] 30 | future: Option 31 | } 32 | } 33 | 34 | impl Once { 35 | pub(crate) fn new(future: Fut) -> Self { 36 | Self { future: Some(future) } 37 | } 38 | } 39 | 40 | impl Stream for Once { 41 | type Item = Fut::Output; 42 | 43 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 44 | let mut this = self.project(); 45 | let v = match this.future.as_mut().as_pin_mut() { 46 | Some(fut) => ready!(fut.poll(cx)), 47 | None => return Poll::Ready(None), 48 | }; 49 | 50 | this.future.set(None); 51 | Poll::Ready(Some(v)) 52 | } 53 | 54 | fn size_hint(&self) -> (usize, Option) { 55 | if self.future.is_some() { 56 | (1, Some(1)) 57 | } else { 58 | (0, Some(0)) 59 | } 60 | } 61 | } 62 | 63 | impl FusedStream for Once { 64 | fn is_terminated(&self) -> bool { 65 | self.future.is_none() 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /futures-util/src/stream/pending.rs: -------------------------------------------------------------------------------- 1 | use super::assert_stream; 2 | use core::marker; 3 | use core::pin::Pin; 4 | use futures_core::stream::{FusedStream, Stream}; 5 | use futures_core::task::{Context, Poll}; 6 | 7 | /// Stream for the [`pending()`] function. 8 | #[derive(Debug)] 9 | #[must_use = "streams do nothing unless polled"] 10 | pub struct Pending { 11 | _data: marker::PhantomData, 12 | } 13 | 14 | /// Creates a stream which never returns any elements. 15 | /// 16 | /// The returned stream will always return `Pending` when polled. 17 | pub fn pending() -> Pending { 18 | assert_stream::(Pending { _data: marker::PhantomData }) 19 | } 20 | 21 | impl Unpin for Pending {} 22 | 23 | impl FusedStream for Pending { 24 | fn is_terminated(&self) -> bool { 25 | true 26 | } 27 | } 28 | 29 | impl Stream for Pending { 30 | type Item = T; 31 | 32 | fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 33 | Poll::Pending 34 | } 35 | 36 | fn size_hint(&self) -> (usize, Option) { 37 | (0, Some(0)) 38 | } 39 | } 40 | 41 | impl Clone for Pending { 42 | fn clone(&self) -> Self { 43 | pending() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /futures-util/src/stream/poll_fn.rs: -------------------------------------------------------------------------------- 1 | //! Definition of the `PollFn` combinator 2 | 3 | use super::assert_stream; 4 | use core::fmt; 5 | use core::pin::Pin; 6 | use futures_core::stream::Stream; 7 | use futures_core::task::{Context, Poll}; 8 | 9 | /// Stream for the [`poll_fn`] function. 10 | #[must_use = "streams do nothing unless polled"] 11 | pub struct PollFn { 12 | f: F, 13 | } 14 | 15 | impl Unpin for PollFn {} 16 | 17 | impl fmt::Debug for PollFn { 18 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 19 | f.debug_struct("PollFn").finish() 20 | } 21 | } 22 | 23 | /// Creates a new stream wrapping a function returning `Poll>`. 24 | /// 25 | /// Polling the returned stream calls the wrapped function. 26 | /// 27 | /// # Examples 28 | /// 29 | /// ``` 30 | /// use futures::stream::poll_fn; 31 | /// use futures::task::Poll; 32 | /// 33 | /// let mut counter = 1usize; 34 | /// 35 | /// let read_stream = poll_fn(move |_| -> Poll> { 36 | /// if counter == 0 { return Poll::Ready(None); } 37 | /// counter -= 1; 38 | /// Poll::Ready(Some("Hello, World!".to_owned())) 39 | /// }); 40 | /// ``` 41 | pub fn poll_fn(f: F) -> PollFn 42 | where 43 | F: FnMut(&mut Context<'_>) -> Poll>, 44 | { 45 | assert_stream::(PollFn { f }) 46 | } 47 | 48 | impl Stream for PollFn 49 | where 50 | F: FnMut(&mut Context<'_>) -> Poll>, 51 | { 52 | type Item = T; 53 | 54 | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 55 | (&mut self.f)(cx) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /futures-util/src/stream/repeat.rs: -------------------------------------------------------------------------------- 1 | use super::assert_stream; 2 | use core::pin::Pin; 3 | use futures_core::stream::{FusedStream, Stream}; 4 | use futures_core::task::{Context, Poll}; 5 | 6 | /// Stream for the [`repeat`] function. 7 | #[derive(Debug, Clone)] 8 | #[must_use = "streams do nothing unless polled"] 9 | pub struct Repeat { 10 | item: T, 11 | } 12 | 13 | /// Create a stream which produces the same item repeatedly. 14 | /// 15 | /// The stream never terminates. Note that you likely want to avoid 16 | /// usage of `collect` or such on the returned stream as it will exhaust 17 | /// available memory as it tries to just fill up all RAM. 18 | /// 19 | /// ``` 20 | /// # futures::executor::block_on(async { 21 | /// use futures::stream::{self, StreamExt}; 22 | /// 23 | /// let stream = stream::repeat(9); 24 | /// assert_eq!(vec![9, 9, 9], stream.take(3).collect::>().await); 25 | /// # }); 26 | /// ``` 27 | pub fn repeat(item: T) -> Repeat 28 | where 29 | T: Clone, 30 | { 31 | assert_stream::(Repeat { item }) 32 | } 33 | 34 | impl Unpin for Repeat {} 35 | 36 | impl Stream for Repeat 37 | where 38 | T: Clone, 39 | { 40 | type Item = T; 41 | 42 | fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 43 | Poll::Ready(Some(self.item.clone())) 44 | } 45 | 46 | fn size_hint(&self) -> (usize, Option) { 47 | (usize::MAX, None) 48 | } 49 | } 50 | 51 | impl FusedStream for Repeat 52 | where 53 | T: Clone, 54 | { 55 | fn is_terminated(&self) -> bool { 56 | false 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/catch_unwind.rs: -------------------------------------------------------------------------------- 1 | use futures_core::stream::{FusedStream, Stream}; 2 | use futures_core::task::{Context, Poll}; 3 | use pin_project_lite::pin_project; 4 | use std::any::Any; 5 | use std::boxed::Box; 6 | use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe}; 7 | use std::pin::Pin; 8 | 9 | pin_project! { 10 | /// Stream for the [`catch_unwind`](super::StreamExt::catch_unwind) method. 11 | #[derive(Debug)] 12 | #[must_use = "streams do nothing unless polled"] 13 | pub struct CatchUnwind { 14 | #[pin] 15 | stream: St, 16 | caught_unwind: bool, 17 | } 18 | } 19 | 20 | impl CatchUnwind { 21 | pub(super) fn new(stream: St) -> Self { 22 | Self { stream, caught_unwind: false } 23 | } 24 | 25 | delegate_access_inner!(stream, St, ()); 26 | } 27 | 28 | impl Stream for CatchUnwind { 29 | type Item = Result>; 30 | 31 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 32 | let mut this = self.project(); 33 | 34 | if *this.caught_unwind { 35 | Poll::Ready(None) 36 | } else { 37 | let res = catch_unwind(AssertUnwindSafe(|| this.stream.as_mut().poll_next(cx))); 38 | 39 | match res { 40 | Ok(poll) => poll.map(|opt| opt.map(Ok)), 41 | Err(e) => { 42 | *this.caught_unwind = true; 43 | Poll::Ready(Some(Err(e))) 44 | } 45 | } 46 | } 47 | } 48 | 49 | fn size_hint(&self) -> (usize, Option) { 50 | if self.caught_unwind { 51 | (0, Some(0)) 52 | } else { 53 | self.stream.size_hint() 54 | } 55 | } 56 | } 57 | 58 | impl FusedStream for CatchUnwind { 59 | fn is_terminated(&self) -> bool { 60 | self.caught_unwind || self.stream.is_terminated() 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/collect.rs: -------------------------------------------------------------------------------- 1 | use core::mem; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::ready; 5 | use futures_core::stream::{FusedStream, Stream}; 6 | use futures_core::task::{Context, Poll}; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Future for the [`collect`](super::StreamExt::collect) method. 11 | #[derive(Debug)] 12 | #[must_use = "futures do nothing unless you `.await` or poll them"] 13 | pub struct Collect { 14 | #[pin] 15 | stream: St, 16 | collection: C, 17 | } 18 | } 19 | 20 | impl Collect { 21 | fn finish(self: Pin<&mut Self>) -> C { 22 | mem::take(self.project().collection) 23 | } 24 | 25 | pub(super) fn new(stream: St) -> Self { 26 | Self { stream, collection: Default::default() } 27 | } 28 | } 29 | 30 | impl FusedFuture for Collect 31 | where 32 | St: FusedStream, 33 | C: Default + Extend, 34 | { 35 | fn is_terminated(&self) -> bool { 36 | self.stream.is_terminated() 37 | } 38 | } 39 | 40 | impl Future for Collect 41 | where 42 | St: Stream, 43 | C: Default + Extend, 44 | { 45 | type Output = C; 46 | 47 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 48 | let mut this = self.as_mut().project(); 49 | loop { 50 | match ready!(this.stream.as_mut().poll_next(cx)) { 51 | Some(e) => this.collection.extend(Some(e)), 52 | None => return Poll::Ready(self.finish()), 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/concat.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::future::{FusedFuture, Future}; 3 | use futures_core::ready; 4 | use futures_core::stream::{FusedStream, Stream}; 5 | use futures_core::task::{Context, Poll}; 6 | use pin_project_lite::pin_project; 7 | 8 | pin_project! { 9 | /// Future for the [`concat`](super::StreamExt::concat) method. 10 | #[derive(Debug)] 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] 12 | pub struct Concat { 13 | #[pin] 14 | stream: St, 15 | accum: Option, 16 | } 17 | } 18 | 19 | impl Concat 20 | where 21 | St: Stream, 22 | St::Item: Extend<::Item> + IntoIterator + Default, 23 | { 24 | pub(super) fn new(stream: St) -> Self { 25 | Self { stream, accum: None } 26 | } 27 | } 28 | 29 | impl Future for Concat 30 | where 31 | St: Stream, 32 | St::Item: Extend<::Item> + IntoIterator + Default, 33 | { 34 | type Output = St::Item; 35 | 36 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 37 | let mut this = self.project(); 38 | 39 | loop { 40 | match ready!(this.stream.as_mut().poll_next(cx)) { 41 | None => return Poll::Ready(this.accum.take().unwrap_or_default()), 42 | Some(e) => { 43 | if let Some(a) = this.accum { 44 | a.extend(e) 45 | } else { 46 | *this.accum = Some(e) 47 | } 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | impl FusedFuture for Concat 55 | where 56 | St: FusedStream, 57 | St::Item: Extend<::Item> + IntoIterator + Default, 58 | { 59 | fn is_terminated(&self) -> bool { 60 | self.accum.is_none() && self.stream.is_terminated() 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/count.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::ready; 5 | use futures_core::stream::{FusedStream, Stream}; 6 | use futures_core::task::{Context, Poll}; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Future for the [`count`](super::StreamExt::count) method. 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] 12 | pub struct Count { 13 | #[pin] 14 | stream: St, 15 | count: usize 16 | } 17 | } 18 | 19 | impl fmt::Debug for Count 20 | where 21 | St: fmt::Debug, 22 | { 23 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 24 | f.debug_struct("Count").field("stream", &self.stream).field("count", &self.count).finish() 25 | } 26 | } 27 | 28 | impl Count { 29 | pub(super) fn new(stream: St) -> Self { 30 | Self { stream, count: 0 } 31 | } 32 | } 33 | 34 | impl FusedFuture for Count { 35 | fn is_terminated(&self) -> bool { 36 | self.stream.is_terminated() 37 | } 38 | } 39 | 40 | impl Future for Count { 41 | type Output = usize; 42 | 43 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 44 | let mut this = self.project(); 45 | 46 | Poll::Ready(loop { 47 | match ready!(this.stream.as_mut().poll_next(cx)) { 48 | Some(_) => *this.count += 1, 49 | None => break *this.count, 50 | } 51 | }) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/cycle.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::ready; 3 | use futures_core::stream::{FusedStream, Stream}; 4 | use futures_core::task::{Context, Poll}; 5 | use pin_project_lite::pin_project; 6 | 7 | pin_project! { 8 | /// Stream for the [`cycle`](super::StreamExt::cycle) method. 9 | #[derive(Debug)] 10 | #[must_use = "streams do nothing unless polled"] 11 | pub struct Cycle { 12 | orig: St, 13 | #[pin] 14 | stream: St, 15 | } 16 | } 17 | 18 | impl Cycle 19 | where 20 | St: Clone + Stream, 21 | { 22 | pub(super) fn new(stream: St) -> Self { 23 | Self { orig: stream.clone(), stream } 24 | } 25 | } 26 | 27 | impl Stream for Cycle 28 | where 29 | St: Clone + Stream, 30 | { 31 | type Item = St::Item; 32 | 33 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 34 | let mut this = self.project(); 35 | 36 | match ready!(this.stream.as_mut().poll_next(cx)) { 37 | None => { 38 | this.stream.set(this.orig.clone()); 39 | this.stream.poll_next(cx) 40 | } 41 | item => Poll::Ready(item), 42 | } 43 | } 44 | 45 | fn size_hint(&self) -> (usize, Option) { 46 | // the cycle stream is either empty or infinite 47 | match self.orig.size_hint() { 48 | size @ (0, Some(0)) => size, 49 | (0, _) => (0, None), 50 | _ => (usize::MAX, None), 51 | } 52 | } 53 | } 54 | 55 | impl FusedStream for Cycle 56 | where 57 | St: Clone + Stream, 58 | { 59 | fn is_terminated(&self) -> bool { 60 | // the cycle stream is either empty or infinite 61 | matches!(self.size_hint(), (0, Some(0))) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/enumerate.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::ready; 3 | use futures_core::stream::{FusedStream, Stream}; 4 | use futures_core::task::{Context, Poll}; 5 | #[cfg(feature = "sink")] 6 | use futures_sink::Sink; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Stream for the [`enumerate`](super::StreamExt::enumerate) method. 11 | #[derive(Debug)] 12 | #[must_use = "streams do nothing unless polled"] 13 | pub struct Enumerate { 14 | #[pin] 15 | stream: St, 16 | count: usize, 17 | } 18 | } 19 | 20 | impl Enumerate { 21 | pub(super) fn new(stream: St) -> Self { 22 | Self { stream, count: 0 } 23 | } 24 | 25 | delegate_access_inner!(stream, St, ()); 26 | } 27 | 28 | impl FusedStream for Enumerate { 29 | fn is_terminated(&self) -> bool { 30 | self.stream.is_terminated() 31 | } 32 | } 33 | 34 | impl Stream for Enumerate { 35 | type Item = (usize, St::Item); 36 | 37 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 38 | let this = self.project(); 39 | 40 | match ready!(this.stream.poll_next(cx)) { 41 | Some(item) => { 42 | let prev_count = *this.count; 43 | *this.count += 1; 44 | Poll::Ready(Some((prev_count, item))) 45 | } 46 | None => Poll::Ready(None), 47 | } 48 | } 49 | 50 | fn size_hint(&self) -> (usize, Option) { 51 | self.stream.size_hint() 52 | } 53 | } 54 | 55 | // Forwarding impl of Sink from the underlying stream 56 | #[cfg(feature = "sink")] 57 | impl Sink for Enumerate 58 | where 59 | S: Stream + Sink, 60 | { 61 | type Error = S::Error; 62 | 63 | delegate_sink!(stream, Item); 64 | } 65 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/flatten.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::ready; 3 | use futures_core::stream::{FusedStream, Stream}; 4 | use futures_core::task::{Context, Poll}; 5 | #[cfg(feature = "sink")] 6 | use futures_sink::Sink; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Stream for the [`flatten`](super::StreamExt::flatten) method. 11 | #[derive(Debug)] 12 | #[must_use = "streams do nothing unless polled"] 13 | pub struct Flatten { 14 | #[pin] 15 | stream: St, 16 | #[pin] 17 | next: Option, 18 | } 19 | } 20 | 21 | impl Flatten { 22 | pub(super) fn new(stream: St) -> Self { 23 | Self { stream, next: None } 24 | } 25 | 26 | delegate_access_inner!(stream, St, ()); 27 | } 28 | 29 | impl FusedStream for Flatten 30 | where 31 | St: FusedStream, 32 | St::Item: Stream, 33 | { 34 | fn is_terminated(&self) -> bool { 35 | self.next.is_none() && self.stream.is_terminated() 36 | } 37 | } 38 | 39 | impl Stream for Flatten 40 | where 41 | St: Stream, 42 | St::Item: Stream, 43 | { 44 | type Item = ::Item; 45 | 46 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 47 | let mut this = self.project(); 48 | Poll::Ready(loop { 49 | if let Some(s) = this.next.as_mut().as_pin_mut() { 50 | if let Some(item) = ready!(s.poll_next(cx)) { 51 | break Some(item); 52 | } else { 53 | this.next.set(None); 54 | } 55 | } else if let Some(s) = ready!(this.stream.as_mut().poll_next(cx)) { 56 | this.next.set(Some(s)); 57 | } else { 58 | break None; 59 | } 60 | }) 61 | } 62 | } 63 | 64 | // Forwarding impl of Sink from the underlying stream 65 | #[cfg(feature = "sink")] 66 | impl Sink for Flatten 67 | where 68 | S: Stream + Sink, 69 | { 70 | type Error = S::Error; 71 | 72 | delegate_sink!(stream, Item); 73 | } 74 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/fuse.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::ready; 3 | use futures_core::stream::{FusedStream, Stream}; 4 | use futures_core::task::{Context, Poll}; 5 | #[cfg(feature = "sink")] 6 | use futures_sink::Sink; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Stream for the [`fuse`](super::StreamExt::fuse) method. 11 | #[derive(Debug)] 12 | #[must_use = "streams do nothing unless polled"] 13 | pub struct Fuse { 14 | #[pin] 15 | stream: St, 16 | done: bool, 17 | } 18 | } 19 | 20 | impl Fuse { 21 | pub(crate) fn new(stream: St) -> Self { 22 | Self { stream, done: false } 23 | } 24 | 25 | /// Returns whether the underlying stream has finished or not. 26 | /// 27 | /// If this method returns `true`, then all future calls to poll are 28 | /// guaranteed to return `None`. If this returns `false`, then the 29 | /// underlying stream is still in use. 30 | pub fn is_done(&self) -> bool { 31 | self.done 32 | } 33 | 34 | delegate_access_inner!(stream, St, ()); 35 | } 36 | 37 | impl FusedStream for Fuse { 38 | fn is_terminated(&self) -> bool { 39 | self.done 40 | } 41 | } 42 | 43 | impl Stream for Fuse { 44 | type Item = S::Item; 45 | 46 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 47 | let this = self.project(); 48 | 49 | if *this.done { 50 | return Poll::Ready(None); 51 | } 52 | 53 | let item = ready!(this.stream.poll_next(cx)); 54 | if item.is_none() { 55 | *this.done = true; 56 | } 57 | Poll::Ready(item) 58 | } 59 | 60 | fn size_hint(&self) -> (usize, Option) { 61 | if self.done { 62 | (0, Some(0)) 63 | } else { 64 | self.stream.size_hint() 65 | } 66 | } 67 | } 68 | 69 | // Forwarding impl of Sink from the underlying stream 70 | #[cfg(feature = "sink")] 71 | impl, Item> Sink for Fuse { 72 | type Error = S::Error; 73 | 74 | delegate_sink!(stream, Item); 75 | } 76 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/map.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | use core::pin::Pin; 3 | use futures_core::ready; 4 | use futures_core::stream::{FusedStream, Stream}; 5 | use futures_core::task::{Context, Poll}; 6 | #[cfg(feature = "sink")] 7 | use futures_sink::Sink; 8 | use pin_project_lite::pin_project; 9 | 10 | use crate::fns::FnMut1; 11 | 12 | pin_project! { 13 | /// Stream for the [`map`](super::StreamExt::map) method. 14 | #[must_use = "streams do nothing unless polled"] 15 | pub struct Map { 16 | #[pin] 17 | stream: St, 18 | f: F, 19 | } 20 | } 21 | 22 | impl fmt::Debug for Map 23 | where 24 | St: fmt::Debug, 25 | { 26 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 27 | f.debug_struct("Map").field("stream", &self.stream).finish() 28 | } 29 | } 30 | 31 | impl Map { 32 | pub(crate) fn new(stream: St, f: F) -> Self { 33 | Self { stream, f } 34 | } 35 | 36 | delegate_access_inner!(stream, St, ()); 37 | } 38 | 39 | impl FusedStream for Map 40 | where 41 | St: FusedStream, 42 | F: FnMut1, 43 | { 44 | fn is_terminated(&self) -> bool { 45 | self.stream.is_terminated() 46 | } 47 | } 48 | 49 | impl Stream for Map 50 | where 51 | St: Stream, 52 | F: FnMut1, 53 | { 54 | type Item = F::Output; 55 | 56 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 57 | let mut this = self.project(); 58 | let res = ready!(this.stream.as_mut().poll_next(cx)); 59 | Poll::Ready(res.map(|x| this.f.call_mut(x))) 60 | } 61 | 62 | fn size_hint(&self) -> (usize, Option) { 63 | self.stream.size_hint() 64 | } 65 | } 66 | 67 | // Forwarding impl of Sink from the underlying stream 68 | #[cfg(feature = "sink")] 69 | impl Sink for Map 70 | where 71 | St: Stream + Sink, 72 | F: FnMut1, 73 | { 74 | type Error = St::Error; 75 | 76 | delegate_sink!(stream, Item); 77 | } 78 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/next.rs: -------------------------------------------------------------------------------- 1 | use crate::stream::StreamExt; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::stream::{FusedStream, Stream}; 5 | use futures_core::task::{Context, Poll}; 6 | 7 | /// Future for the [`next`](super::StreamExt::next) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct Next<'a, St: ?Sized> { 11 | stream: &'a mut St, 12 | } 13 | 14 | impl Unpin for Next<'_, St> {} 15 | 16 | impl<'a, St: ?Sized + Stream + Unpin> Next<'a, St> { 17 | pub(super) fn new(stream: &'a mut St) -> Self { 18 | Self { stream } 19 | } 20 | } 21 | 22 | impl FusedFuture for Next<'_, St> { 23 | fn is_terminated(&self) -> bool { 24 | self.stream.is_terminated() 25 | } 26 | } 27 | 28 | impl Future for Next<'_, St> { 29 | type Output = Option; 30 | 31 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 32 | self.stream.poll_next_unpin(cx) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/select_next_some.rs: -------------------------------------------------------------------------------- 1 | use crate::stream::StreamExt; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::ready; 5 | use futures_core::stream::FusedStream; 6 | use futures_core::task::{Context, Poll}; 7 | 8 | /// Future for the [`select_next_some`](super::StreamExt::select_next_some) 9 | /// method. 10 | #[derive(Debug)] 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] 12 | pub struct SelectNextSome<'a, St: ?Sized> { 13 | stream: &'a mut St, 14 | } 15 | 16 | impl<'a, St: ?Sized> SelectNextSome<'a, St> { 17 | pub(super) fn new(stream: &'a mut St) -> Self { 18 | Self { stream } 19 | } 20 | } 21 | 22 | impl FusedFuture for SelectNextSome<'_, St> { 23 | fn is_terminated(&self) -> bool { 24 | self.stream.is_terminated() 25 | } 26 | } 27 | 28 | impl Future for SelectNextSome<'_, St> { 29 | type Output = St::Item; 30 | 31 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 32 | assert!(!self.stream.is_terminated(), "SelectNextSome polled after terminated"); 33 | 34 | if let Some(item) = ready!(self.stream.poll_next_unpin(cx)) { 35 | Poll::Ready(item) 36 | } else { 37 | debug_assert!(self.stream.is_terminated()); 38 | cx.waker().wake_by_ref(); 39 | Poll::Pending 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/skip.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::ready; 3 | use futures_core::stream::{FusedStream, Stream}; 4 | use futures_core::task::{Context, Poll}; 5 | #[cfg(feature = "sink")] 6 | use futures_sink::Sink; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Stream for the [`skip`](super::StreamExt::skip) method. 11 | #[derive(Debug)] 12 | #[must_use = "streams do nothing unless polled"] 13 | pub struct Skip { 14 | #[pin] 15 | stream: St, 16 | remaining: usize, 17 | } 18 | } 19 | 20 | impl Skip { 21 | pub(super) fn new(stream: St, n: usize) -> Self { 22 | Self { stream, remaining: n } 23 | } 24 | 25 | delegate_access_inner!(stream, St, ()); 26 | } 27 | 28 | impl FusedStream for Skip { 29 | fn is_terminated(&self) -> bool { 30 | self.stream.is_terminated() 31 | } 32 | } 33 | 34 | impl Stream for Skip { 35 | type Item = St::Item; 36 | 37 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 38 | let mut this = self.project(); 39 | 40 | while *this.remaining > 0 { 41 | if ready!(this.stream.as_mut().poll_next(cx)).is_some() { 42 | *this.remaining -= 1; 43 | } else { 44 | return Poll::Ready(None); 45 | } 46 | } 47 | 48 | this.stream.poll_next(cx) 49 | } 50 | 51 | fn size_hint(&self) -> (usize, Option) { 52 | let (lower, upper) = self.stream.size_hint(); 53 | 54 | let lower = lower.saturating_sub(self.remaining); 55 | let upper = upper.map(|x| x.saturating_sub(self.remaining)); 56 | 57 | (lower, upper) 58 | } 59 | } 60 | 61 | // Forwarding impl of Sink from the underlying stream 62 | #[cfg(feature = "sink")] 63 | impl Sink for Skip 64 | where 65 | S: Stream + Sink, 66 | { 67 | type Error = S::Error; 68 | 69 | delegate_sink!(stream, Item); 70 | } 71 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/try_for_each.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | use core::pin::Pin; 3 | use futures_core::future::{Future, TryFuture}; 4 | use futures_core::ready; 5 | use futures_core::stream::Stream; 6 | use futures_core::task::{Context, Poll}; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Future for the [`try_for_each`](super::StreamExt::try_for_each) method. 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] 12 | pub struct TryForEach { 13 | #[pin] 14 | stream: St, 15 | f: F, 16 | #[pin] 17 | future: Option, 18 | } 19 | } 20 | 21 | impl fmt::Debug for TryForEach 22 | where 23 | St: fmt::Debug, 24 | Fut: fmt::Debug, 25 | { 26 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 27 | f.debug_struct("TryForEach") 28 | .field("stream", &self.stream) 29 | .field("future", &self.future) 30 | .finish() 31 | } 32 | } 33 | 34 | impl TryForEach 35 | where 36 | St: Stream, 37 | F: FnMut(St::Item) -> Fut, 38 | Fut: TryFuture, 39 | { 40 | pub(super) fn new(stream: St, f: F) -> Self { 41 | Self { stream, f, future: None } 42 | } 43 | } 44 | 45 | impl Future for TryForEach 46 | where 47 | St: Stream, 48 | F: FnMut(St::Item) -> Fut, 49 | Fut: TryFuture, 50 | { 51 | type Output = Result<(), Fut::Error>; 52 | 53 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 54 | let mut this = self.project(); 55 | loop { 56 | if let Some(fut) = this.future.as_mut().as_pin_mut() { 57 | ready!(fut.try_poll(cx))?; 58 | this.future.set(None); 59 | } else { 60 | match ready!(this.stream.as_mut().poll_next(cx)) { 61 | Some(e) => this.future.set(Some((this.f)(e))), 62 | None => break, 63 | } 64 | } 65 | } 66 | Poll::Ready(Ok(())) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /futures-util/src/stream/stream/unzip.rs: -------------------------------------------------------------------------------- 1 | use core::mem; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::ready; 5 | use futures_core::stream::{FusedStream, Stream}; 6 | use futures_core::task::{Context, Poll}; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Future for the [`unzip`](super::StreamExt::unzip) method. 11 | #[derive(Debug)] 12 | #[must_use = "futures do nothing unless you `.await` or poll them"] 13 | pub struct Unzip { 14 | #[pin] 15 | stream: St, 16 | left: FromA, 17 | right: FromB, 18 | } 19 | } 20 | 21 | impl Unzip { 22 | fn finish(self: Pin<&mut Self>) -> (FromA, FromB) { 23 | let this = self.project(); 24 | (mem::take(this.left), mem::take(this.right)) 25 | } 26 | 27 | pub(super) fn new(stream: St) -> Self { 28 | Self { stream, left: Default::default(), right: Default::default() } 29 | } 30 | } 31 | 32 | impl FusedFuture for Unzip 33 | where 34 | St: FusedStream, 35 | FromA: Default + Extend, 36 | FromB: Default + Extend, 37 | { 38 | fn is_terminated(&self) -> bool { 39 | self.stream.is_terminated() 40 | } 41 | } 42 | 43 | impl Future for Unzip 44 | where 45 | St: Stream, 46 | FromA: Default + Extend, 47 | FromB: Default + Extend, 48 | { 49 | type Output = (FromA, FromB); 50 | 51 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<(FromA, FromB)> { 52 | let mut this = self.as_mut().project(); 53 | loop { 54 | match ready!(this.stream.as_mut().poll_next(cx)) { 55 | Some(e) => { 56 | this.left.extend(Some(e.0)); 57 | this.right.extend(Some(e.1)); 58 | } 59 | None => return Poll::Ready(self.finish()), 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /futures-util/src/stream/try_stream/into_stream.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::stream::{FusedStream, Stream, TryStream}; 3 | use futures_core::task::{Context, Poll}; 4 | #[cfg(feature = "sink")] 5 | use futures_sink::Sink; 6 | use pin_project_lite::pin_project; 7 | 8 | pin_project! { 9 | /// Stream for the [`into_stream`](super::TryStreamExt::into_stream) method. 10 | #[derive(Debug)] 11 | #[must_use = "streams do nothing unless polled"] 12 | pub struct IntoStream { 13 | #[pin] 14 | stream: St, 15 | } 16 | } 17 | 18 | impl IntoStream { 19 | #[inline] 20 | pub(super) fn new(stream: St) -> Self { 21 | Self { stream } 22 | } 23 | 24 | delegate_access_inner!(stream, St, ()); 25 | } 26 | 27 | impl FusedStream for IntoStream { 28 | fn is_terminated(&self) -> bool { 29 | self.stream.is_terminated() 30 | } 31 | } 32 | 33 | impl Stream for IntoStream { 34 | type Item = Result; 35 | 36 | #[inline] 37 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 38 | self.project().stream.try_poll_next(cx) 39 | } 40 | 41 | fn size_hint(&self) -> (usize, Option) { 42 | self.stream.size_hint() 43 | } 44 | } 45 | 46 | // Forwarding impl of Sink from the underlying stream 47 | #[cfg(feature = "sink")] 48 | impl, Item> Sink for IntoStream { 49 | type Error = S::Error; 50 | 51 | delegate_sink!(stream, Item); 52 | } 53 | -------------------------------------------------------------------------------- /futures-util/src/stream/try_stream/try_collect.rs: -------------------------------------------------------------------------------- 1 | use core::mem; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::ready; 5 | use futures_core::stream::{FusedStream, TryStream}; 6 | use futures_core::task::{Context, Poll}; 7 | use pin_project_lite::pin_project; 8 | 9 | pin_project! { 10 | /// Future for the [`try_collect`](super::TryStreamExt::try_collect) method. 11 | #[derive(Debug)] 12 | #[must_use = "futures do nothing unless you `.await` or poll them"] 13 | pub struct TryCollect { 14 | #[pin] 15 | stream: St, 16 | items: C, 17 | } 18 | } 19 | 20 | impl TryCollect { 21 | pub(super) fn new(s: St) -> Self { 22 | Self { stream: s, items: Default::default() } 23 | } 24 | } 25 | 26 | impl FusedFuture for TryCollect 27 | where 28 | St: TryStream + FusedStream, 29 | C: Default + Extend, 30 | { 31 | fn is_terminated(&self) -> bool { 32 | self.stream.is_terminated() 33 | } 34 | } 35 | 36 | impl Future for TryCollect 37 | where 38 | St: TryStream, 39 | C: Default + Extend, 40 | { 41 | type Output = Result; 42 | 43 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 44 | let mut this = self.project(); 45 | Poll::Ready(Ok(loop { 46 | match ready!(this.stream.as_mut().try_poll_next(cx)?) { 47 | Some(x) => this.items.extend(Some(x)), 48 | None => break mem::take(this.items), 49 | } 50 | })) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /futures-util/src/stream/try_stream/try_concat.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use futures_core::future::Future; 3 | use futures_core::ready; 4 | use futures_core::stream::TryStream; 5 | use futures_core::task::{Context, Poll}; 6 | use pin_project_lite::pin_project; 7 | 8 | pin_project! { 9 | /// Future for the [`try_concat`](super::TryStreamExt::try_concat) method. 10 | #[derive(Debug)] 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] 12 | pub struct TryConcat { 13 | #[pin] 14 | stream: St, 15 | accum: Option, 16 | } 17 | } 18 | 19 | impl TryConcat 20 | where 21 | St: TryStream, 22 | St::Ok: Extend<::Item> + IntoIterator + Default, 23 | { 24 | pub(super) fn new(stream: St) -> Self { 25 | Self { stream, accum: None } 26 | } 27 | } 28 | 29 | impl Future for TryConcat 30 | where 31 | St: TryStream, 32 | St::Ok: Extend<::Item> + IntoIterator + Default, 33 | { 34 | type Output = Result; 35 | 36 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 37 | let mut this = self.project(); 38 | 39 | Poll::Ready(Ok(loop { 40 | if let Some(x) = ready!(this.stream.as_mut().try_poll_next(cx)?) { 41 | if let Some(a) = this.accum { 42 | a.extend(x) 43 | } else { 44 | *this.accum = Some(x) 45 | } 46 | } else { 47 | break this.accum.take().unwrap_or_default(); 48 | } 49 | })) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /futures-util/src/stream/try_stream/try_next.rs: -------------------------------------------------------------------------------- 1 | use crate::stream::TryStreamExt; 2 | use core::pin::Pin; 3 | use futures_core::future::{FusedFuture, Future}; 4 | use futures_core::stream::{FusedStream, TryStream}; 5 | use futures_core::task::{Context, Poll}; 6 | 7 | /// Future for the [`try_next`](super::TryStreamExt::try_next) method. 8 | #[derive(Debug)] 9 | #[must_use = "futures do nothing unless you `.await` or poll them"] 10 | pub struct TryNext<'a, St: ?Sized> { 11 | stream: &'a mut St, 12 | } 13 | 14 | impl Unpin for TryNext<'_, St> {} 15 | 16 | impl<'a, St: ?Sized + TryStream + Unpin> TryNext<'a, St> { 17 | pub(super) fn new(stream: &'a mut St) -> Self { 18 | Self { stream } 19 | } 20 | } 21 | 22 | impl FusedFuture for TryNext<'_, St> { 23 | fn is_terminated(&self) -> bool { 24 | self.stream.is_terminated() 25 | } 26 | } 27 | 28 | impl Future for TryNext<'_, St> { 29 | type Output = Result, St::Error>; 30 | 31 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 32 | self.stream.try_poll_next_unpin(cx)?.map(Ok) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /futures-util/src/task/mod.rs: -------------------------------------------------------------------------------- 1 | //! Tools for working with tasks. 2 | //! 3 | //! This module contains: 4 | //! 5 | //! - [`Spawn`], a trait for spawning new tasks. 6 | //! - [`Context`], a context of an asynchronous task, 7 | //! including a handle for waking up the task. 8 | //! - [`Waker`], a handle for waking up a task. 9 | //! 10 | //! The remaining types and traits in the module are used for implementing 11 | //! executors or dealing with synchronization issues around task wakeup. 12 | 13 | #[doc(no_inline)] 14 | pub use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; 15 | 16 | pub use futures_task::{FutureObj, LocalFutureObj, LocalSpawn, Spawn, SpawnError, UnsafeFutureObj}; 17 | 18 | pub use futures_task::noop_waker; 19 | pub use futures_task::noop_waker_ref; 20 | 21 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 22 | #[cfg(feature = "alloc")] 23 | pub use futures_task::ArcWake; 24 | 25 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 26 | #[cfg(feature = "alloc")] 27 | pub use futures_task::waker; 28 | 29 | #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] 30 | #[cfg(feature = "alloc")] 31 | pub use futures_task::{waker_ref, WakerRef}; 32 | 33 | #[cfg_attr( 34 | target_os = "none", 35 | cfg(any(target_has_atomic = "ptr", feature = "portable-atomic")) 36 | )] 37 | pub use futures_core::task::__internal::AtomicWaker; 38 | 39 | mod spawn; 40 | pub use self::spawn::{LocalSpawnExt, SpawnExt}; 41 | -------------------------------------------------------------------------------- /futures-util/src/unfold_state.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | pin_project! { 6 | /// UnfoldState used for stream and sink unfolds 7 | #[project = UnfoldStateProj] 8 | #[project_replace = UnfoldStateProjReplace] 9 | #[derive(Debug)] 10 | pub(crate) enum UnfoldState { 11 | Value { 12 | value: T, 13 | }, 14 | Future { 15 | #[pin] 16 | future: Fut, 17 | }, 18 | Empty, 19 | } 20 | } 21 | 22 | impl UnfoldState { 23 | pub(crate) fn is_empty(&self) -> bool { 24 | matches!(self, Self::Empty) 25 | } 26 | 27 | pub(crate) fn is_future(&self) -> bool { 28 | matches!(self, Self::Future { .. }) 29 | } 30 | 31 | pub(crate) fn project_future(self: Pin<&mut Self>) -> Option> { 32 | match self.project() { 33 | UnfoldStateProj::Future { future } => Some(future), 34 | _ => None, 35 | } 36 | } 37 | 38 | pub(crate) fn take_value(self: Pin<&mut Self>) -> Option { 39 | match &*self { 40 | Self::Value { .. } => match self.project_replace(Self::Empty) { 41 | UnfoldStateProjReplace::Value { value } => Some(value), 42 | _ => unreachable!(), 43 | }, 44 | _ => None, 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /futures/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /futures/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /futures/tests/_require_features.rs: -------------------------------------------------------------------------------- 1 | #[cfg(not(all( 2 | feature = "std", 3 | feature = "alloc", 4 | feature = "async-await", 5 | feature = "compat", 6 | feature = "io-compat", 7 | feature = "executor", 8 | feature = "thread-pool", 9 | )))] 10 | compile_error!( 11 | "`futures` tests must have all stable features activated: \ 12 | use `--all-features` or `--features default,thread-pool,io-compat`" 13 | ); 14 | -------------------------------------------------------------------------------- /futures/tests/compat.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "compat")] 2 | #![cfg(not(miri))] // Miri does not support epoll 3 | 4 | use futures::compat::Future01CompatExt; 5 | use futures::prelude::*; 6 | use std::time::Instant; 7 | use tokio::runtime::Runtime; 8 | use tokio::timer::Delay; 9 | 10 | #[test] 11 | fn can_use_01_futures_in_a_03_future_running_on_a_01_executor() { 12 | let f = Delay::new(Instant::now()).compat(); 13 | 14 | let mut runtime = Runtime::new().unwrap(); 15 | runtime.block_on(f.boxed().compat()).unwrap(); 16 | } 17 | -------------------------------------------------------------------------------- /futures/tests/future_abortable.rs: -------------------------------------------------------------------------------- 1 | use futures::channel::oneshot; 2 | use futures::executor::block_on; 3 | use futures::future::{abortable, Aborted, FutureExt}; 4 | use futures::task::{Context, Poll}; 5 | use futures_test::task::new_count_waker; 6 | 7 | #[test] 8 | fn abortable_works() { 9 | let (_tx, a_rx) = oneshot::channel::<()>(); 10 | let (abortable_rx, abort_handle) = abortable(a_rx); 11 | 12 | abort_handle.abort(); 13 | assert!(abortable_rx.is_aborted()); 14 | assert_eq!(Err(Aborted), block_on(abortable_rx)); 15 | } 16 | 17 | #[test] 18 | fn abortable_awakens() { 19 | let (_tx, a_rx) = oneshot::channel::<()>(); 20 | let (mut abortable_rx, abort_handle) = abortable(a_rx); 21 | 22 | let (waker, counter) = new_count_waker(); 23 | let mut cx = Context::from_waker(&waker); 24 | 25 | assert_eq!(counter, 0); 26 | assert_eq!(Poll::Pending, abortable_rx.poll_unpin(&mut cx)); 27 | assert_eq!(counter, 0); 28 | 29 | abort_handle.abort(); 30 | assert_eq!(counter, 1); 31 | assert!(abortable_rx.is_aborted()); 32 | assert_eq!(Poll::Ready(Err(Aborted)), abortable_rx.poll_unpin(&mut cx)); 33 | } 34 | 35 | #[test] 36 | fn abortable_resolves() { 37 | let (tx, a_rx) = oneshot::channel::<()>(); 38 | let (abortable_rx, _abort_handle) = abortable(a_rx); 39 | 40 | tx.send(()).unwrap(); 41 | 42 | assert!(!abortable_rx.is_aborted()); 43 | assert_eq!(Ok(Ok(())), block_on(abortable_rx)); 44 | } 45 | -------------------------------------------------------------------------------- /futures/tests/future_fuse.rs: -------------------------------------------------------------------------------- 1 | use futures::future::{self, FutureExt}; 2 | use futures::task::Context; 3 | use futures_test::task::panic_waker; 4 | 5 | #[test] 6 | fn fuse() { 7 | let mut future = future::ready::(2).fuse(); 8 | let waker = panic_waker(); 9 | let mut cx = Context::from_waker(&waker); 10 | assert!(future.poll_unpin(&mut cx).is_ready()); 11 | assert!(future.poll_unpin(&mut cx).is_pending()); 12 | } 13 | -------------------------------------------------------------------------------- /futures/tests/future_inspect.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{self, FutureExt}; 3 | 4 | #[test] 5 | fn smoke() { 6 | let mut counter = 0; 7 | 8 | { 9 | let work = future::ready::(40).inspect(|val| { 10 | counter += *val; 11 | }); 12 | assert_eq!(block_on(work), 40); 13 | } 14 | 15 | assert_eq!(counter, 40); 16 | } 17 | -------------------------------------------------------------------------------- /futures/tests/future_join.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{self, Future}; 3 | use std::task::Poll; 4 | 5 | /// This tests verifies (through miri) that self-referencing 6 | /// futures are not invalidated when joining them. 7 | #[test] 8 | fn futures_join_macro_self_referential() { 9 | block_on(async { futures::join!(yield_now(), trouble()) }); 10 | } 11 | 12 | async fn trouble() { 13 | let lucky_number = 42; 14 | let problematic_variable = &lucky_number; 15 | 16 | yield_now().await; 17 | 18 | // problematic dereference 19 | let _ = { *problematic_variable }; 20 | } 21 | 22 | fn yield_now() -> impl Future { 23 | let mut yielded = false; 24 | future::poll_fn(move |cx| { 25 | if core::mem::replace(&mut yielded, true) { 26 | Poll::Ready(()) 27 | } else { 28 | cx.waker().wake_by_ref(); 29 | Poll::Pending 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /futures/tests/future_join_all.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{join_all, ready, Future, JoinAll}; 3 | use std::fmt::Debug; 4 | use std::pin::pin; 5 | 6 | #[track_caller] 7 | fn assert_done(actual_fut: impl Future, expected: T) 8 | where 9 | T: PartialEq + Debug, 10 | { 11 | let output = block_on(pin!(actual_fut)); 12 | assert_eq!(output, expected); 13 | } 14 | 15 | #[test] 16 | fn collect_collects() { 17 | assert_done(join_all(vec![ready(1), ready(2)]), vec![1, 2]); 18 | assert_done(join_all(vec![ready(1)]), vec![1]); 19 | // REVIEW: should this be implemented? 20 | // assert_done(join_all(Vec::::new()), vec![]); 21 | 22 | // TODO: needs more tests 23 | } 24 | 25 | #[test] 26 | fn join_all_iter_lifetime() { 27 | // In futures-rs version 0.1, this function would fail to typecheck due to an overly 28 | // conservative type parameterization of `JoinAll`. 29 | fn sizes(bufs: Vec<&[u8]>) -> impl Future> { 30 | let iter = bufs.into_iter().map(|b| ready::(b.len())); 31 | join_all(iter) 32 | } 33 | 34 | assert_done(sizes(vec![&[1, 2, 3], &[], &[0]]), vec![3_usize, 0, 1]); 35 | } 36 | 37 | #[test] 38 | fn join_all_from_iter() { 39 | assert_done(vec![ready(1), ready(2)].into_iter().collect::>(), vec![1, 2]) 40 | } 41 | -------------------------------------------------------------------------------- /futures/tests/future_obj.rs: -------------------------------------------------------------------------------- 1 | use futures::future::{Future, FutureExt, FutureObj}; 2 | use futures::task::{Context, Poll}; 3 | use std::pin::Pin; 4 | 5 | #[test] 6 | fn dropping_does_not_segfault() { 7 | FutureObj::new(async { String::new() }.boxed()); 8 | } 9 | 10 | #[test] 11 | fn dropping_drops_the_future() { 12 | let mut times_dropped = 0; 13 | 14 | struct Inc<'a>(&'a mut u32); 15 | 16 | impl Future for Inc<'_> { 17 | type Output = (); 18 | 19 | fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<()> { 20 | unimplemented!() 21 | } 22 | } 23 | 24 | impl Drop for Inc<'_> { 25 | fn drop(&mut self) { 26 | *self.0 += 1; 27 | } 28 | } 29 | 30 | FutureObj::new(Inc(&mut times_dropped).boxed()); 31 | 32 | assert_eq!(times_dropped, 1); 33 | } 34 | -------------------------------------------------------------------------------- /futures/tests/future_select_all.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{ready, select_all}; 3 | use std::collections::HashSet; 4 | 5 | #[test] 6 | fn smoke() { 7 | let v = vec![ready(1), ready(2), ready(3)]; 8 | 9 | let mut c = vec![1, 2, 3].into_iter().collect::>(); 10 | 11 | let (i, idx, v) = block_on(select_all(v)); 12 | assert!(c.remove(&i)); 13 | assert_eq!(idx, 0); 14 | 15 | let (i, idx, v) = block_on(select_all(v)); 16 | assert!(c.remove(&i)); 17 | assert_eq!(idx, 0); 18 | 19 | let (i, idx, v) = block_on(select_all(v)); 20 | assert!(c.remove(&i)); 21 | assert_eq!(idx, 0); 22 | 23 | assert!(c.is_empty()); 24 | assert!(v.is_empty()); 25 | } 26 | -------------------------------------------------------------------------------- /futures/tests/future_select_ok.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{err, ok, select_ok}; 3 | 4 | #[test] 5 | fn ignore_err() { 6 | let v = vec![err(1), err(2), ok(3), ok(4)]; 7 | 8 | let (i, v) = block_on(select_ok(v)).ok().unwrap(); 9 | assert_eq!(i, 3); 10 | 11 | assert_eq!(v.len(), 1); 12 | 13 | let (i, v) = block_on(select_ok(v)).ok().unwrap(); 14 | assert_eq!(i, 4); 15 | 16 | assert!(v.is_empty()); 17 | } 18 | 19 | #[test] 20 | fn last_err() { 21 | let v = vec![ok(1), err(2), err(3)]; 22 | 23 | let (i, v) = block_on(select_ok(v)).ok().unwrap(); 24 | assert_eq!(i, 1); 25 | 26 | assert_eq!(v.len(), 2); 27 | 28 | let i = block_on(select_ok(v)).err().unwrap(); 29 | assert_eq!(i, 3); 30 | } 31 | -------------------------------------------------------------------------------- /futures/tests/future_try_join_all.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{err, ok, try_join_all, Future, TryJoinAll}; 3 | use std::fmt::Debug; 4 | use std::pin::pin; 5 | 6 | #[track_caller] 7 | fn assert_done(actual_fut: impl Future, expected: T) 8 | where 9 | T: PartialEq + Debug, 10 | { 11 | let output = block_on(pin!(actual_fut)); 12 | assert_eq!(output, expected); 13 | } 14 | 15 | #[test] 16 | fn collect_collects() { 17 | assert_done(try_join_all(vec![ok(1), ok(2)]), Ok::<_, usize>(vec![1, 2])); 18 | assert_done(try_join_all(vec![ok(1), err(2)]), Err(2)); 19 | assert_done(try_join_all(vec![ok(1)]), Ok::<_, usize>(vec![1])); 20 | // REVIEW: should this be implemented? 21 | // assert_done(try_join_all(Vec::::new()), Ok(vec![])); 22 | 23 | // TODO: needs more tests 24 | } 25 | 26 | #[test] 27 | fn try_join_all_iter_lifetime() { 28 | // In futures-rs version 0.1, this function would fail to typecheck due to an overly 29 | // conservative type parameterization of `TryJoinAll`. 30 | fn sizes(bufs: Vec<&[u8]>) -> impl Future, ()>> { 31 | let iter = bufs.into_iter().map(|b| ok::(b.len())); 32 | try_join_all(iter) 33 | } 34 | 35 | assert_done(sizes(vec![&[1, 2, 3], &[], &[0]]), Ok(vec![3_usize, 0, 1])); 36 | } 37 | 38 | #[test] 39 | fn try_join_all_from_iter() { 40 | assert_done( 41 | vec![ok(1), ok(2)].into_iter().collect::>(), 42 | Ok::<_, usize>(vec![1, 2]), 43 | ) 44 | } 45 | -------------------------------------------------------------------------------- /futures/tests/io_cursor.rs: -------------------------------------------------------------------------------- 1 | use assert_matches::assert_matches; 2 | use futures::executor::block_on; 3 | use futures::future::lazy; 4 | use futures::io::{AsyncWrite, Cursor}; 5 | use futures::task::Poll; 6 | use std::pin::Pin; 7 | 8 | #[test] 9 | fn cursor_asyncwrite_vec() { 10 | let mut cursor = Cursor::new(vec![0; 5]); 11 | block_on(lazy(|cx| { 12 | assert_matches!(Pin::new(&mut cursor).poll_write(cx, &[1, 2]), Poll::Ready(Ok(2))); 13 | assert_matches!(Pin::new(&mut cursor).poll_write(cx, &[3, 4]), Poll::Ready(Ok(2))); 14 | assert_matches!(Pin::new(&mut cursor).poll_write(cx, &[5, 6]), Poll::Ready(Ok(2))); 15 | assert_matches!(Pin::new(&mut cursor).poll_write(cx, &[6, 7]), Poll::Ready(Ok(2))); 16 | })); 17 | assert_eq!(cursor.into_inner(), [1, 2, 3, 4, 5, 6, 6, 7]); 18 | } 19 | 20 | #[test] 21 | fn cursor_asyncwrite_box() { 22 | let mut cursor = Cursor::new(vec![0; 5].into_boxed_slice()); 23 | block_on(lazy(|cx| { 24 | assert_matches!(Pin::new(&mut cursor).poll_write(cx, &[1, 2]), Poll::Ready(Ok(2))); 25 | assert_matches!(Pin::new(&mut cursor).poll_write(cx, &[3, 4]), Poll::Ready(Ok(2))); 26 | assert_matches!(Pin::new(&mut cursor).poll_write(cx, &[5, 6]), Poll::Ready(Ok(1))); 27 | assert_matches!(Pin::new(&mut cursor).poll_write(cx, &[6, 7]), Poll::Ready(Ok(0))); 28 | })); 29 | assert_eq!(&*cursor.into_inner(), [1, 2, 3, 4, 5]); 30 | } 31 | -------------------------------------------------------------------------------- /futures/tests/io_read.rs: -------------------------------------------------------------------------------- 1 | use futures::io::AsyncRead; 2 | use futures_test::task::panic_context; 3 | use std::io; 4 | use std::pin::Pin; 5 | use std::task::{Context, Poll}; 6 | 7 | type MockReaderFun = Box Poll>>; 8 | 9 | struct MockReader { 10 | fun: MockReaderFun, 11 | } 12 | 13 | impl MockReader { 14 | fn new(fun: impl FnMut(&mut [u8]) -> Poll> + 'static) -> Self { 15 | Self { fun: Box::new(fun) } 16 | } 17 | } 18 | 19 | impl AsyncRead for MockReader { 20 | fn poll_read( 21 | self: Pin<&mut Self>, 22 | _cx: &mut Context<'_>, 23 | buf: &mut [u8], 24 | ) -> Poll> { 25 | (self.get_mut().fun)(buf) 26 | } 27 | } 28 | 29 | /// Verifies that the default implementation of `poll_read_vectored` 30 | /// calls `poll_read` with an empty slice if no buffers are provided. 31 | #[test] 32 | fn read_vectored_no_buffers() { 33 | let mut reader = MockReader::new(|buf| { 34 | assert_eq!(buf, b""); 35 | Err(io::ErrorKind::BrokenPipe.into()).into() 36 | }); 37 | let cx = &mut panic_context(); 38 | let bufs = &mut []; 39 | 40 | let res = Pin::new(&mut reader).poll_read_vectored(cx, bufs); 41 | let res = res.map_err(|e| e.kind()); 42 | assert_eq!(res, Poll::Ready(Err(io::ErrorKind::BrokenPipe))) 43 | } 44 | 45 | /// Verifies that the default implementation of `poll_read_vectored` 46 | /// calls `poll_read` with the first non-empty buffer. 47 | #[test] 48 | fn read_vectored_first_non_empty() { 49 | let mut reader = MockReader::new(|buf| { 50 | assert_eq!(buf.len(), 4); 51 | buf.copy_from_slice(b"four"); 52 | Poll::Ready(Ok(4)) 53 | }); 54 | let cx = &mut panic_context(); 55 | let mut buf = [0; 4]; 56 | let bufs = &mut [ 57 | io::IoSliceMut::new(&mut []), 58 | io::IoSliceMut::new(&mut []), 59 | io::IoSliceMut::new(&mut buf), 60 | ]; 61 | 62 | let res = Pin::new(&mut reader).poll_read_vectored(cx, bufs); 63 | let res = res.map_err(|e| e.kind()); 64 | assert_eq!(res, Poll::Ready(Ok(4))); 65 | assert_eq!(buf, b"four"[..]); 66 | } 67 | -------------------------------------------------------------------------------- /futures/tests/io_read_exact.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::io::AsyncReadExt; 3 | 4 | #[test] 5 | fn read_exact() { 6 | let mut reader: &[u8] = &[1, 2, 3, 4, 5]; 7 | let mut out = [0u8; 3]; 8 | 9 | let res = block_on(reader.read_exact(&mut out)); // read 3 bytes out 10 | assert!(res.is_ok()); 11 | assert_eq!(out, [1, 2, 3]); 12 | assert_eq!(reader.len(), 2); 13 | 14 | let res = block_on(reader.read_exact(&mut out)); // read another 3 bytes, but only 2 bytes left 15 | assert!(res.is_err()); 16 | assert_eq!(reader.len(), 0); 17 | } 18 | -------------------------------------------------------------------------------- /futures/tests/io_read_to_end.rs: -------------------------------------------------------------------------------- 1 | use futures::{ 2 | executor::block_on, 3 | io::{self, AsyncRead, AsyncReadExt}, 4 | task::{Context, Poll}, 5 | }; 6 | use std::pin::Pin; 7 | 8 | #[test] 9 | #[should_panic(expected = "assertion failed: n <= buf.len()")] 10 | fn issue2310() { 11 | struct MyRead { 12 | first: bool, 13 | } 14 | 15 | impl MyRead { 16 | fn new() -> Self { 17 | Self { first: false } 18 | } 19 | } 20 | 21 | impl AsyncRead for MyRead { 22 | fn poll_read( 23 | mut self: Pin<&mut Self>, 24 | _cx: &mut Context<'_>, 25 | _buf: &mut [u8], 26 | ) -> Poll> { 27 | Poll::Ready(if !self.first { 28 | self.first = true; 29 | // First iteration: return more than the buffer size 30 | Ok(64) 31 | } else { 32 | // Second iteration: indicate that we are done 33 | Ok(0) 34 | }) 35 | } 36 | } 37 | 38 | struct VecWrapper { 39 | inner: Vec, 40 | } 41 | 42 | impl VecWrapper { 43 | fn new() -> Self { 44 | Self { inner: Vec::new() } 45 | } 46 | } 47 | 48 | impl Drop for VecWrapper { 49 | fn drop(&mut self) { 50 | // Observe uninitialized bytes 51 | println!("{:?}", &self.inner); 52 | // Overwrite heap contents 53 | for b in &mut self.inner { 54 | *b = 0x90; 55 | } 56 | } 57 | } 58 | 59 | block_on(async { 60 | let mut vec = VecWrapper::new(); 61 | let mut read = MyRead::new(); 62 | 63 | read.read_to_end(&mut vec.inner).await.unwrap(); 64 | }) 65 | } 66 | -------------------------------------------------------------------------------- /futures/tests/io_read_to_string.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{Future, FutureExt}; 3 | use futures::io::{AsyncReadExt, Cursor}; 4 | use futures::stream::{self, StreamExt, TryStreamExt}; 5 | use futures::task::Poll; 6 | use futures_test::io::AsyncReadTestExt; 7 | use futures_test::task::noop_context; 8 | 9 | #[test] 10 | fn read_to_string() { 11 | let mut c = Cursor::new(&b""[..]); 12 | let mut v = String::new(); 13 | assert_eq!(block_on(c.read_to_string(&mut v)).unwrap(), 0); 14 | assert_eq!(v, ""); 15 | 16 | let mut c = Cursor::new(&b"1"[..]); 17 | let mut v = String::new(); 18 | assert_eq!(block_on(c.read_to_string(&mut v)).unwrap(), 1); 19 | assert_eq!(v, "1"); 20 | 21 | let mut c = Cursor::new(&b"\xff"[..]); 22 | let mut v = String::new(); 23 | assert!(block_on(c.read_to_string(&mut v)).is_err()); 24 | } 25 | 26 | #[test] 27 | fn interleave_pending() { 28 | fn run(mut f: F) -> F::Output { 29 | let mut cx = noop_context(); 30 | loop { 31 | if let Poll::Ready(x) = f.poll_unpin(&mut cx) { 32 | return x; 33 | } 34 | } 35 | } 36 | let mut buf = stream::iter(vec![&b"12"[..], &b"33"[..], &b"3"[..]]) 37 | .map(Ok) 38 | .into_async_read() 39 | .interleave_pending(); 40 | 41 | let mut v = String::new(); 42 | assert_eq!(run(buf.read_to_string(&mut v)).unwrap(), 5); 43 | assert_eq!(v, "12333"); 44 | } 45 | -------------------------------------------------------------------------------- /futures/tests/io_read_until.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{Future, FutureExt}; 3 | use futures::io::{AsyncBufReadExt, Cursor}; 4 | use futures::stream::{self, StreamExt, TryStreamExt}; 5 | use futures::task::Poll; 6 | use futures_test::io::AsyncReadTestExt; 7 | use futures_test::task::noop_context; 8 | 9 | fn run(mut f: F) -> F::Output { 10 | let mut cx = noop_context(); 11 | loop { 12 | if let Poll::Ready(x) = f.poll_unpin(&mut cx) { 13 | return x; 14 | } 15 | } 16 | } 17 | 18 | #[test] 19 | fn read_until() { 20 | let mut buf = Cursor::new(b"12"); 21 | let mut v = Vec::new(); 22 | assert_eq!(block_on(buf.read_until(b'3', &mut v)).unwrap(), 2); 23 | assert_eq!(v, b"12"); 24 | 25 | let mut buf = Cursor::new(b"1233"); 26 | let mut v = Vec::new(); 27 | assert_eq!(block_on(buf.read_until(b'3', &mut v)).unwrap(), 3); 28 | assert_eq!(v, b"123"); 29 | v.truncate(0); 30 | assert_eq!(block_on(buf.read_until(b'3', &mut v)).unwrap(), 1); 31 | assert_eq!(v, b"3"); 32 | v.truncate(0); 33 | assert_eq!(block_on(buf.read_until(b'3', &mut v)).unwrap(), 0); 34 | assert_eq!(v, []); 35 | } 36 | 37 | #[test] 38 | fn maybe_pending() { 39 | let mut buf = b"12".interleave_pending(); 40 | let mut v = Vec::new(); 41 | assert_eq!(run(buf.read_until(b'3', &mut v)).unwrap(), 2); 42 | assert_eq!(v, b"12"); 43 | 44 | let mut buf = stream::iter(vec![&b"12"[..], &b"33"[..], &b"3"[..]]) 45 | .map(Ok) 46 | .into_async_read() 47 | .interleave_pending(); 48 | let mut v = Vec::new(); 49 | assert_eq!(run(buf.read_until(b'3', &mut v)).unwrap(), 3); 50 | assert_eq!(v, b"123"); 51 | v.clear(); 52 | assert_eq!(run(buf.read_until(b'3', &mut v)).unwrap(), 1); 53 | assert_eq!(v, b"3"); 54 | v.clear(); 55 | assert_eq!(run(buf.read_until(b'3', &mut v)).unwrap(), 1); 56 | assert_eq!(v, b"3"); 57 | v.clear(); 58 | assert_eq!(run(buf.read_until(b'3', &mut v)).unwrap(), 0); 59 | assert_eq!(v, []); 60 | } 61 | -------------------------------------------------------------------------------- /futures/tests/io_window.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::reversed_empty_ranges)] // This is intentional. 2 | 3 | use futures::io::Window; 4 | 5 | #[test] 6 | fn set() { 7 | let mut buffer = Window::new(&[1, 2, 3]); 8 | buffer.set(..3); 9 | assert_eq!(buffer.as_ref(), &[1, 2, 3]); 10 | buffer.set(3..3); 11 | assert_eq!(buffer.as_ref(), &[]); 12 | buffer.set(3..=2); // == 3..3 13 | assert_eq!(buffer.as_ref(), &[]); 14 | buffer.set(0..2); 15 | assert_eq!(buffer.as_ref(), &[1, 2]); 16 | } 17 | 18 | #[test] 19 | #[should_panic] 20 | fn set_panic_out_of_bounds() { 21 | let mut buffer = Window::new(&[1, 2, 3]); 22 | buffer.set(2..4); 23 | } 24 | 25 | #[test] 26 | #[should_panic] 27 | fn set_panic_start_is_greater_than_end() { 28 | let mut buffer = Window::new(&[1, 2, 3]); 29 | buffer.set(3..2); 30 | } 31 | -------------------------------------------------------------------------------- /futures/tests/macro-reexport/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "macro-reexport" 3 | version = "0.0.0" 4 | edition = "2018" 5 | publish = false 6 | 7 | [dependencies] 8 | futures04 = { path = "../..", package = "futures" } 9 | 10 | [lints] 11 | workspace = true 12 | -------------------------------------------------------------------------------- /futures/tests/macro-reexport/src/lib.rs: -------------------------------------------------------------------------------- 1 | // normal reexport 2 | pub use futures04::{join, select, select_biased, try_join}; 3 | 4 | // reexport + rename 5 | pub use futures04::{ 6 | join as join2, select as select2, select_biased as select_biased2, try_join as try_join2, 7 | }; 8 | -------------------------------------------------------------------------------- /futures/tests/macro-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "macro-tests" 3 | version = "0.0.0" 4 | edition = "2018" 5 | publish = false 6 | 7 | [dependencies] 8 | futures04 = { path = "../..", package = "futures" } 9 | macro-reexport = { path = "../macro-reexport" } 10 | 11 | [lints] 12 | workspace = true 13 | -------------------------------------------------------------------------------- /futures/tests/macro_comma_support.rs: -------------------------------------------------------------------------------- 1 | use futures::{ 2 | executor::block_on, 3 | future::{self, FutureExt}, 4 | join, ready, 5 | task::Poll, 6 | try_join, 7 | }; 8 | 9 | #[test] 10 | fn ready() { 11 | block_on(future::poll_fn(|_| { 12 | ready!(Poll::Ready(()),); 13 | Poll::Ready(()) 14 | })) 15 | } 16 | 17 | #[test] 18 | fn poll() { 19 | use futures::poll; 20 | 21 | block_on(async { 22 | let _ = poll!(async {}.boxed(),); 23 | }) 24 | } 25 | 26 | #[test] 27 | fn join() { 28 | block_on(async { 29 | let future1 = async { 1 }; 30 | let future2 = async { 2 }; 31 | join!(future1, future2,); 32 | }) 33 | } 34 | 35 | #[test] 36 | fn try_join() { 37 | block_on(async { 38 | let future1 = async { 1 }.never_error(); 39 | let future2 = async { 2 }.never_error(); 40 | try_join!(future1, future2,) 41 | }) 42 | .unwrap(); 43 | } 44 | -------------------------------------------------------------------------------- /futures/tests/no-std/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "no-std" 3 | version = "0.0.0" 4 | edition = "2018" 5 | publish = false 6 | 7 | [features] 8 | futures-core-alloc = ["futures-core/alloc"] 9 | futures-task-alloc = ["futures-task/alloc"] 10 | futures-channel-alloc = ["futures-channel/alloc"] 11 | futures-util-alloc = ["futures-util/alloc"] 12 | futures-util-async-await = ["futures-util/async-await"] 13 | futures-alloc = ["futures/alloc"] 14 | futures-async-await = ["futures/async-await"] 15 | 16 | [dependencies] 17 | futures-core = { path = "../../../futures-core", optional = true, default-features = false } 18 | futures-task = { path = "../../../futures-task", optional = true, default-features = false } 19 | futures-channel = { path = "../../../futures-channel", optional = true, default-features = false } 20 | futures-util = { path = "../../../futures-util", optional = true, default-features = false } 21 | futures = { path = "../..", optional = true, default-features = false } 22 | 23 | [lints] 24 | workspace = true 25 | -------------------------------------------------------------------------------- /futures/tests/no-std/build.rs: -------------------------------------------------------------------------------- 1 | use std::{env, process::Command}; 2 | 3 | fn main() { 4 | println!("cargo:rustc-check-cfg=cfg(nightly)"); 5 | if is_nightly() { 6 | println!("cargo:rustc-cfg=nightly"); 7 | } 8 | } 9 | 10 | fn is_nightly() -> bool { 11 | env::var_os("RUSTC") 12 | .and_then(|rustc| Command::new(rustc).arg("--version").output().ok()) 13 | .and_then(|output| String::from_utf8(output.stdout).ok()) 14 | .is_some_and(|version| version.contains("nightly") || version.contains("dev")) 15 | } 16 | -------------------------------------------------------------------------------- /futures/tests/no-std/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg(nightly)] 2 | #![no_std] 3 | #![allow(unused_imports)] 4 | 5 | #[cfg(feature = "futures-core-alloc")] 6 | #[cfg(target_has_atomic = "ptr")] 7 | pub use futures_core::task::__internal::AtomicWaker as _; 8 | 9 | #[cfg(feature = "futures-task-alloc")] 10 | #[cfg(target_has_atomic = "ptr")] 11 | pub use futures_task::ArcWake as _; 12 | 13 | #[cfg(feature = "futures-channel-alloc")] 14 | #[cfg(target_has_atomic = "ptr")] 15 | pub use futures_channel::oneshot as _; 16 | 17 | #[cfg(any(feature = "futures", feature = "futures-alloc"))] 18 | #[cfg(target_has_atomic = "ptr")] 19 | pub use futures::task::AtomicWaker as _; 20 | 21 | #[cfg(feature = "futures-alloc")] 22 | #[cfg(target_has_atomic = "ptr")] 23 | pub use futures::stream::FuturesOrdered as _; 24 | 25 | #[cfg(any(feature = "futures-util", feature = "futures-util-alloc"))] 26 | #[cfg(target_has_atomic = "ptr")] 27 | pub use futures_util::task::AtomicWaker as _; 28 | 29 | #[cfg(feature = "futures-util-alloc")] 30 | #[cfg(target_has_atomic = "ptr")] 31 | pub use futures_util::stream::FuturesOrdered as _; 32 | -------------------------------------------------------------------------------- /futures/tests/object_safety.rs: -------------------------------------------------------------------------------- 1 | fn assert_is_object_safe() {} 2 | 3 | #[test] 4 | fn future() { 5 | // `FutureExt`, `TryFutureExt` and `UnsafeFutureObj` are not object safe. 6 | use futures::future::{FusedFuture, Future, TryFuture}; 7 | 8 | assert_is_object_safe::>(); 9 | assert_is_object_safe::>(); 10 | assert_is_object_safe::>>(); 11 | } 12 | 13 | #[test] 14 | fn stream() { 15 | // `StreamExt` and `TryStreamExt` are not object safe. 16 | use futures::stream::{FusedStream, Stream, TryStream}; 17 | 18 | assert_is_object_safe::>(); 19 | assert_is_object_safe::>(); 20 | assert_is_object_safe::>>(); 21 | } 22 | 23 | #[test] 24 | fn sink() { 25 | // `SinkExt` is not object safe. 26 | use futures::sink::Sink; 27 | 28 | assert_is_object_safe::>(); 29 | } 30 | 31 | #[test] 32 | fn io() { 33 | // `AsyncReadExt`, `AsyncWriteExt`, `AsyncSeekExt` and `AsyncBufReadExt` are not object safe. 34 | use futures::io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite}; 35 | 36 | assert_is_object_safe::(); 37 | assert_is_object_safe::(); 38 | assert_is_object_safe::(); 39 | assert_is_object_safe::(); 40 | } 41 | 42 | #[test] 43 | fn task() { 44 | // `ArcWake`, `SpawnExt` and `LocalSpawnExt` are not object safe. 45 | use futures::task::{LocalSpawn, Spawn}; 46 | 47 | assert_is_object_safe::(); 48 | assert_is_object_safe::(); 49 | } 50 | -------------------------------------------------------------------------------- /futures/tests/recurse.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::{self, BoxFuture, FutureExt}; 3 | use std::sync::mpsc; 4 | use std::thread; 5 | 6 | #[test] 7 | fn lots() { 8 | #[cfg(not(futures_sanitizer))] 9 | const N: i32 = 1_000; 10 | #[cfg(futures_sanitizer)] // If N is many, asan reports stack-overflow: https://gist.github.com/taiki-e/099446d21cbec69d4acbacf7a9646136 11 | const N: i32 = 100; 12 | 13 | fn do_it(input: (i32, i32)) -> BoxFuture<'static, i32> { 14 | let (n, x) = input; 15 | if n == 0 { 16 | future::ready(x).boxed() 17 | } else { 18 | future::ready((n - 1, x + n)).then(do_it).boxed() 19 | } 20 | } 21 | 22 | let (tx, rx) = mpsc::channel(); 23 | thread::spawn(|| block_on(do_it((N, 0)).map(move |x| tx.send(x).unwrap()))); 24 | assert_eq!((0..=N).sum::(), rx.recv().unwrap()); 25 | } 26 | -------------------------------------------------------------------------------- /futures/tests/sink_fanout.rs: -------------------------------------------------------------------------------- 1 | use futures::channel::mpsc; 2 | use futures::executor::block_on; 3 | use futures::join; 4 | use futures::sink::SinkExt; 5 | use futures::stream::{self, StreamExt}; 6 | 7 | #[test] 8 | fn it_works() { 9 | let (tx1, rx1) = mpsc::channel(1); 10 | let (tx2, rx2) = mpsc::channel(2); 11 | let tx = tx1.fanout(tx2).sink_map_err(|_| ()); 12 | 13 | let src = stream::iter((0..10).map(Ok)); 14 | let fwd = src.forward(tx); 15 | 16 | let collect_fut1 = rx1.collect::>(); 17 | let collect_fut2 = rx2.collect::>(); 18 | let (_, vec1, vec2) = block_on(async move { join!(fwd, collect_fut1, collect_fut2) }); 19 | 20 | let expected = (0..10).map(Ok::<_, ()>).collect::>(); 21 | 22 | assert_eq!(vec1, expected); 23 | assert_eq!(vec2, expected); 24 | } 25 | -------------------------------------------------------------------------------- /futures/tests/stream_abortable.rs: -------------------------------------------------------------------------------- 1 | use futures::channel::mpsc; 2 | use futures::executor::block_on; 3 | use futures::stream::{abortable, Stream, StreamExt}; 4 | use futures::task::{Context, Poll}; 5 | use futures::SinkExt; 6 | use futures_test::task::new_count_waker; 7 | use std::pin::Pin; 8 | 9 | #[test] 10 | fn abortable_works() { 11 | let (_tx, a_rx) = mpsc::channel::<()>(1); 12 | let (mut abortable_rx, abort_handle) = abortable(a_rx); 13 | 14 | abort_handle.abort(); 15 | assert!(abortable_rx.is_aborted()); 16 | assert_eq!(None, block_on(abortable_rx.next())); 17 | } 18 | 19 | #[test] 20 | fn abortable_awakens() { 21 | let (_tx, a_rx) = mpsc::channel::<()>(1); 22 | let (mut abortable_rx, abort_handle) = abortable(a_rx); 23 | 24 | let (waker, counter) = new_count_waker(); 25 | let mut cx = Context::from_waker(&waker); 26 | 27 | assert_eq!(counter, 0); 28 | assert_eq!(Poll::Pending, Pin::new(&mut abortable_rx).poll_next(&mut cx)); 29 | assert_eq!(counter, 0); 30 | 31 | abort_handle.abort(); 32 | assert_eq!(counter, 1); 33 | assert!(abortable_rx.is_aborted()); 34 | assert_eq!(Poll::Ready(None), Pin::new(&mut abortable_rx).poll_next(&mut cx)); 35 | } 36 | 37 | #[test] 38 | fn abortable_resolves() { 39 | let (mut tx, a_rx) = mpsc::channel::<()>(1); 40 | let (mut abortable_rx, _abort_handle) = abortable(a_rx); 41 | 42 | block_on(tx.send(())).unwrap(); 43 | 44 | assert!(!abortable_rx.is_aborted()); 45 | assert_eq!(Some(()), block_on(abortable_rx.next())); 46 | } 47 | -------------------------------------------------------------------------------- /futures/tests/stream_catch_unwind.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on_stream; 2 | use futures::stream::{self, StreamExt}; 3 | 4 | #[test] 5 | fn panic_in_the_middle_of_the_stream() { 6 | let stream = stream::iter(vec![Some(10), None, Some(11)]); 7 | 8 | // panic on second element 9 | let stream_panicking = stream.map(|o| o.unwrap()); 10 | let mut iter = block_on_stream(stream_panicking.catch_unwind()); 11 | 12 | assert_eq!(10, iter.next().unwrap().ok().unwrap()); 13 | assert!(iter.next().unwrap().is_err()); 14 | assert!(iter.next().is_none()); 15 | } 16 | 17 | #[test] 18 | fn no_panic() { 19 | let stream = stream::iter(vec![10, 11, 12]); 20 | 21 | let mut iter = block_on_stream(stream.catch_unwind()); 22 | 23 | assert_eq!(10, iter.next().unwrap().ok().unwrap()); 24 | assert_eq!(11, iter.next().unwrap().ok().unwrap()); 25 | assert_eq!(12, iter.next().unwrap().ok().unwrap()); 26 | assert!(iter.next().is_none()); 27 | } 28 | -------------------------------------------------------------------------------- /futures/tests/stream_split.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::sink::{Sink, SinkExt}; 3 | use futures::stream::{self, Stream, StreamExt}; 4 | use futures::task::{Context, Poll}; 5 | use pin_project::pin_project; 6 | use std::pin::Pin; 7 | 8 | #[test] 9 | fn test_split() { 10 | #[pin_project] 11 | struct Join { 12 | #[pin] 13 | stream: T, 14 | #[pin] 15 | sink: U, 16 | } 17 | 18 | impl Stream for Join { 19 | type Item = T::Item; 20 | 21 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 22 | self.project().stream.poll_next(cx) 23 | } 24 | } 25 | 26 | impl, Item> Sink for Join { 27 | type Error = U::Error; 28 | 29 | fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 30 | self.project().sink.poll_ready(cx) 31 | } 32 | 33 | fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { 34 | self.project().sink.start_send(item) 35 | } 36 | 37 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 38 | self.project().sink.poll_flush(cx) 39 | } 40 | 41 | fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 42 | self.project().sink.poll_close(cx) 43 | } 44 | } 45 | 46 | let mut dest: Vec = Vec::new(); 47 | { 48 | let join = Join { stream: stream::iter(vec![10, 20, 30]), sink: &mut dest }; 49 | 50 | let (sink, stream) = join.split(); 51 | let join = sink.reunite(stream).expect("test_split: reunite error"); 52 | let (mut sink, stream) = join.split(); 53 | let mut stream = stream.map(Ok); 54 | block_on(sink.send_all(&mut stream)).unwrap(); 55 | } 56 | assert_eq!(dest, vec![10, 20, 30]); 57 | } 58 | -------------------------------------------------------------------------------- /futures/tests/stream_unfold.rs: -------------------------------------------------------------------------------- 1 | use futures::future; 2 | use futures::stream; 3 | use futures_test::future::FutureTestExt; 4 | use futures_test::{assert_stream_done, assert_stream_next, assert_stream_pending}; 5 | 6 | #[test] 7 | fn unfold1() { 8 | let mut stream = stream::unfold(0, |state| { 9 | if state <= 2 { 10 | future::ready(Some((state * 2, state + 1))).pending_once() 11 | } else { 12 | future::ready(None).pending_once() 13 | } 14 | }); 15 | 16 | // Creates the future with the closure 17 | // Not ready (delayed future) 18 | assert_stream_pending!(stream); 19 | // Future is ready, yields the item 20 | assert_stream_next!(stream, 0); 21 | 22 | // Repeat 23 | assert_stream_pending!(stream); 24 | assert_stream_next!(stream, 2); 25 | 26 | assert_stream_pending!(stream); 27 | assert_stream_next!(stream, 4); 28 | 29 | // No more items 30 | assert_stream_pending!(stream); 31 | assert_stream_done!(stream); 32 | } 33 | -------------------------------------------------------------------------------- /futures/tests/task_arc_wake.rs: -------------------------------------------------------------------------------- 1 | use futures::task::{self, ArcWake, Waker}; 2 | use std::panic; 3 | use std::sync::{Arc, Mutex}; 4 | 5 | struct CountingWaker { 6 | nr_wake: Mutex, 7 | } 8 | 9 | impl CountingWaker { 10 | fn new() -> Self { 11 | Self { nr_wake: Mutex::new(0) } 12 | } 13 | 14 | fn wakes(&self) -> i32 { 15 | *self.nr_wake.lock().unwrap() 16 | } 17 | } 18 | 19 | impl ArcWake for CountingWaker { 20 | fn wake_by_ref(arc_self: &Arc) { 21 | let mut lock = arc_self.nr_wake.lock().unwrap(); 22 | *lock += 1; 23 | } 24 | } 25 | 26 | #[test] 27 | fn create_from_arc() { 28 | let some_w = Arc::new(CountingWaker::new()); 29 | 30 | let w1: Waker = task::waker(some_w.clone()); 31 | assert_eq!(2, Arc::strong_count(&some_w)); 32 | w1.wake_by_ref(); 33 | assert_eq!(1, some_w.wakes()); 34 | 35 | let w2 = w1.clone(); 36 | assert_eq!(3, Arc::strong_count(&some_w)); 37 | 38 | w2.wake_by_ref(); 39 | assert_eq!(2, some_w.wakes()); 40 | 41 | drop(w2); 42 | assert_eq!(2, Arc::strong_count(&some_w)); 43 | drop(w1); 44 | assert_eq!(1, Arc::strong_count(&some_w)); 45 | } 46 | 47 | #[test] 48 | fn ref_wake_same() { 49 | let some_w = Arc::new(CountingWaker::new()); 50 | 51 | let w1: Waker = task::waker(some_w.clone()); 52 | let w2 = task::waker_ref(&some_w); 53 | let w3 = w2.clone(); 54 | 55 | assert!(w1.will_wake(&w2)); 56 | assert!(w2.will_wake(&w3)); 57 | } 58 | 59 | #[test] 60 | fn proper_refcount_on_wake_panic() { 61 | struct PanicWaker; 62 | 63 | impl ArcWake for PanicWaker { 64 | fn wake_by_ref(_arc_self: &Arc) { 65 | panic!("WAKE UP"); 66 | } 67 | } 68 | 69 | let some_w = Arc::new(PanicWaker); 70 | 71 | let w1: Waker = task::waker(some_w.clone()); 72 | assert_eq!( 73 | "WAKE UP", 74 | *panic::catch_unwind(|| w1.wake_by_ref()).unwrap_err().downcast::<&str>().unwrap() 75 | ); 76 | assert_eq!(2, Arc::strong_count(&some_w)); // some_w + w1 77 | drop(w1); 78 | assert_eq!(1, Arc::strong_count(&some_w)); // some_w 79 | } 80 | -------------------------------------------------------------------------------- /futures/tests/task_atomic_waker.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::future::poll_fn; 3 | use futures::task::{AtomicWaker, Poll}; 4 | use std::sync::atomic::AtomicUsize; 5 | use std::sync::atomic::Ordering; 6 | use std::sync::Arc; 7 | use std::thread; 8 | 9 | #[test] 10 | fn basic() { 11 | let atomic_waker = Arc::new(AtomicWaker::new()); 12 | let atomic_waker_copy = atomic_waker.clone(); 13 | 14 | let returned_pending = Arc::new(AtomicUsize::new(0)); 15 | let returned_pending_copy = returned_pending.clone(); 16 | 17 | let woken = Arc::new(AtomicUsize::new(0)); 18 | let woken_copy = woken.clone(); 19 | 20 | let t = thread::spawn(move || { 21 | let mut pending_count = 0; 22 | 23 | block_on(poll_fn(move |cx| { 24 | if woken_copy.load(Ordering::Relaxed) == 1 { 25 | Poll::Ready(()) 26 | } else { 27 | // Assert we return pending exactly once 28 | assert_eq!(0, pending_count); 29 | pending_count += 1; 30 | atomic_waker_copy.register(cx.waker()); 31 | 32 | returned_pending_copy.store(1, Ordering::Relaxed); 33 | 34 | Poll::Pending 35 | } 36 | })) 37 | }); 38 | 39 | while returned_pending.load(Ordering::Relaxed) == 0 {} 40 | 41 | // give spawned thread some time to sleep in `block_on` 42 | thread::yield_now(); 43 | 44 | woken.store(1, Ordering::Relaxed); 45 | atomic_waker.wake(); 46 | 47 | t.join().unwrap(); 48 | } 49 | -------------------------------------------------------------------------------- /futures/tests/test_macro.rs: -------------------------------------------------------------------------------- 1 | #[futures_test::test] 2 | async fn it_works() { 3 | let fut = async { true }; 4 | assert!(fut.await); 5 | 6 | let fut = async { false }; 7 | assert!(!fut.await); 8 | } 9 | 10 | #[should_panic] 11 | #[futures_test::test] 12 | async fn it_is_being_run() { 13 | let fut = async { false }; 14 | assert!(fut.await); 15 | } 16 | 17 | #[futures_test::test] 18 | async fn return_ty() -> Result<(), ()> { 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /futures/tests/try_join.rs: -------------------------------------------------------------------------------- 1 | #![deny(unreachable_code)] 2 | 3 | use futures::{executor::block_on, try_join}; 4 | 5 | // TODO: This abuses https://github.com/rust-lang/rust/issues/58733 in order to 6 | // test behavior of the `try_join!` macro with the never type before it is 7 | // stabilized. Once `!` is again stabilized this can be removed and replaced 8 | // with direct use of `!` below where `Never` is used. 9 | trait MyTrait { 10 | type Output; 11 | } 12 | impl MyTrait for fn() -> T { 13 | type Output = T; 14 | } 15 | type Never = ! as MyTrait>::Output; 16 | 17 | #[test] 18 | fn try_join_never_error() { 19 | block_on(async { 20 | let future1 = async { Ok::<(), Never>(()) }; 21 | let future2 = async { Ok::<(), Never>(()) }; 22 | try_join!(future1, future2) 23 | }) 24 | .unwrap(); 25 | } 26 | 27 | #[test] 28 | fn try_join_never_ok() { 29 | block_on(async { 30 | let future1 = async { Err::(()) }; 31 | let future2 = async { Err::(()) }; 32 | try_join!(future1, future2) 33 | }) 34 | .unwrap_err(); 35 | } 36 | -------------------------------------------------------------------------------- /triagebot.toml: -------------------------------------------------------------------------------- 1 | [relabel] 2 | allow-unauthenticated = [ 3 | "S-*", 4 | ] 5 | 6 | [review-submitted] 7 | # This label is added when a "request changes" review is submitted. 8 | reviewed_label = "S-waiting-on-author" 9 | # These labels are removed when a "request changes" review is submitted. 10 | review_labels = ["S-waiting-on-review"] 11 | 12 | [review-requested] 13 | # Those labels are removed when PR author requests a review from an assignee 14 | remove_labels = ["S-waiting-on-author"] 15 | # Those labels are added when PR author requests a review from an assignee 16 | add_labels = ["S-waiting-on-review"] 17 | 18 | [assign] 19 | warn_non_default_branch = true 20 | 21 | [autolabel."A-channel"] 22 | trigger_files = ["futures-channel/src"] 23 | 24 | [autolabel."A-compat"] 25 | trigger_files = ["futures-util/src/compat"] 26 | 27 | [autolabel."A-executor"] 28 | trigger_files = ["futures-executor/src"] 29 | 30 | [autolabel."A-future"] 31 | trigger_files = ["futures-core/src/future.rs", "futures-util/src/future"] 32 | 33 | [autolabel."A-io"] 34 | trigger_files = ["futures-io/src", "futures-util/src/io"] 35 | 36 | [autolabel."A-lock"] 37 | trigger_files = ["futures-util/src/lock"] 38 | 39 | [autolabel."A-macro"] 40 | trigger_files = ["futures-macro/src", "futures-util/src/async_await"] 41 | 42 | [autolabel."A-sink"] 43 | trigger_files = ["futures-sink/src", "futures-util/src/sink"] 44 | 45 | [autolabel."A-stream"] 46 | trigger_files = ["futures-core/src/stream.rs", "futures-util/src/stream"] 47 | 48 | [autolabel."A-task"] 49 | trigger_files = ["futures-core/src/task", "futures-task/src", "futures-util/src/task"] 50 | 51 | [autolabel."S-waiting-on-review"] 52 | new_pr = true 53 | --------------------------------------------------------------------------------