├── .github ├── CONTRIBUTING.md └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches ├── mutex.rs ├── task.rs └── task_local.rs ├── ci └── install-mdbook.sh ├── docs ├── .gitignore ├── book.toml └── src │ ├── SUMMARY.md │ ├── concepts.md │ ├── concepts │ ├── async-read-write.md │ ├── data.csv │ ├── futures.md │ ├── streams.md │ └── tasks.md │ ├── glossary.md │ ├── images │ ├── async_1.svg │ ├── async_2.svg │ ├── horizontal_color.svg │ ├── icon_color.svg │ └── vertical_color.svg │ ├── introduction.md │ ├── overview │ ├── async-std.md │ └── stability-guarantees.md │ ├── patterns.md │ ├── patterns │ ├── accept-loop.md │ ├── accepting-concurrent-requests.md │ ├── async-read-write.md │ ├── background-tasks.md │ ├── fork-join.md │ ├── proper-shutdown.md │ ├── small-patterns.md │ └── testing.md │ ├── security │ ├── index.md │ └── policy.md │ └── tutorial │ ├── accept_loop.md │ ├── all_together.md │ ├── clean_shutdown.md │ ├── connecting_readers_and_writers.md │ ├── handling_disconnection.md │ ├── implementing_a_client.md │ ├── index.md │ ├── receiving_messages.md │ ├── sending_messages.md │ └── specification.md ├── examples ├── README.md ├── a-chat │ ├── client.rs │ ├── main.rs │ └── server.rs ├── hello-world.rs ├── line-count.rs ├── list-dir.rs ├── logging.rs ├── print-file.rs ├── socket-timeouts.rs ├── stdin-echo.rs ├── stdin-timeout.rs ├── surf-web.rs ├── task-local.rs ├── task-name.rs ├── tcp-client.rs ├── tcp-echo.rs ├── tcp-ipv4-and-6-echo.rs ├── udp-client.rs └── udp-echo.rs ├── src ├── channel.rs ├── collections │ ├── binary_heap │ │ ├── extend.rs │ │ ├── from_stream.rs │ │ └── mod.rs │ ├── btree_map │ │ ├── extend.rs │ │ ├── from_stream.rs │ │ └── mod.rs │ ├── btree_set │ │ ├── extend.rs │ │ ├── from_stream.rs │ │ └── mod.rs │ ├── hash_map │ │ ├── extend.rs │ │ ├── from_stream.rs │ │ └── mod.rs │ ├── hash_set │ │ ├── extend.rs │ │ ├── from_stream.rs │ │ └── mod.rs │ ├── linked_list │ │ ├── extend.rs │ │ ├── from_stream.rs │ │ └── mod.rs │ ├── mod.rs │ └── vec_deque │ │ ├── extend.rs │ │ ├── from_stream.rs │ │ └── mod.rs ├── fs │ ├── canonicalize.rs │ ├── copy.rs │ ├── create_dir.rs │ ├── create_dir_all.rs │ ├── dir_builder.rs │ ├── dir_entry.rs │ ├── file.rs │ ├── file_type.rs │ ├── hard_link.rs │ ├── metadata.rs │ ├── mod.rs │ ├── open_options.rs │ ├── permissions.rs │ ├── read.rs │ ├── read_dir.rs │ ├── read_link.rs │ ├── read_to_string.rs │ ├── remove_dir.rs │ ├── remove_dir_all.rs │ ├── remove_file.rs │ ├── rename.rs │ ├── set_permissions.rs │ ├── symlink_metadata.rs │ └── write.rs ├── future │ ├── future │ │ ├── delay.rs │ │ ├── flatten.rs │ │ ├── join.rs │ │ ├── mod.rs │ │ ├── race.rs │ │ ├── try_join.rs │ │ └── try_race.rs │ ├── into_future.rs │ ├── maybe_done.rs │ ├── mod.rs │ ├── pending.rs │ ├── poll_fn.rs │ ├── ready.rs │ └── timeout.rs ├── io │ ├── buf_read │ │ ├── lines.rs │ │ ├── mod.rs │ │ ├── read_line.rs │ │ ├── read_until.rs │ │ └── split.rs │ ├── buf_reader.rs │ ├── buf_writer.rs │ ├── copy.rs │ ├── cursor.rs │ ├── empty.rs │ ├── mod.rs │ ├── prelude.rs │ ├── read │ │ ├── bytes.rs │ │ ├── chain.rs │ │ ├── mod.rs │ │ ├── read.rs │ │ ├── read_exact.rs │ │ ├── read_to_end.rs │ │ ├── read_to_string.rs │ │ ├── read_vectored.rs │ │ └── take.rs │ ├── repeat.rs │ ├── seek │ │ ├── mod.rs │ │ └── seek.rs │ ├── sink.rs │ ├── stderr.rs │ ├── stdin.rs │ ├── stdio.rs │ ├── stdout.rs │ ├── timeout.rs │ ├── utils.rs │ └── write │ │ ├── flush.rs │ │ ├── mod.rs │ │ ├── write.rs │ │ ├── write_all.rs │ │ ├── write_fmt.rs │ │ └── write_vectored.rs ├── lib.rs ├── macros.rs ├── net │ ├── addr.rs │ ├── mod.rs │ ├── tcp │ │ ├── listener.rs │ │ ├── mod.rs │ │ └── stream.rs │ └── udp │ │ └── mod.rs ├── option │ ├── from_stream.rs │ ├── mod.rs │ ├── product.rs │ └── sum.rs ├── os │ ├── mod.rs │ ├── unix │ │ ├── fs.rs │ │ ├── io.rs │ │ ├── mod.rs │ │ └── net │ │ │ ├── datagram.rs │ │ │ ├── listener.rs │ │ │ ├── mod.rs │ │ │ └── stream.rs │ └── windows │ │ ├── fs.rs │ │ ├── io.rs │ │ └── mod.rs ├── path │ ├── ancestors.rs │ ├── components.rs │ ├── iter.rs │ ├── mod.rs │ ├── path.rs │ └── pathbuf.rs ├── pin │ └── mod.rs ├── prelude.rs ├── process.rs ├── result │ ├── from_stream.rs │ ├── mod.rs │ ├── product.rs │ └── sum.rs ├── rt │ └── mod.rs ├── stream │ ├── double_ended_stream │ │ ├── mod.rs │ │ ├── next_back.rs │ │ ├── nth_back.rs │ │ ├── rfind.rs │ │ ├── rfold.rs │ │ └── try_rfold.rs │ ├── empty.rs │ ├── exact_size_stream.rs │ ├── extend.rs │ ├── from_fn.rs │ ├── from_iter.rs │ ├── from_stream.rs │ ├── fused_stream.rs │ ├── interval.rs │ ├── into_stream.rs │ ├── mod.rs │ ├── once.rs │ ├── pending.rs │ ├── product.rs │ ├── repeat.rs │ ├── repeat_with.rs │ ├── stream │ │ ├── all.rs │ │ ├── any.rs │ │ ├── chain.rs │ │ ├── cloned.rs │ │ ├── cmp.rs │ │ ├── copied.rs │ │ ├── count.rs │ │ ├── cycle.rs │ │ ├── delay.rs │ │ ├── enumerate.rs │ │ ├── eq.rs │ │ ├── filter.rs │ │ ├── filter_map.rs │ │ ├── find.rs │ │ ├── find_map.rs │ │ ├── flat_map.rs │ │ ├── flatten.rs │ │ ├── fold.rs │ │ ├── for_each.rs │ │ ├── fuse.rs │ │ ├── ge.rs │ │ ├── gt.rs │ │ ├── inspect.rs │ │ ├── last.rs │ │ ├── le.rs │ │ ├── lt.rs │ │ ├── map.rs │ │ ├── max.rs │ │ ├── max_by.rs │ │ ├── max_by_key.rs │ │ ├── merge.rs │ │ ├── min.rs │ │ ├── min_by.rs │ │ ├── min_by_key.rs │ │ ├── mod.rs │ │ ├── ne.rs │ │ ├── next.rs │ │ ├── nth.rs │ │ ├── partial_cmp.rs │ │ ├── partition.rs │ │ ├── position.rs │ │ ├── scan.rs │ │ ├── skip.rs │ │ ├── skip_while.rs │ │ ├── step_by.rs │ │ ├── take.rs │ │ ├── take_while.rs │ │ ├── throttle.rs │ │ ├── timeout.rs │ │ ├── try_fold.rs │ │ ├── try_for_each.rs │ │ ├── unzip.rs │ │ └── zip.rs │ ├── successors.rs │ └── sum.rs ├── string │ ├── extend.rs │ ├── from_stream.rs │ └── mod.rs ├── sync │ ├── condvar.rs │ ├── mod.rs │ └── waker_set.rs ├── task │ ├── block_on.rs │ ├── builder.rs │ ├── current.rs │ ├── join_handle.rs │ ├── mod.rs │ ├── ready.rs │ ├── sleep.rs │ ├── spawn.rs │ ├── spawn_blocking.rs │ ├── spawn_local.rs │ ├── task.rs │ ├── task_id.rs │ ├── task_local.rs │ ├── task_locals_wrapper.rs │ └── yield_now.rs ├── unit │ ├── extend.rs │ ├── from_stream.rs │ └── mod.rs ├── utils.rs └── vec │ ├── extend.rs │ ├── from_stream.rs │ └── mod.rs └── tests ├── addr.rs ├── block_on.rs ├── buf_writer.rs ├── channel.rs ├── collect.rs ├── condvar.rs ├── io_copy.rs ├── io_timeout.rs ├── mutex.rs ├── rwlock.rs ├── stream.rs ├── task_local.rs ├── tcp.rs ├── timeout.rs ├── udp.rs ├── uds.rs └── verbose_errors.rs /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Our contribution policy can be found at [async.rs/contribute][policy]. 2 | 3 | [policy]: https://async.rs/contribute/ 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /benches/mutex.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use async_std::sync::{Arc, Mutex}; 6 | use async_std::task; 7 | use test::Bencher; 8 | 9 | #[bench] 10 | fn create(b: &mut Bencher) { 11 | b.iter(|| Mutex::new(())); 12 | } 13 | 14 | #[bench] 15 | fn contention(b: &mut Bencher) { 16 | b.iter(|| task::block_on(run(10, 1000))); 17 | } 18 | 19 | #[bench] 20 | fn no_contention(b: &mut Bencher) { 21 | b.iter(|| task::block_on(run(1, 10000))); 22 | } 23 | 24 | async fn run(task: usize, iter: usize) { 25 | let m = Arc::new(Mutex::new(())); 26 | let mut tasks = Vec::new(); 27 | 28 | for _ in 0..task { 29 | let m = m.clone(); 30 | tasks.push(task::spawn(async move { 31 | for _ in 0..iter { 32 | let _ = m.lock().await; 33 | } 34 | })); 35 | } 36 | 37 | for t in tasks { 38 | t.await; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /benches/task.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use async_std::task; 6 | use test::Bencher; 7 | 8 | #[bench] 9 | fn block_on(b: &mut Bencher) { 10 | b.iter(|| task::block_on(async {})); 11 | } 12 | -------------------------------------------------------------------------------- /benches/task_local.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use async_std::task; 6 | use async_std::task_local; 7 | use test::{black_box, Bencher}; 8 | 9 | #[bench] 10 | fn get(b: &mut Bencher) { 11 | task_local! { 12 | static VAL: u64 = 1; 13 | } 14 | 15 | let mut sum = 0; 16 | task::block_on(async { 17 | b.iter(|| VAL.with(|v| sum += v)); 18 | }); 19 | black_box(sum); 20 | } 21 | -------------------------------------------------------------------------------- /ci/install-mdbook.sh: -------------------------------------------------------------------------------- 1 | set -euxo pipefail 2 | 3 | # Based on the Rust-Embedded WG's book CI 4 | # https://github.com/rust-embedded/book/blob/HEAD/ci/install.sh 5 | 6 | main() { 7 | # Note - this will only accept releases tagged with v0.3.x 8 | local tag=$(git ls-remote --tags --refs --exit-code \ 9 | https://github.com/rust-lang-nursery/mdbook \ 10 | | cut -d/ -f3 \ 11 | | grep -E '^v0\.3\.[0-9]+$' \ 12 | | sort --version-sort \ 13 | | tail -n1) 14 | 15 | curl -LSfs https://japaric.github.io/trust/install.sh | \ 16 | sh -s -- --git rust-lang-nursery/mdbook --tag $tag 17 | } 18 | 19 | main 20 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | -------------------------------------------------------------------------------- /docs/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["The async-std maintainers"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "Async programming in Rust with async-std" 7 | 8 | [build] 9 | create-missing = false 10 | 11 | [output.html] 12 | git-repository-url = "https://github.com/async-rs/async-std" 13 | git-repository-icon = "fa-github" 14 | -------------------------------------------------------------------------------- /docs/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Introduction](./introduction.md) 4 | - [Welcome to `async-std`!](./overview/async-std.md) 5 | - [Stability guarantees](./overview/stability-guarantees.md) 6 | - [Async concepts using async-std](./concepts.md) 7 | - [Futures](./concepts/futures.md) 8 | - [Tasks](./concepts/tasks.md) 9 | - [Async read/write](./concepts/async-read-write.md) 10 | - [Streams and Channels](./concepts/streams.md) 11 | - [Tutorial: Implementing a chat](./tutorial/index.md) 12 | - [Specification and Getting started](./tutorial/specification.md) 13 | - [Writing an Accept Loop](./tutorial/accept_loop.md) 14 | - [Receiving Messages](./tutorial/receiving_messages.md) 15 | - [Sending Messages](./tutorial/sending_messages.md) 16 | - [Connecting Readers and Writers](./tutorial/connecting_readers_and_writers.md) 17 | - [All Together](./tutorial/all_together.md) 18 | - [Clean Shutdown](./tutorial/clean_shutdown.md) 19 | - [Handling Disconnection](./tutorial/handling_disconnection.md) 20 | - [Implementing a Client](./tutorial/implementing_a_client.md) 21 | - [Async Patterns](./patterns.md) 22 | - [TODO: Collected Small Patterns](./patterns/small-patterns.md) 23 | - [Production-Ready Accept Loop](./patterns/accept-loop.md) 24 | - [Security practices](./security/index.md) 25 | - [Security Disclosures and Policy](./security/policy.md) 26 | - [Glossary](./glossary.md) 27 | -------------------------------------------------------------------------------- /docs/src/concepts.md: -------------------------------------------------------------------------------- 1 | # Async concepts using async-std 2 | 3 | [Rust Futures][futures] have the reputation of being hard. We don't think this is the case. They are, in our opinion, one of the easiest concurrency concepts around and have an intuitive explanation. 4 | 5 | However, there are good reasons for that perception. Futures have three concepts at their base that seem to be a constant source of confusion: deferred computation, asynchronicity and independence of execution strategy. 6 | 7 | These concepts are not hard, but something many people are not used to. This base confusion is amplified by many implementations oriented on details. Most explanations of these implementations also target advanced users, and can be hard for beginners. We try to provide both easy-to-understand primitives and approachable overviews of the concepts. 8 | 9 | Futures are a concept that abstracts over how code is run. By themselves, they do nothing. This is a weird concept in an imperative language, where usually one thing happens after the other - right now. 10 | 11 | So how do Futures run? You decide! Futures do nothing without the piece of code _executing_ them. This part is called an _executor_. An _executor_ decides _when_ and _how_ to execute your futures. The `async-std::task` module provides you with an interface to such an executor. 12 | 13 | Let's start with a little bit of motivation, though. 14 | 15 | [futures]: https://en.wikipedia.org/wiki/Futures_and_promises 16 | -------------------------------------------------------------------------------- /docs/src/concepts/async-read-write.md: -------------------------------------------------------------------------------- 1 | # TODO: Async read/write 2 | -------------------------------------------------------------------------------- /docs/src/concepts/data.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/async-rs/async-std/96f564672a8588ac0516e86580c249009ad3e94f/docs/src/concepts/data.csv -------------------------------------------------------------------------------- /docs/src/concepts/streams.md: -------------------------------------------------------------------------------- 1 | # TODO: Streams 2 | -------------------------------------------------------------------------------- /docs/src/glossary.md: -------------------------------------------------------------------------------- 1 | # Glossary 2 | 3 | ### blocking 4 | 5 | "blocked" generally refers to conditions that keep a task from doing its work. For example, it might need data to be sent by a client before continuing. When tasks become blocked, usually, other tasks are scheduled. 6 | 7 | Sometimes you hear that you should never call "blocking functions" in an async context. What this refers to is functions that block the current thread and do not yield control back. This keeps the executor from using this thread to schedule another task. 8 | -------------------------------------------------------------------------------- /docs/src/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ![async-std logo](./images/horizontal_color.svg) 4 | 5 | This book serves as high-level documentation for `async-std` and a way of learning async programming in Rust through it. As such, it focuses on the `async-std` API and the task model it gives you. 6 | 7 | Please note that the Rust project provides its own book on asynchronous programming, called ["Asynchronous Programming in Rust"][async-book], which we highly recommend reading along with this book, as it provides a different, wider view on the topic. 8 | 9 | [async-book]: https://rust-lang.github.io/async-book/ 10 | -------------------------------------------------------------------------------- /docs/src/overview/async-std.md: -------------------------------------------------------------------------------- 1 | # Welcome to `async-std` 2 | 3 | `async-std`, along with its [supporting libraries][organization], is a library making your life in async programming easier. It provides fundamental implementations for downstream libraries and applications alike. The name reflects the approach of this library: it is as closely modeled to the Rust main standard library as possible, replacing all components by async counterparts. 4 | 5 | `async-std` provides an interface to all important primitives: filesystem operations, network operations and concurrency basics like timers. It also exposes a `task` in a model similar to the `thread` module found in the Rust standard lib. But it does not only include I/O primitives, but also `async/await` compatible versions of primitives like `Mutex`. 6 | 7 | [organization]: https://github.com/async-rs 8 | -------------------------------------------------------------------------------- /docs/src/patterns.md: -------------------------------------------------------------------------------- 1 | # Patterns 2 | 3 | This section documents small, useful patterns. 4 | 5 | It is intended to be read at a glance, allowing you to get back when you have a problem. -------------------------------------------------------------------------------- /docs/src/patterns/accepting-concurrent-requests.md: -------------------------------------------------------------------------------- 1 | # Accepting requests 2 | -------------------------------------------------------------------------------- /docs/src/patterns/async-read-write.md: -------------------------------------------------------------------------------- 1 | # Async read/write 2 | -------------------------------------------------------------------------------- /docs/src/patterns/background-tasks.md: -------------------------------------------------------------------------------- 1 | # Background Tasks 2 | -------------------------------------------------------------------------------- /docs/src/patterns/fork-join.md: -------------------------------------------------------------------------------- 1 | # Fork/Join 2 | -------------------------------------------------------------------------------- /docs/src/patterns/proper-shutdown.md: -------------------------------------------------------------------------------- 1 | # Proper Shutdown 2 | -------------------------------------------------------------------------------- /docs/src/patterns/small-patterns.md: -------------------------------------------------------------------------------- 1 | # Small Patterns 2 | 3 | A collection of small, useful patterns. 4 | 5 | ## Splitting streams 6 | 7 | `async-std` doesn't provide a `split()` method on `io` handles. Instead, splitting a stream into a read and write half can be done like this: 8 | 9 | ```rust,edition2018 10 | # extern crate async_std; 11 | use async_std::{io, net::TcpStream}; 12 | async fn echo(stream: TcpStream) { 13 | let (reader, writer) = &mut (&stream, &stream); 14 | io::copy(reader, writer).await; 15 | } 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/src/patterns/testing.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | -------------------------------------------------------------------------------- /docs/src/security/index.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | Writing a highly performant async core library is a task involving some instances of unsafe code. 4 | 5 | We take great care in vetting all unsafe code included in `async-std` and do follow generally accepted practices. 6 | 7 | In the case that you find a security-related bug in our library, please get in touch with our [security contact][security-policy]. 8 | 9 | Patches improving the resilience of the library or the testing setup are happily accepted on our [github org][github]. 10 | 11 | [security-policy]: /security/policy 12 | [github]: https://github.com/async-rs 13 | -------------------------------------------------------------------------------- /docs/src/tutorial/index.md: -------------------------------------------------------------------------------- 1 | # Tutorial: Writing a chat 2 | 3 | Nothing is simpler than creating a chat server, right? 4 | Not quite, chat servers expose you to all the fun of asynchronous programming: 5 | 6 | How will the server handle clients connecting concurrently? 7 | 8 | How will it handle them disconnecting? 9 | 10 | How will it distribute the messages? 11 | 12 | This tutorial explains how to write a chat server in `async-std`. 13 | 14 | You can also find the tutorial in [our repository](https://github.com/async-rs/async-std/blob/HEAD/examples/a-chat). 15 | -------------------------------------------------------------------------------- /docs/src/tutorial/specification.md: -------------------------------------------------------------------------------- 1 | # Specification and Getting Started 2 | 3 | ## Specification 4 | 5 | The chat uses a simple text protocol over TCP. 6 | The protocol consists of utf-8 messages, separated by `\n`. 7 | 8 | The client connects to the server and sends login as a first line. 9 | After that, the client can send messages to other clients using the following syntax: 10 | 11 | ```text 12 | login1, login2, ... loginN: message 13 | ``` 14 | 15 | Each of the specified clients then receives a `from login: message` message. 16 | 17 | A possible session might look like this 18 | 19 | ```text 20 | On Alice's computer: | On Bob's computer: 21 | 22 | > alice | > bob 23 | > bob: hello < from alice: hello 24 | | > alice, bob: hi! 25 | < from bob: hi! 26 | < from bob: hi! | 27 | ``` 28 | 29 | The main challenge for the chat server is keeping track of many concurrent connections. 30 | The main challenge for the chat client is managing concurrent outgoing messages, incoming messages and user's typing. 31 | 32 | ## Getting Started 33 | 34 | Let's create a new Cargo project: 35 | 36 | ```bash 37 | $ cargo new a-chat 38 | $ cd a-chat 39 | ``` 40 | 41 | Add the following lines to `Cargo.toml`: 42 | 43 | ```toml 44 | [dependencies] 45 | futures = "0.3.0" 46 | async-std = "1" 47 | ``` 48 | -------------------------------------------------------------------------------- /examples/a-chat/client.rs: -------------------------------------------------------------------------------- 1 | use futures::select; 2 | use futures::FutureExt; 3 | 4 | use async_std::{ 5 | io::{stdin, BufReader}, 6 | net::{TcpStream, ToSocketAddrs}, 7 | prelude::*, 8 | task, 9 | }; 10 | 11 | type Result = std::result::Result>; 12 | 13 | pub(crate) fn main() -> Result<()> { 14 | task::block_on(try_main("127.0.0.1:8080")) 15 | } 16 | 17 | async fn try_main(addr: impl ToSocketAddrs) -> Result<()> { 18 | let stream = TcpStream::connect(addr).await?; 19 | let (reader, mut writer) = (&stream, &stream); 20 | let reader = BufReader::new(reader); 21 | let mut lines_from_server = futures::StreamExt::fuse(reader.lines()); 22 | 23 | let stdin = BufReader::new(stdin()); 24 | let mut lines_from_stdin = futures::StreamExt::fuse(stdin.lines()); 25 | loop { 26 | select! { 27 | line = lines_from_server.next().fuse() => match line { 28 | Some(line) => { 29 | let line = line?; 30 | println!("{}", line); 31 | }, 32 | None => break, 33 | }, 34 | line = lines_from_stdin.next().fuse() => match line { 35 | Some(line) => { 36 | let line = line?; 37 | writer.write_all(line.as_bytes()).await?; 38 | writer.write_all(b"\n").await?; 39 | } 40 | None => break, 41 | } 42 | } 43 | } 44 | Ok(()) 45 | } 46 | -------------------------------------------------------------------------------- /examples/a-chat/main.rs: -------------------------------------------------------------------------------- 1 | mod client; 2 | mod server; 3 | 4 | type Result = std::result::Result>; 5 | 6 | fn main() -> Result<()> { 7 | let mut args = std::env::args(); 8 | match (args.nth(1).as_ref().map(String::as_str), args.next()) { 9 | (Some("client"), None) => client::main(), 10 | (Some("server"), None) => server::main(), 11 | _ => Err("Usage: a-chat [client|server]".into()), 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/hello-world.rs: -------------------------------------------------------------------------------- 1 | //! Spawns a task that says hello. 2 | 3 | use async_std::task; 4 | 5 | async fn say_hi() { 6 | println!("Hello, world!"); 7 | } 8 | 9 | fn main() { 10 | task::block_on(say_hi()) 11 | } 12 | -------------------------------------------------------------------------------- /examples/line-count.rs: -------------------------------------------------------------------------------- 1 | //! Counts the number of lines in a file given as an argument. 2 | 3 | use std::env::args; 4 | 5 | use async_std::fs::File; 6 | use async_std::io::{self, BufReader}; 7 | use async_std::prelude::*; 8 | use async_std::task; 9 | 10 | fn main() -> io::Result<()> { 11 | let path = args().nth(1).expect("missing path argument"); 12 | 13 | task::block_on(async { 14 | let file = File::open(&path).await?; 15 | let mut lines = BufReader::new(file).lines(); 16 | let mut count = 0u64; 17 | 18 | while let Some(line) = lines.next().await { 19 | line?; 20 | count += 1; 21 | } 22 | 23 | println!("The file contains {} lines.", count); 24 | Ok(()) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /examples/list-dir.rs: -------------------------------------------------------------------------------- 1 | //! Lists files in a directory given as an argument. 2 | 3 | use std::env::args; 4 | 5 | use async_std::fs; 6 | use async_std::io; 7 | use async_std::prelude::*; 8 | use async_std::task; 9 | 10 | fn main() -> io::Result<()> { 11 | let path = args().nth(1).expect("missing path argument"); 12 | 13 | task::block_on(async { 14 | let mut dir = fs::read_dir(&path).await?; 15 | 16 | while let Some(res) = dir.next().await { 17 | let entry = res?; 18 | println!("{}", entry.file_name().to_string_lossy()); 19 | } 20 | 21 | Ok(()) 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /examples/logging.rs: -------------------------------------------------------------------------------- 1 | //! Prints the runtime's execution log on the standard output. 2 | 3 | use async_std::task; 4 | 5 | fn main() { 6 | femme::with_level(log::LevelFilter::Trace); 7 | 8 | task::block_on(async { 9 | let handle = task::spawn(async { 10 | log::info!("Hello world!"); 11 | }); 12 | 13 | handle.await; 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /examples/print-file.rs: -------------------------------------------------------------------------------- 1 | //! Prints a file given as an argument to stdout. 2 | 3 | use std::env::args; 4 | 5 | use async_std::fs::File; 6 | use async_std::io; 7 | use async_std::prelude::*; 8 | use async_std::task; 9 | 10 | const LEN: usize = 16 * 1024; // 16 Kb 11 | 12 | fn main() -> io::Result<()> { 13 | let path = args().nth(1).expect("missing path argument"); 14 | 15 | task::block_on(async { 16 | let mut file = File::open(&path).await?; 17 | let mut stdout = io::stdout(); 18 | let mut buf = vec![0u8; LEN]; 19 | 20 | loop { 21 | // Read a buffer from the file. 22 | let n = file.read(&mut buf).await?; 23 | 24 | // If this is the end of file, clean up and return. 25 | if n == 0 { 26 | stdout.flush().await?; 27 | return Ok(()); 28 | } 29 | 30 | // Write the buffer into stdout. 31 | stdout.write_all(&buf[..n]).await?; 32 | } 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /examples/socket-timeouts.rs: -------------------------------------------------------------------------------- 1 | //! Prints response of GET request made to TCP server with 5 second socket timeout 2 | 3 | use std::time::Duration; 4 | 5 | use async_std::{io, net::TcpStream, prelude::*, task}; 6 | 7 | async fn get() -> io::Result> { 8 | let mut stream = TcpStream::connect("example.com:80").await?; 9 | stream 10 | .write_all(b"GET /index.html HTTP/1.0\r\n\r\n") 11 | .await?; 12 | 13 | let mut buf = vec![]; 14 | 15 | io::timeout(Duration::from_secs(5), async move { 16 | stream.read_to_end(&mut buf).await?; 17 | Ok(buf) 18 | }) 19 | .await 20 | } 21 | 22 | fn main() { 23 | task::block_on(async { 24 | let raw_response = get().await.expect("request"); 25 | let response = String::from_utf8(raw_response).expect("utf8 conversion"); 26 | println!("received: {}", response); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /examples/stdin-echo.rs: -------------------------------------------------------------------------------- 1 | //! Echoes lines read on stdin to stdout. 2 | 3 | use async_std::io; 4 | use async_std::prelude::*; 5 | use async_std::task; 6 | 7 | fn main() -> io::Result<()> { 8 | task::block_on(async { 9 | let stdin = io::stdin(); 10 | let mut stdout = io::stdout(); 11 | let mut line = String::new(); 12 | 13 | loop { 14 | // Read a line from stdin. 15 | let n = stdin.read_line(&mut line).await?; 16 | 17 | // If this is the end of stdin, return. 18 | if n == 0 { 19 | return Ok(()); 20 | } 21 | 22 | // Write the line to stdout. 23 | stdout.write_all(line.as_bytes()).await?; 24 | stdout.flush().await?; 25 | line.clear(); 26 | } 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /examples/stdin-timeout.rs: -------------------------------------------------------------------------------- 1 | //! Reads a line from stdin, or exits with an error if nothing is read in 5 seconds. 2 | 3 | use std::time::Duration; 4 | 5 | use async_std::io; 6 | use async_std::task; 7 | 8 | fn main() -> io::Result<()> { 9 | // This async scope times out after 5 seconds. 10 | task::block_on(io::timeout(Duration::from_secs(5), async { 11 | let stdin = io::stdin(); 12 | 13 | // Read a line from the standard input and display it. 14 | let mut line = String::new(); 15 | stdin.read_line(&mut line).await?; 16 | dbg!(line); 17 | 18 | Ok(()) 19 | })) 20 | } 21 | -------------------------------------------------------------------------------- /examples/surf-web.rs: -------------------------------------------------------------------------------- 1 | use async_std::task; 2 | 3 | fn main() -> Result<(), surf::Error> { 4 | task::block_on(async { 5 | let url = "https://www.rust-lang.org"; 6 | let mut response = surf::get(url).send().await?; 7 | let body = response.body_string().await?; 8 | 9 | dbg!(url); 10 | dbg!(response.status()); 11 | dbg!(response.version()); 12 | dbg!(response.header_names()); 13 | dbg!(response.header_values()); 14 | dbg!(body.len()); 15 | 16 | Ok(()) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /examples/task-local.rs: -------------------------------------------------------------------------------- 1 | //! Creates a task-local value. 2 | 3 | use std::cell::Cell; 4 | 5 | use async_std::prelude::*; 6 | use async_std::task; 7 | 8 | task_local! { 9 | static VAR: Cell = Cell::new(1); 10 | } 11 | 12 | fn main() { 13 | task::block_on(async { 14 | println!("var = {}", VAR.with(|v| v.get())); 15 | VAR.with(|v| v.set(2)); 16 | println!("var = {}", VAR.with(|v| v.get())); 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /examples/task-name.rs: -------------------------------------------------------------------------------- 1 | //! Spawns a named task that prints its name. 2 | 3 | use async_std::task; 4 | 5 | async fn print_name() { 6 | println!("My name is {:?}", task::current().name()); 7 | } 8 | 9 | fn main() { 10 | task::block_on(async { 11 | task::Builder::new() 12 | .name("my-task".to_string()) 13 | .spawn(print_name()) 14 | .unwrap() 15 | .await; 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /examples/tcp-client.rs: -------------------------------------------------------------------------------- 1 | //! TCP client. 2 | //! 3 | //! First start the echo server: 4 | //! 5 | //! ```sh 6 | //! $ cargo run --example tcp-echo 7 | //! ``` 8 | //! 9 | //! Then run the client: 10 | //! 11 | //! ```sh 12 | //! $ cargo run --example tcp-client 13 | //! ``` 14 | 15 | use async_std::io; 16 | use async_std::net::TcpStream; 17 | use async_std::prelude::*; 18 | use async_std::task; 19 | 20 | fn main() -> io::Result<()> { 21 | task::block_on(async { 22 | let mut stream = TcpStream::connect("127.0.0.1:8080").await?; 23 | println!("Connected to {}", &stream.peer_addr()?); 24 | 25 | let msg = "hello world"; 26 | println!("<- {}", msg); 27 | stream.write_all(msg.as_bytes()).await?; 28 | 29 | let mut buf = vec![0u8; 1024]; 30 | let n = stream.read(&mut buf).await?; 31 | println!("-> {}\n", String::from_utf8_lossy(&buf[..n])); 32 | 33 | Ok(()) 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /examples/tcp-echo.rs: -------------------------------------------------------------------------------- 1 | //! TCP echo server. 2 | //! 3 | //! To send messages, do: 4 | //! 5 | //! ```sh 6 | //! $ nc localhost 8080 7 | //! ``` 8 | 9 | use async_std::io; 10 | use async_std::net::{TcpListener, TcpStream}; 11 | use async_std::prelude::*; 12 | use async_std::task; 13 | 14 | async fn process(stream: TcpStream) -> io::Result<()> { 15 | println!("Accepted from: {}", stream.peer_addr()?); 16 | 17 | let mut reader = stream.clone(); 18 | let mut writer = stream; 19 | io::copy(&mut reader, &mut writer).await?; 20 | 21 | Ok(()) 22 | } 23 | 24 | fn main() -> io::Result<()> { 25 | task::block_on(async { 26 | let listener = TcpListener::bind("127.0.0.1:8080").await?; 27 | println!("Listening on {}", listener.local_addr()?); 28 | 29 | let mut incoming = listener.incoming(); 30 | 31 | while let Some(stream) = incoming.next().await { 32 | let stream = stream?; 33 | task::spawn(async { 34 | process(stream).await.unwrap(); 35 | }); 36 | } 37 | Ok(()) 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /examples/tcp-ipv4-and-6-echo.rs: -------------------------------------------------------------------------------- 1 | //! TCP echo server, accepting connections both on both ipv4 and ipv6 sockets. 2 | //! 3 | //! To send messages, do: 4 | //! 5 | //! ```sh 6 | //! $ nc 127.0.0.1 8080 7 | //! $ nc ::1 8080 8 | //! ``` 9 | 10 | use async_std::io; 11 | use async_std::net::{TcpListener, TcpStream}; 12 | use async_std::prelude::*; 13 | use async_std::task; 14 | 15 | async fn process(stream: TcpStream) -> io::Result<()> { 16 | println!("Accepted from: {}", stream.peer_addr()?); 17 | 18 | let mut reader = stream.clone(); 19 | let mut writer = stream; 20 | io::copy(&mut reader, &mut writer).await?; 21 | 22 | Ok(()) 23 | } 24 | 25 | fn main() -> io::Result<()> { 26 | task::block_on(async { 27 | let ipv4_listener = TcpListener::bind("127.0.0.1:8080").await?; 28 | println!("Listening on {}", ipv4_listener.local_addr()?); 29 | let ipv6_listener = TcpListener::bind("[::1]:8080").await?; 30 | println!("Listening on {}", ipv6_listener.local_addr()?); 31 | 32 | let ipv4_incoming = ipv4_listener.incoming(); 33 | let ipv6_incoming = ipv6_listener.incoming(); 34 | 35 | let mut incoming = ipv4_incoming.merge(ipv6_incoming); 36 | 37 | while let Some(stream) = incoming.next().await { 38 | let stream = stream?; 39 | task::spawn(async { 40 | process(stream).await.unwrap(); 41 | }); 42 | } 43 | Ok(()) 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /examples/udp-client.rs: -------------------------------------------------------------------------------- 1 | //! UDP client. 2 | //! 3 | //! First start the echo server: 4 | //! 5 | //! ```sh 6 | //! $ cargo run --example udp-echo 7 | //! ``` 8 | //! 9 | //! Then run the client: 10 | //! 11 | //! ```sh 12 | //! $ cargo run --example udp-client 13 | //! ``` 14 | 15 | use async_std::io; 16 | use async_std::net::UdpSocket; 17 | use async_std::task; 18 | 19 | fn main() -> io::Result<()> { 20 | task::block_on(async { 21 | let socket = UdpSocket::bind("127.0.0.1:8081").await?; 22 | println!("Listening on {}", socket.local_addr()?); 23 | 24 | let msg = "hello world"; 25 | println!("<- {}", msg); 26 | socket.send_to(msg.as_bytes(), "127.0.0.1:8080").await?; 27 | 28 | let mut buf = vec![0u8; 1024]; 29 | let (n, _) = socket.recv_from(&mut buf).await?; 30 | println!("-> {}\n", String::from_utf8_lossy(&buf[..n])); 31 | 32 | Ok(()) 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /examples/udp-echo.rs: -------------------------------------------------------------------------------- 1 | //! UDP echo server. 2 | //! 3 | //! To send messages, do: 4 | //! 5 | //! ```sh 6 | //! $ nc -u localhost 8080 7 | //! ``` 8 | 9 | use async_std::io; 10 | use async_std::net::UdpSocket; 11 | use async_std::task; 12 | 13 | fn main() -> io::Result<()> { 14 | task::block_on(async { 15 | let socket = UdpSocket::bind("127.0.0.1:8080").await?; 16 | let mut buf = vec![0u8; 1024]; 17 | 18 | println!("Listening on {}", socket.local_addr()?); 19 | 20 | loop { 21 | let (n, peer) = socket.recv_from(&mut buf).await?; 22 | let sent = socket.send_to(&buf[..n], &peer).await?; 23 | println!("Sent {} out of {} bytes to {}", sent, n, peer); 24 | } 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /src/channel.rs: -------------------------------------------------------------------------------- 1 | //! Channels 2 | //! 3 | //! Multi-producer, multi-consumer queues, used for message-based 4 | //! communication. Can provide a lightweight inter-task synchronisation 5 | //! mechanism, at the cost of some extra memory. 6 | 7 | #[doc(inline)] 8 | pub use async_channel::*; 9 | -------------------------------------------------------------------------------- /src/collections/binary_heap/extend.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, IntoStream}; 6 | 7 | impl stream::Extend for BinaryHeap { 8 | fn extend<'a, S: IntoStream + 'a>( 9 | &'a mut self, 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | let stream = stream.into_stream(); 16 | 17 | self.reserve(stream.size_hint().0); 18 | 19 | Box::pin(stream.for_each(move |item| self.push(item))) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/collections/binary_heap/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, FromStream, IntoStream}; 6 | 7 | impl FromStream for BinaryHeap { 8 | #[inline] 9 | fn from_stream<'a, S: IntoStream + 'a>( 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | let stream = stream.into_stream(); 16 | 17 | Box::pin(async move { 18 | let mut out = BinaryHeap::new(); 19 | stream::extend(&mut out, stream).await; 20 | out 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/collections/binary_heap/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust priority queue implemented with a binary heap 2 | 3 | mod extend; 4 | mod from_stream; 5 | 6 | #[doc(inline)] 7 | pub use std::collections::BinaryHeap; 8 | -------------------------------------------------------------------------------- /src/collections/btree_map/extend.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeMap; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, IntoStream}; 6 | 7 | impl stream::Extend<(K, V)> for BTreeMap { 8 | fn extend<'a, S: IntoStream + 'a>( 9 | &'a mut self, 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | Box::pin(stream.into_stream().for_each(move |(k, v)| { 16 | self.insert(k, v); 17 | })) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/collections/btree_map/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeMap; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, FromStream, IntoStream}; 6 | 7 | impl FromStream<(K, V)> for BTreeMap { 8 | #[inline] 9 | fn from_stream<'a, S: IntoStream + 'a>( 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | let stream = stream.into_stream(); 16 | 17 | Box::pin(async move { 18 | let mut out = BTreeMap::new(); 19 | stream::extend(&mut out, stream).await; 20 | out 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/collections/btree_map/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust B-Tree Map 2 | 3 | mod extend; 4 | mod from_stream; 5 | 6 | #[doc(inline)] 7 | pub use std::collections::BTreeMap; 8 | -------------------------------------------------------------------------------- /src/collections/btree_set/extend.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeSet; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, IntoStream}; 6 | 7 | impl stream::Extend for BTreeSet { 8 | fn extend<'a, S: IntoStream + 'a>( 9 | &'a mut self, 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | Box::pin(stream.into_stream().for_each(move |item| { 16 | self.insert(item); 17 | })) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/collections/btree_set/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeSet; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, FromStream, IntoStream}; 6 | 7 | impl FromStream for BTreeSet { 8 | #[inline] 9 | fn from_stream<'a, S: IntoStream + 'a>( 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | let stream = stream.into_stream(); 16 | 17 | Box::pin(async move { 18 | let mut out = BTreeSet::new(); 19 | stream::extend(&mut out, stream).await; 20 | out 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/collections/btree_set/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust B-Tree Set 2 | 3 | mod extend; 4 | mod from_stream; 5 | 6 | #[doc(inline)] 7 | pub use std::collections::BTreeSet; 8 | -------------------------------------------------------------------------------- /src/collections/hash_map/extend.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::hash::{BuildHasher, Hash}; 3 | use std::pin::Pin; 4 | 5 | use crate::prelude::*; 6 | use crate::stream::{self, IntoStream}; 7 | 8 | impl stream::Extend<(K, V)> for HashMap 9 | where 10 | K: Eq + Hash + Send, 11 | V: Send, 12 | H: BuildHasher + Default + Send, 13 | { 14 | fn extend<'a, S: IntoStream + 'a>( 15 | &'a mut self, 16 | stream: S, 17 | ) -> Pin + 'a + Send>> 18 | where 19 | ::IntoStream: Send, 20 | { 21 | let stream = stream.into_stream(); 22 | 23 | // The following is adapted from the hashbrown source code: 24 | // https://github.com/rust-lang/hashbrown/blob/d1ad4fc3aae2ade446738eea512e50b9e863dd0c/src/map.rs#L2470-L2491 25 | // 26 | // Keys may be already present or show multiple times in the stream. Reserve the entire 27 | // hint lower bound if the map is empty. Otherwise reserve half the hint (rounded up), so 28 | // the map will only resize twice in the worst case. 29 | 30 | let additional = if self.is_empty() { 31 | stream.size_hint().0 32 | } else { 33 | (stream.size_hint().0 + 1) / 2 34 | }; 35 | self.reserve(additional); 36 | 37 | Box::pin(stream.for_each(move |(k, v)| { 38 | self.insert(k, v); 39 | })) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/collections/hash_map/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::hash::{BuildHasher, Hash}; 3 | use std::pin::Pin; 4 | 5 | use crate::prelude::*; 6 | use crate::stream::{self, FromStream, IntoStream}; 7 | 8 | impl FromStream<(K, V)> for HashMap 9 | where 10 | K: Eq + Hash + Send, 11 | H: BuildHasher + Default + Send, 12 | V: Send, 13 | { 14 | #[inline] 15 | fn from_stream<'a, S: IntoStream + 'a>( 16 | stream: S, 17 | ) -> Pin + 'a + Send>> 18 | where 19 | ::IntoStream: Send, 20 | { 21 | let stream = stream.into_stream(); 22 | 23 | Box::pin(async move { 24 | let mut out = HashMap::with_hasher(Default::default()); 25 | stream::extend(&mut out, stream).await; 26 | out 27 | }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/collections/hash_map/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust hash map, implemented with quadratic probing and SIMD lookup. 2 | 3 | mod extend; 4 | mod from_stream; 5 | 6 | #[doc(inline)] 7 | pub use std::collections::HashMap; 8 | -------------------------------------------------------------------------------- /src/collections/hash_set/extend.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::hash::{BuildHasher, Hash}; 3 | use std::pin::Pin; 4 | 5 | use crate::prelude::*; 6 | use crate::stream::{self, IntoStream}; 7 | 8 | impl stream::Extend for HashSet 9 | where 10 | T: Eq + Hash + Send, 11 | H: BuildHasher + Default + Send, 12 | { 13 | fn extend<'a, S: IntoStream + 'a>( 14 | &'a mut self, 15 | stream: S, 16 | ) -> Pin + 'a + Send>> 17 | where 18 | ::IntoStream: Send, 19 | { 20 | // The Extend impl for HashSet in the standard library delegates to the internal HashMap. 21 | // Thus, this impl is just a copy of the async Extend impl for HashMap in this crate. 22 | 23 | let stream = stream.into_stream(); 24 | 25 | // The following is adapted from the hashbrown source code: 26 | // https://github.com/rust-lang/hashbrown/blob/d1ad4fc3aae2ade446738eea512e50b9e863dd0c/src/map.rs#L2470-L2491 27 | // 28 | // Keys may be already present or show multiple times in the stream. Reserve the entire 29 | // hint lower bound if the map is empty. Otherwise reserve half the hint (rounded up), so 30 | // the map will only resize twice in the worst case. 31 | 32 | let additional = if self.is_empty() { 33 | stream.size_hint().0 34 | } else { 35 | (stream.size_hint().0 + 1) / 2 36 | }; 37 | self.reserve(additional); 38 | 39 | Box::pin(stream.for_each(move |item| { 40 | self.insert(item); 41 | })) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/collections/hash_set/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::hash::{BuildHasher, Hash}; 3 | use std::pin::Pin; 4 | 5 | use crate::prelude::*; 6 | use crate::stream::{self, FromStream, IntoStream}; 7 | 8 | impl FromStream for HashSet 9 | where 10 | T: Eq + Hash + Send, 11 | H: BuildHasher + Default + Send, 12 | { 13 | #[inline] 14 | fn from_stream<'a, S: IntoStream + 'a>( 15 | stream: S, 16 | ) -> Pin + 'a + Send>> 17 | where 18 | ::IntoStream: Send, 19 | { 20 | let stream = stream.into_stream(); 21 | 22 | Box::pin(async move { 23 | let mut out = HashSet::with_hasher(Default::default()); 24 | stream::extend(&mut out, stream).await; 25 | out 26 | }) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/collections/hash_set/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust hash set, implemented as a `HashMap` where the value is `()`. 2 | 3 | mod extend; 4 | mod from_stream; 5 | 6 | #[doc(inline)] 7 | pub use std::collections::HashSet; 8 | -------------------------------------------------------------------------------- /src/collections/linked_list/extend.rs: -------------------------------------------------------------------------------- 1 | use std::collections::LinkedList; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, IntoStream}; 6 | 7 | impl stream::Extend for LinkedList { 8 | fn extend<'a, S: IntoStream + 'a>( 9 | &'a mut self, 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | let stream = stream.into_stream(); 16 | Box::pin(stream.for_each(move |item| self.push_back(item))) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/collections/linked_list/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::collections::LinkedList; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, FromStream, IntoStream}; 6 | 7 | impl FromStream for LinkedList { 8 | #[inline] 9 | fn from_stream<'a, S: IntoStream + 'a>( 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | let stream = stream.into_stream(); 16 | 17 | Box::pin(async move { 18 | let mut out = LinkedList::new(); 19 | stream::extend(&mut out, stream).await; 20 | out 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/collections/linked_list/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust doubly-linked list with owned nodes 2 | 3 | mod extend; 4 | mod from_stream; 5 | 6 | #[doc(inline)] 7 | pub use std::collections::LinkedList; 8 | -------------------------------------------------------------------------------- /src/collections/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust standard collections 2 | //! 3 | //! This library provides efficient implementations of the most common general purpose programming 4 | //! data structures. 5 | 6 | pub mod binary_heap; 7 | pub mod btree_map; 8 | pub mod btree_set; 9 | pub mod hash_map; 10 | pub mod hash_set; 11 | pub mod linked_list; 12 | pub mod vec_deque; 13 | 14 | #[allow(unused)] 15 | pub use binary_heap::BinaryHeap; 16 | #[allow(unused)] 17 | pub use btree_map::BTreeMap; 18 | #[allow(unused)] 19 | pub use btree_set::BTreeSet; 20 | #[allow(unused)] 21 | pub use hash_map::HashMap; 22 | #[allow(unused)] 23 | pub use hash_set::HashSet; 24 | #[allow(unused)] 25 | pub use linked_list::LinkedList; 26 | #[allow(unused)] 27 | pub use vec_deque::VecDeque; 28 | -------------------------------------------------------------------------------- /src/collections/vec_deque/extend.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, IntoStream}; 6 | 7 | impl stream::Extend for VecDeque { 8 | fn extend<'a, S: IntoStream + 'a>( 9 | &'a mut self, 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | let stream = stream.into_stream(); 16 | 17 | self.reserve(stream.size_hint().0); 18 | 19 | Box::pin(stream.for_each(move |item| self.push_back(item))) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/collections/vec_deque/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::pin::Pin; 3 | 4 | use crate::prelude::*; 5 | use crate::stream::{self, FromStream, IntoStream}; 6 | 7 | impl FromStream for VecDeque { 8 | #[inline] 9 | fn from_stream<'a, S: IntoStream + 'a>( 10 | stream: S, 11 | ) -> Pin + 'a + Send>> 12 | where 13 | ::IntoStream: Send, 14 | { 15 | let stream = stream.into_stream(); 16 | 17 | Box::pin(async move { 18 | let mut out = VecDeque::new(); 19 | stream::extend(&mut out, stream).await; 20 | out 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/collections/vec_deque/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust double-ended queue, implemented with a growable ring buffer. 2 | 3 | mod extend; 4 | mod from_stream; 5 | 6 | #[doc(inline)] 7 | pub use std::collections::VecDeque; 8 | -------------------------------------------------------------------------------- /src/fs/canonicalize.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::{Path, PathBuf}; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Returns the canonical form of a path. 7 | /// 8 | /// The returned path is in absolute form with all intermediate components normalized and symbolic 9 | /// links resolved. 10 | /// 11 | /// This function is an async version of [`std::fs::canonicalize`]. 12 | /// 13 | /// [`std::fs::canonicalize`]: https://doc.rust-lang.org/std/fs/fn.canonicalize.html 14 | /// 15 | /// # Errors 16 | /// 17 | /// An error will be returned in the following situations: 18 | /// 19 | /// * `path` does not point to an existing file or directory. 20 | /// * A non-final component in `path` is not a directory. 21 | /// * Some other I/O error occurred. 22 | /// 23 | /// # Examples 24 | /// 25 | /// ```no_run 26 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 27 | /// # 28 | /// use async_std::fs; 29 | /// 30 | /// let path = fs::canonicalize(".").await?; 31 | /// # 32 | /// # Ok(()) }) } 33 | /// ``` 34 | pub async fn canonicalize>(path: P) -> io::Result { 35 | let path = path.as_ref().to_owned(); 36 | spawn_blocking(move || { 37 | std::fs::canonicalize(&path) 38 | .map(Into::into) 39 | .context(|| format!("could not canonicalize `{}`", path.display())) 40 | }) 41 | .await 42 | } 43 | -------------------------------------------------------------------------------- /src/fs/copy.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Copies the contents and permissions of a file to a new location. 7 | /// 8 | /// On success, the total number of bytes copied is returned and equals the length of the `to` file 9 | /// after this operation. 10 | /// 11 | /// The old contents of `to` will be overwritten. If `from` and `to` both point to the same file, 12 | /// then the file will likely get truncated as a result of this operation. 13 | /// 14 | /// If you're working with open [`File`]s and want to copy contents through those types, use the 15 | /// [`io::copy`] function. 16 | /// 17 | /// This function is an async version of [`std::fs::copy`]. 18 | /// 19 | /// [`File`]: struct.File.html 20 | /// [`io::copy`]: ../io/fn.copy.html 21 | /// [`std::fs::copy`]: https://doc.rust-lang.org/std/fs/fn.copy.html 22 | /// 23 | /// # Errors 24 | /// 25 | /// An error will be returned in the following situations: 26 | /// 27 | /// * `from` does not point to an existing file. 28 | /// * The current process lacks permissions to read `from` or write `to`. 29 | /// * Some other I/O error occurred. 30 | /// 31 | /// # Examples 32 | /// 33 | /// ```no_run 34 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 35 | /// # 36 | /// use async_std::fs; 37 | /// 38 | /// let num_bytes = fs::copy("a.txt", "b.txt").await?; 39 | /// # 40 | /// # Ok(()) }) } 41 | /// ``` 42 | pub async fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { 43 | let from = from.as_ref().to_owned(); 44 | let to = to.as_ref().to_owned(); 45 | spawn_blocking(move || { 46 | std::fs::copy(&from, &to) 47 | .context(|| format!("could not copy `{}` to `{}`", from.display(), to.display())) 48 | }) 49 | .await 50 | } 51 | -------------------------------------------------------------------------------- /src/fs/create_dir.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Creates a new directory. 7 | /// 8 | /// Note that this function will only create the final directory in `path`. If you want to create 9 | /// all of its missing parent directories too, use the [`create_dir_all`] function instead. 10 | /// 11 | /// This function is an async version of [`std::fs::create_dir`]. 12 | /// 13 | /// [`create_dir_all`]: fn.create_dir_all.html 14 | /// [`std::fs::create_dir`]: https://doc.rust-lang.org/std/fs/fn.create_dir.html 15 | /// 16 | /// # Errors 17 | /// 18 | /// An error will be returned in the following situations: 19 | /// 20 | /// * `path` already points to an existing file or directory. 21 | /// * A parent directory in `path` does not exist. 22 | /// * The current process lacks permissions to create the directory. 23 | /// * Some other I/O error occurred. 24 | /// 25 | /// # Examples 26 | /// 27 | /// ```no_run 28 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 29 | /// # 30 | /// use async_std::fs; 31 | /// 32 | /// fs::create_dir("./some/directory").await?; 33 | /// # 34 | /// # Ok(()) }) } 35 | /// ``` 36 | pub async fn create_dir>(path: P) -> io::Result<()> { 37 | let path = path.as_ref().to_owned(); 38 | spawn_blocking(move || { 39 | std::fs::create_dir(&path) 40 | .context(|| format!("could not create directory `{}`", path.display())) 41 | }) 42 | .await 43 | } 44 | -------------------------------------------------------------------------------- /src/fs/create_dir_all.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Creates a new directory and all of its parents if they are missing. 7 | /// 8 | /// This function is an async version of [`std::fs::create_dir_all`]. 9 | /// 10 | /// [`std::fs::create_dir_all`]: https://doc.rust-lang.org/std/fs/fn.create_dir_all.html 11 | /// 12 | /// # Errors 13 | /// 14 | /// An error will be returned in the following situations: 15 | /// 16 | /// * `path` already points to an existing file or directory. 17 | /// * The current process lacks permissions to create the directory or its missing parents. 18 | /// * Some other I/O error occurred. 19 | /// 20 | /// # Examples 21 | /// 22 | /// ```no_run 23 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 24 | /// # 25 | /// use async_std::fs; 26 | /// 27 | /// fs::create_dir_all("./some/directory").await?; 28 | /// # 29 | /// # Ok(()) }) } 30 | /// ``` 31 | pub async fn create_dir_all>(path: P) -> io::Result<()> { 32 | let path = path.as_ref().to_owned(); 33 | spawn_blocking(move || { 34 | std::fs::create_dir_all(&path) 35 | .context(|| format!("could not create directory path `{}`", path.display())) 36 | }) 37 | .await 38 | } 39 | -------------------------------------------------------------------------------- /src/fs/hard_link.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Creates a hard link on the filesystem. 7 | /// 8 | /// The `dst` path will be a link pointing to the `src` path. Note that operating systems often 9 | /// require these two paths to be located on the same filesystem. 10 | /// 11 | /// This function is an async version of [`std::fs::hard_link`]. 12 | /// 13 | /// [`std::fs::hard_link`]: https://doc.rust-lang.org/std/fs/fn.hard_link.html 14 | /// 15 | /// # Errors 16 | /// 17 | /// An error will be returned in the following situations: 18 | /// 19 | /// * `src` does not point to an existing file. 20 | /// * Some other I/O error occurred. 21 | /// 22 | /// # Examples 23 | /// 24 | /// ```no_run 25 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 26 | /// # 27 | /// use async_std::fs; 28 | /// 29 | /// fs::hard_link("a.txt", "b.txt").await?; 30 | /// # 31 | /// # Ok(()) }) } 32 | /// ``` 33 | pub async fn hard_link, Q: AsRef>(from: P, to: Q) -> io::Result<()> { 34 | let from = from.as_ref().to_owned(); 35 | let to = to.as_ref().to_owned(); 36 | spawn_blocking(move || { 37 | std::fs::hard_link(&from, &to).context(|| { 38 | format!( 39 | "could not create a hard link from `{}` to `{}`", 40 | from.display(), 41 | to.display() 42 | ) 43 | }) 44 | }) 45 | .await 46 | } 47 | -------------------------------------------------------------------------------- /src/fs/permissions.rs: -------------------------------------------------------------------------------- 1 | cfg_not_docs! { 2 | pub use std::fs::Permissions; 3 | } 4 | 5 | cfg_docs! { 6 | /// A set of permissions on a file or directory. 7 | /// 8 | /// This type is a re-export of [`std::fs::Permissions`]. 9 | /// 10 | /// [`std::fs::Permissions`]: https://doc.rust-lang.org/std/fs/struct.Permissions.html 11 | #[derive(Clone, PartialEq, Eq, Debug)] 12 | pub struct Permissions { 13 | _private: (), 14 | } 15 | 16 | impl Permissions { 17 | /// Returns the read-only flag. 18 | /// 19 | /// # Examples 20 | /// 21 | /// ```no_run 22 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 23 | /// # 24 | /// use async_std::fs; 25 | /// 26 | /// let perm = fs::metadata("a.txt").await?.permissions(); 27 | /// println!("{:?}", perm.readonly()); 28 | /// # 29 | /// # Ok(()) }) } 30 | /// ``` 31 | pub fn readonly(&self) -> bool { 32 | unreachable!("this impl only appears in the rendered docs") 33 | } 34 | 35 | /// Configures the read-only flag. 36 | /// 37 | /// [`fs::set_permissions`]: fn.set_permissions.html 38 | /// 39 | /// # Examples 40 | /// 41 | /// ```no_run 42 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 43 | /// # 44 | /// use async_std::fs; 45 | /// 46 | /// let mut perm = fs::metadata("a.txt").await?.permissions(); 47 | /// perm.set_readonly(true); 48 | /// fs::set_permissions("a.txt", perm).await?; 49 | /// # 50 | /// # Ok(()) }) } 51 | /// ``` 52 | pub fn set_readonly(&mut self, readonly: bool) { 53 | unreachable!("this impl only appears in the rendered docs") 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/fs/read.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Reads the entire contents of a file as raw bytes. 7 | /// 8 | /// This is a convenience function for reading entire files. It pre-allocates a buffer based on the 9 | /// file size when available, so it is typically faster than manually opening a file and reading 10 | /// from it. 11 | /// 12 | /// If you want to read the contents as a string, use [`read_to_string`] instead. 13 | /// 14 | /// This function is an async version of [`std::fs::read`]. 15 | /// 16 | /// [`read_to_string`]: fn.read_to_string.html 17 | /// [`std::fs::read`]: https://doc.rust-lang.org/std/fs/fn.read.html 18 | /// 19 | /// # Errors 20 | /// 21 | /// An error will be returned in the following situations: 22 | /// 23 | /// * `path` does not point to an existing file. 24 | /// * The current process lacks permissions to read the file. 25 | /// * Some other I/O error occurred. 26 | /// 27 | /// # Examples 28 | /// 29 | /// ```no_run 30 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 31 | /// # 32 | /// use async_std::fs; 33 | /// 34 | /// let contents = fs::read("a.txt").await?; 35 | /// # 36 | /// # Ok(()) }) } 37 | /// ``` 38 | pub async fn read>(path: P) -> io::Result> { 39 | let path = path.as_ref().to_owned(); 40 | spawn_blocking(move || { 41 | std::fs::read(&path).context(|| format!("could not read file `{}`", path.display())) 42 | }) 43 | .await 44 | } 45 | -------------------------------------------------------------------------------- /src/fs/read_link.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::{Path, PathBuf}; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Reads a symbolic link and returns the path it points to. 7 | /// 8 | /// This function is an async version of [`std::fs::read_link`]. 9 | /// 10 | /// [`std::fs::read_link`]: https://doc.rust-lang.org/std/fs/fn.read_link.html 11 | /// 12 | /// # Errors 13 | /// 14 | /// An error will be returned in the following situations: 15 | /// 16 | /// * `path` does not point to an existing link. 17 | /// * Some other I/O error occurred. 18 | /// 19 | /// # Examples 20 | /// 21 | /// ```no_run 22 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 23 | /// # 24 | /// use async_std::fs; 25 | /// 26 | /// let path = fs::read_link("a.txt").await?; 27 | /// # 28 | /// # Ok(()) }) } 29 | /// ``` 30 | pub async fn read_link>(path: P) -> io::Result { 31 | let path = path.as_ref().to_owned(); 32 | spawn_blocking(move || { 33 | std::fs::read_link(&path) 34 | .map(Into::into) 35 | .context(|| format!("could not read link `{}`", path.display())) 36 | }) 37 | .await 38 | } 39 | -------------------------------------------------------------------------------- /src/fs/read_to_string.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Reads the entire contents of a file as a string. 7 | /// 8 | /// This is a convenience function for reading entire files. It pre-allocates a string based on the 9 | /// file size when available, so it is typically faster than manually opening a file and reading 10 | /// from it. 11 | /// 12 | /// If you want to read the contents as raw bytes, use [`read`] instead. 13 | /// 14 | /// This function is an async version of [`std::fs::read_to_string`]. 15 | /// 16 | /// [`read`]: fn.read.html 17 | /// [`std::fs::read_to_string`]: https://doc.rust-lang.org/std/fs/fn.read_to_string.html 18 | /// 19 | /// # Errors 20 | /// 21 | /// An error will be returned in the following situations: 22 | /// 23 | /// * `path` does not point to an existing file. 24 | /// * The current process lacks permissions to read the file. 25 | /// * The contents of the file cannot be read as a UTF-8 string. 26 | /// * Some other I/O error occurred. 27 | /// 28 | /// # Examples 29 | /// 30 | /// ```no_run 31 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 32 | /// # 33 | /// use async_std::fs; 34 | /// 35 | /// let contents = fs::read_to_string("a.txt").await?; 36 | /// # 37 | /// # Ok(()) }) } 38 | /// ``` 39 | pub async fn read_to_string>(path: P) -> io::Result { 40 | let path = path.as_ref().to_owned(); 41 | spawn_blocking(move || { 42 | std::fs::read_to_string(&path) 43 | .context(|| format!("could not read file `{}`", path.display())) 44 | }) 45 | .await 46 | } 47 | -------------------------------------------------------------------------------- /src/fs/remove_dir.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Removes an empty directory. 7 | /// 8 | /// This function is an async version of [`std::fs::remove_dir`]. 9 | /// 10 | /// [`std::fs::remove_dir`]: https://doc.rust-lang.org/std/fs/fn.remove_dir.html 11 | /// 12 | /// # Errors 13 | /// 14 | /// An error will be returned in the following situations: 15 | /// 16 | /// * `path` is not an existing and empty directory. 17 | /// * The current process lacks permissions to remove the directory. 18 | /// * Some other I/O error occurred. 19 | /// 20 | /// # Examples 21 | /// 22 | /// ```no_run 23 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 24 | /// # 25 | /// use async_std::fs; 26 | /// 27 | /// fs::remove_dir("./some/directory").await?; 28 | /// # 29 | /// # Ok(()) }) } 30 | /// ``` 31 | pub async fn remove_dir>(path: P) -> io::Result<()> { 32 | let path = path.as_ref().to_owned(); 33 | spawn_blocking(move || { 34 | std::fs::remove_dir(&path) 35 | .context(|| format!("could not remove directory `{}`", path.display())) 36 | }) 37 | .await 38 | } 39 | -------------------------------------------------------------------------------- /src/fs/remove_dir_all.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Removes a directory and all of its contents. 7 | /// 8 | /// This function is an async version of [`std::fs::remove_dir_all`]. 9 | /// 10 | /// [`std::fs::remove_dir_all`]: https://doc.rust-lang.org/std/fs/fn.remove_dir_all.html 11 | /// 12 | /// # Errors 13 | /// 14 | /// An error will be returned in the following situations: 15 | /// 16 | /// * `path` is not an existing and empty directory. 17 | /// * The current process lacks permissions to remove the directory. 18 | /// * Some other I/O error occurred. 19 | /// 20 | /// # Examples 21 | /// 22 | /// ```no_run 23 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 24 | /// # 25 | /// use async_std::fs; 26 | /// 27 | /// fs::remove_dir_all("./some/directory").await?; 28 | /// # 29 | /// # Ok(()) }) } 30 | /// ``` 31 | pub async fn remove_dir_all>(path: P) -> io::Result<()> { 32 | let path = path.as_ref().to_owned(); 33 | spawn_blocking(move || { 34 | std::fs::remove_dir_all(&path) 35 | .context(|| format!("could not remove directory `{}`", path.display())) 36 | }) 37 | .await 38 | } 39 | -------------------------------------------------------------------------------- /src/fs/remove_file.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Removes a file. 7 | /// 8 | /// This function is an async version of [`std::fs::remove_file`]. 9 | /// 10 | /// [`std::fs::remove_file`]: https://doc.rust-lang.org/std/fs/fn.remove_file.html 11 | /// 12 | /// # Errors 13 | /// 14 | /// An error will be returned in the following situations: 15 | /// 16 | /// * `path` does not point to an existing file. 17 | /// * The current process lacks permissions to remove the file. 18 | /// * Some other I/O error occurred. 19 | /// 20 | /// # Examples 21 | /// 22 | /// ```no_run 23 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 24 | /// # 25 | /// use async_std::fs; 26 | /// 27 | /// fs::remove_file("a.txt").await?; 28 | /// # 29 | /// # Ok(()) }) } 30 | /// ``` 31 | pub async fn remove_file>(path: P) -> io::Result<()> { 32 | let path = path.as_ref().to_owned(); 33 | spawn_blocking(move || { 34 | std::fs::remove_file(&path) 35 | .context(|| format!("could not remove file `{}`", path.display())) 36 | }) 37 | .await 38 | } 39 | -------------------------------------------------------------------------------- /src/fs/rename.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Renames a file or directory to a new location. 7 | /// 8 | /// If a file or directory already exists at the target location, it will be overwritten by this 9 | /// operation. 10 | /// 11 | /// This function is an async version of [`std::fs::rename`]. 12 | /// 13 | /// [`std::fs::rename`]: https://doc.rust-lang.org/std/fs/fn.rename.html 14 | /// 15 | /// # Errors 16 | /// 17 | /// An error will be returned in the following situations: 18 | /// 19 | /// * `from` does not point to an existing file or directory. 20 | /// * `from` and `to` are on different filesystems. 21 | /// * The current process lacks permissions to do the rename operation. 22 | /// * Some other I/O error occurred. 23 | /// 24 | /// # Examples 25 | /// 26 | /// ```no_run 27 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 28 | /// # 29 | /// use async_std::fs; 30 | /// 31 | /// fs::rename("a.txt", "b.txt").await?; 32 | /// # 33 | /// # Ok(()) }) } 34 | /// ``` 35 | pub async fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> { 36 | let from = from.as_ref().to_owned(); 37 | let to = to.as_ref().to_owned(); 38 | spawn_blocking(move || { 39 | std::fs::rename(&from, &to).context(|| { 40 | format!( 41 | "could not rename `{}` to `{}`", 42 | from.display(), 43 | to.display() 44 | ) 45 | }) 46 | }) 47 | .await 48 | } 49 | -------------------------------------------------------------------------------- /src/fs/set_permissions.rs: -------------------------------------------------------------------------------- 1 | use crate::fs::Permissions; 2 | use crate::io; 3 | use crate::path::Path; 4 | use crate::task::spawn_blocking; 5 | 6 | /// Changes the permissions of a file or directory. 7 | /// 8 | /// This function is an async version of [`std::fs::set_permissions`]. 9 | /// 10 | /// [`std::fs::set_permissions`]: https://doc.rust-lang.org/std/fs/fn.set_permissions.html 11 | /// 12 | /// # Errors 13 | /// 14 | /// An error will be returned in the following situations: 15 | /// 16 | /// * `path` does not point to an existing file or directory. 17 | /// * The current process lacks permissions to change attributes on the file or directory. 18 | /// * Some other I/O error occurred. 19 | /// 20 | /// # Examples 21 | /// 22 | /// ```no_run 23 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 24 | /// # 25 | /// use async_std::fs; 26 | /// 27 | /// let mut perm = fs::metadata("a.txt").await?.permissions(); 28 | /// perm.set_readonly(true); 29 | /// fs::set_permissions("a.txt", perm).await?; 30 | /// # 31 | /// # Ok(()) }) } 32 | /// ``` 33 | pub async fn set_permissions>(path: P, perm: Permissions) -> io::Result<()> { 34 | let path = path.as_ref().to_owned(); 35 | spawn_blocking(move || std::fs::set_permissions(path, perm)).await 36 | } 37 | -------------------------------------------------------------------------------- /src/fs/symlink_metadata.rs: -------------------------------------------------------------------------------- 1 | use crate::fs::Metadata; 2 | use crate::io; 3 | use crate::path::Path; 4 | use crate::task::spawn_blocking; 5 | 6 | /// Reads metadata for a path without following symbolic links. 7 | /// 8 | /// If you want to follow symbolic links before reading metadata of the target file or directory, 9 | /// use [`metadata`] instead. 10 | /// 11 | /// This function is an async version of [`std::fs::symlink_metadata`]. 12 | /// 13 | /// [`metadata`]: fn.metadata.html 14 | /// [`std::fs::symlink_metadata`]: https://doc.rust-lang.org/std/fs/fn.symlink_metadata.html 15 | /// 16 | /// # Errors 17 | /// 18 | /// An error will be returned in the following situations: 19 | /// 20 | /// * `path` does not point to an existing file or directory. 21 | /// * The current process lacks permissions to read metadata for the path. 22 | /// * Some other I/O error occurred. 23 | /// 24 | /// # Examples 25 | /// 26 | /// ```no_run 27 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 28 | /// # 29 | /// use async_std::fs; 30 | /// 31 | /// let perm = fs::symlink_metadata("a.txt").await?.permissions(); 32 | /// # 33 | /// # Ok(()) }) } 34 | /// ``` 35 | pub async fn symlink_metadata>(path: P) -> io::Result { 36 | let path = path.as_ref().to_owned(); 37 | spawn_blocking(move || std::fs::symlink_metadata(path)).await 38 | } 39 | -------------------------------------------------------------------------------- /src/fs/write.rs: -------------------------------------------------------------------------------- 1 | use crate::io; 2 | use crate::path::Path; 3 | use crate::task::spawn_blocking; 4 | use crate::utils::Context as _; 5 | 6 | /// Writes a slice of bytes as the new contents of a file. 7 | /// 8 | /// This function will create a file if it does not exist, and will entirely replace its contents 9 | /// if it does. 10 | /// 11 | /// This function is an async version of [`std::fs::write`]. 12 | /// 13 | /// [`std::fs::write`]: https://doc.rust-lang.org/std/fs/fn.write.html 14 | /// 15 | /// # Errors 16 | /// 17 | /// An error will be returned in the following situations: 18 | /// 19 | /// * The file's parent directory does not exist. 20 | /// * The current process lacks permissions to write to the file. 21 | /// * Some other I/O error occurred. 22 | /// 23 | /// # Examples 24 | /// 25 | /// ```no_run 26 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 27 | /// # 28 | /// use async_std::fs; 29 | /// 30 | /// fs::write("a.txt", b"Hello world!").await?; 31 | /// # 32 | /// # Ok(()) }) } 33 | /// ``` 34 | pub async fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { 35 | let path = path.as_ref().to_owned(); 36 | let contents = contents.as_ref().to_owned(); 37 | spawn_blocking(move || { 38 | std::fs::write(&path, contents) 39 | .context(|| format!("could not write to file `{}`", path.display())) 40 | }) 41 | .await 42 | } 43 | -------------------------------------------------------------------------------- /src/future/future/delay.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | use std::pin::Pin; 3 | use std::time::Duration; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::task::{Context, Poll}; 8 | use crate::utils::{timer_after, Timer}; 9 | 10 | pin_project! { 11 | #[doc(hidden)] 12 | #[allow(missing_debug_implementations)] 13 | pub struct DelayFuture { 14 | #[pin] 15 | future: F, 16 | #[pin] 17 | delay: Timer, 18 | } 19 | } 20 | 21 | impl DelayFuture { 22 | pub fn new(future: F, dur: Duration) -> DelayFuture { 23 | let delay = timer_after(dur); 24 | 25 | DelayFuture { future, delay } 26 | } 27 | } 28 | 29 | impl Future for DelayFuture { 30 | type Output = F::Output; 31 | 32 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 33 | let this = self.project(); 34 | 35 | match this.delay.poll(cx) { 36 | Poll::Pending => Poll::Pending, 37 | Poll::Ready(_) => match this.future.poll(cx) { 38 | Poll::Ready(v) => Poll::Ready(v), 39 | Poll::Pending => Poll::Pending, 40 | }, 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/future/future/flatten.rs: -------------------------------------------------------------------------------- 1 | use pin_project_lite::pin_project; 2 | use std::future::Future; 3 | use std::pin::Pin; 4 | 5 | use crate::future::IntoFuture; 6 | use crate::task::{ready, Context, Poll}; 7 | 8 | pin_project! { 9 | #[doc(hidden)] 10 | #[allow(missing_debug_implementations)] 11 | pub struct FlattenFuture { 12 | #[pin] 13 | state: State, 14 | } 15 | } 16 | 17 | pin_project! { 18 | #[project = StateProj] 19 | #[derive(Debug)] 20 | enum State { 21 | First { 22 | #[pin] 23 | fut1: Fut1, 24 | }, 25 | Second { 26 | #[pin] 27 | fut2: Fut2, 28 | }, 29 | Empty, 30 | } 31 | } 32 | 33 | impl FlattenFuture { 34 | pub(crate) fn new(fut1: Fut1) -> FlattenFuture { 35 | FlattenFuture { 36 | state: State::First { fut1 }, 37 | } 38 | } 39 | } 40 | 41 | impl Future for FlattenFuture::Future> 42 | where 43 | Fut1: Future, 44 | Fut1::Output: IntoFuture, 45 | { 46 | type Output = ::Output; 47 | 48 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 49 | let mut state = self.project().state; 50 | loop { 51 | match state.as_mut().project() { 52 | StateProj::First { fut1 } => { 53 | let fut2 = ready!(fut1.poll(cx)).into_future(); 54 | state.set(State::Second { fut2 }); 55 | } 56 | StateProj::Second { fut2 } => { 57 | let v = ready!(fut2.poll(cx)); 58 | state.set(State::Empty); 59 | return Poll::Ready(v); 60 | } 61 | StateProj::Empty => panic!("polled a completed future"), 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/future/future/join.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | 3 | use crate::future::MaybeDone; 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::task::{Context, Poll}; 7 | use std::future::Future; 8 | 9 | pin_project! { 10 | #[allow(missing_docs)] 11 | #[allow(missing_debug_implementations)] 12 | pub struct Join 13 | where 14 | L: Future, 15 | R: Future, 16 | { 17 | #[pin] left: MaybeDone, 18 | #[pin] right: MaybeDone, 19 | } 20 | } 21 | 22 | impl Join 23 | where 24 | L: Future, 25 | R: Future, 26 | { 27 | pub(crate) fn new(left: L, right: R) -> Self { 28 | Self { 29 | left: MaybeDone::new(left), 30 | right: MaybeDone::new(right), 31 | } 32 | } 33 | } 34 | 35 | impl Future for Join 36 | where 37 | L: Future, 38 | R: Future, 39 | { 40 | type Output = (L::Output, R::Output); 41 | 42 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 43 | let this = self.project(); 44 | 45 | let mut left = this.left; 46 | let mut right = this.right; 47 | 48 | let is_left_ready = Future::poll(Pin::new(&mut left), cx).is_ready(); 49 | if is_left_ready && right.as_ref().output().is_some() { 50 | return Poll::Ready((left.take().unwrap(), right.take().unwrap())); 51 | } 52 | 53 | let is_right_ready = Future::poll(Pin::new(&mut right), cx).is_ready(); 54 | if is_right_ready && left.as_ref().output().is_some() { 55 | return Poll::Ready((left.take().unwrap(), right.take().unwrap())); 56 | } 57 | 58 | Poll::Pending 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/future/future/race.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | use std::pin::Pin; 3 | 4 | use crate::future::MaybeDone; 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::task::{Context, Poll}; 8 | 9 | pin_project! { 10 | #[allow(missing_docs)] 11 | #[allow(missing_debug_implementations)] 12 | pub struct Race 13 | where 14 | L: Future, 15 | R: Future 16 | { 17 | #[pin] left: MaybeDone, 18 | #[pin] right: MaybeDone, 19 | } 20 | } 21 | 22 | impl Race 23 | where 24 | L: Future, 25 | R: Future, 26 | { 27 | pub(crate) fn new(left: L, right: R) -> Self { 28 | Self { 29 | left: MaybeDone::new(left), 30 | right: MaybeDone::new(right), 31 | } 32 | } 33 | } 34 | 35 | impl Future for Race 36 | where 37 | L: Future, 38 | R: Future, 39 | { 40 | type Output = L::Output; 41 | 42 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 43 | let this = self.project(); 44 | 45 | let mut left = this.left; 46 | if Future::poll(Pin::new(&mut left), cx).is_ready() { 47 | return Poll::Ready(left.take().unwrap()); 48 | } 49 | 50 | let mut right = this.right; 51 | if Future::poll(Pin::new(&mut right), cx).is_ready() { 52 | return Poll::Ready(right.take().unwrap()); 53 | } 54 | 55 | Poll::Pending 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/future/into_future.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | 3 | /// Convert a type into a `Future`. 4 | /// 5 | /// # Examples 6 | /// 7 | /// ``` 8 | /// use async_std::future::{Future, IntoFuture}; 9 | /// use async_std::io; 10 | /// use async_std::pin::Pin; 11 | /// 12 | /// struct Client; 13 | /// 14 | /// impl Client { 15 | /// pub async fn send(self) -> io::Result<()> { 16 | /// // Send a request 17 | /// Ok(()) 18 | /// } 19 | /// } 20 | /// 21 | /// impl IntoFuture for Client { 22 | /// type Output = io::Result<()>; 23 | /// 24 | /// type Future = Pin>>; 25 | /// 26 | /// fn into_future(self) -> Self::Future { 27 | /// Box::pin(async { 28 | /// self.send().await 29 | /// }) 30 | /// } 31 | /// } 32 | /// ``` 33 | #[cfg(feature = "unstable")] 34 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 35 | pub trait IntoFuture { 36 | /// The type of value produced on completion. 37 | type Output; 38 | 39 | /// Which kind of future are we turning this into? 40 | type Future: Future; 41 | 42 | /// Create a future from a value 43 | fn into_future(self) -> Self::Future; 44 | } 45 | 46 | impl IntoFuture for T { 47 | type Output = T::Output; 48 | type Future = T; 49 | 50 | fn into_future(self) -> Self::Future { 51 | self 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/future/pending.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | use std::marker::PhantomData; 3 | use std::pin::Pin; 4 | 5 | use crate::task::{Context, Poll}; 6 | 7 | /// Never resolves to a value. 8 | /// 9 | /// # Examples 10 | /// 11 | /// ``` 12 | /// # async_std::task::block_on(async { 13 | /// # 14 | /// use std::time::Duration; 15 | /// 16 | /// use async_std::future; 17 | /// use async_std::io; 18 | /// 19 | /// let dur = Duration::from_secs(1); 20 | /// let fut = future::pending(); 21 | /// 22 | /// let res: io::Result<()> = io::timeout(dur, fut).await; 23 | /// assert!(res.is_err()); 24 | /// # 25 | /// # }) 26 | /// ``` 27 | pub async fn pending() -> T { 28 | let fut = Pending { 29 | _marker: PhantomData, 30 | }; 31 | fut.await 32 | } 33 | 34 | struct Pending { 35 | _marker: PhantomData, 36 | } 37 | 38 | impl Future for Pending { 39 | type Output = T; 40 | 41 | fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { 42 | Poll::Pending 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/future/poll_fn.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use crate::task::{Context, Poll}; 5 | 6 | /// Creates a new future wrapping around a function returning [`Poll`]. 7 | /// 8 | /// Polling the returned future delegates to the wrapped function. 9 | /// 10 | /// # Examples 11 | /// 12 | /// ``` 13 | /// # async_std::task::block_on(async { 14 | /// # 15 | /// use async_std::future; 16 | /// use async_std::task::{Context, Poll}; 17 | /// 18 | /// fn poll_greeting(_: &mut Context<'_>) -> Poll { 19 | /// Poll::Ready("hello world".to_string()) 20 | /// } 21 | /// 22 | /// assert_eq!(future::poll_fn(poll_greeting).await, "hello world"); 23 | /// # 24 | /// # }) 25 | /// ``` 26 | pub async fn poll_fn(f: F) -> T 27 | where 28 | F: FnMut(&mut Context<'_>) -> Poll, 29 | { 30 | let fut = PollFn { f }; 31 | fut.await 32 | } 33 | 34 | struct PollFn { 35 | f: F, 36 | } 37 | 38 | impl Unpin for PollFn {} 39 | 40 | impl Future for PollFn 41 | where 42 | F: FnMut(&mut Context<'_>) -> Poll, 43 | { 44 | type Output = T; 45 | 46 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 47 | (&mut self.f)(cx) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/future/ready.rs: -------------------------------------------------------------------------------- 1 | /// Resolves to the provided value. 2 | /// 3 | /// This function is an async version of [`std::convert::identity`]. 4 | /// 5 | /// [`std::convert::identity`]: https://doc.rust-lang.org/std/convert/fn.identity.html 6 | /// 7 | /// # Examples 8 | /// 9 | /// ``` 10 | /// # async_std::task::block_on(async { 11 | /// # 12 | /// use async_std::future; 13 | /// 14 | /// assert_eq!(future::ready(10).await, 10); 15 | /// # 16 | /// # }) 17 | /// ``` 18 | pub async fn ready(val: T) -> T { 19 | val 20 | } 21 | -------------------------------------------------------------------------------- /src/io/buf_read/read_line.rs: -------------------------------------------------------------------------------- 1 | use std::mem; 2 | use std::pin::Pin; 3 | use std::str; 4 | use std::future::Future; 5 | 6 | use super::read_until_internal; 7 | use crate::io::{self, BufRead}; 8 | use crate::task::{Context, Poll}; 9 | 10 | #[doc(hidden)] 11 | #[allow(missing_debug_implementations)] 12 | pub struct ReadLineFuture<'a, T: Unpin + ?Sized> { 13 | pub(crate) reader: &'a mut T, 14 | pub(crate) buf: &'a mut String, 15 | pub(crate) bytes: Vec, 16 | pub(crate) read: usize, 17 | } 18 | 19 | impl Future for ReadLineFuture<'_, T> { 20 | type Output = io::Result; 21 | 22 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 23 | let Self { 24 | reader, 25 | buf, 26 | bytes, 27 | read, 28 | } = &mut *self; 29 | let reader = Pin::new(reader); 30 | 31 | let ret = futures_core::ready!(read_until_internal(reader, cx, b'\n', bytes, read)); 32 | if str::from_utf8(&bytes).is_err() { 33 | Poll::Ready(ret.and_then(|_| { 34 | Err(io::Error::new( 35 | io::ErrorKind::InvalidData, 36 | "stream did not contain valid UTF-8", 37 | )) 38 | })) 39 | } else { 40 | #[allow(clippy::debug_assert_with_mut_call)] 41 | { 42 | debug_assert!(buf.is_empty()); 43 | debug_assert_eq!(*read, 0); 44 | } 45 | 46 | // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. 47 | mem::swap(unsafe { buf.as_mut_vec() }, bytes); 48 | Poll::Ready(ret) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/io/buf_read/read_until.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use super::read_until_internal; 5 | use crate::io::{self, BufRead}; 6 | use crate::task::{Context, Poll}; 7 | 8 | #[doc(hidden)] 9 | #[allow(missing_debug_implementations)] 10 | pub struct ReadUntilFuture<'a, T: Unpin + ?Sized> { 11 | pub(crate) reader: &'a mut T, 12 | pub(crate) byte: u8, 13 | pub(crate) buf: &'a mut Vec, 14 | pub(crate) read: usize, 15 | } 16 | 17 | impl Future for ReadUntilFuture<'_, T> { 18 | type Output = io::Result; 19 | 20 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 21 | let Self { 22 | reader, 23 | byte, 24 | buf, 25 | read, 26 | } = &mut *self; 27 | read_until_internal(Pin::new(reader), cx, *byte, buf, read) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/io/buf_read/split.rs: -------------------------------------------------------------------------------- 1 | use std::mem; 2 | use std::pin::Pin; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use super::read_until_internal; 7 | use crate::io::{self, BufRead}; 8 | use crate::stream::Stream; 9 | use crate::task::{Context, Poll}; 10 | 11 | pin_project! { 12 | /// A stream over the contents of an instance of [`BufRead`] split on a particular byte. 13 | /// 14 | /// This stream is created by the [`split`] method on types that implement [`BufRead`]. 15 | /// 16 | /// This type is an async version of [`std::io::Split`]. 17 | /// 18 | /// [`split`]: trait.BufRead.html#method.lines 19 | /// [`BufRead`]: trait.BufRead.html 20 | /// [`std::io::Split`]: https://doc.rust-lang.org/std/io/struct.Split.html 21 | #[derive(Debug)] 22 | pub struct Split { 23 | #[pin] 24 | pub(crate) reader: R, 25 | pub(crate) buf: Vec, 26 | pub(crate) read: usize, 27 | pub(crate) delim: u8, 28 | } 29 | } 30 | 31 | impl Stream for Split { 32 | type Item = io::Result>; 33 | 34 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 35 | let this = self.project(); 36 | let n = futures_core::ready!(read_until_internal( 37 | this.reader, 38 | cx, 39 | *this.delim, 40 | this.buf, 41 | this.read 42 | ))?; 43 | if n == 0 && this.buf.is_empty() { 44 | return Poll::Ready(None); 45 | } 46 | if this.buf[this.buf.len() - 1] == *this.delim { 47 | this.buf.pop(); 48 | } 49 | Poll::Ready(Some(Ok(mem::replace(this.buf, vec![])))) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/io/empty.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::pin::Pin; 3 | 4 | use crate::io::{self, BufRead, Read}; 5 | use crate::task::{Context, Poll}; 6 | 7 | /// Creates a reader that contains no data. 8 | /// 9 | /// # Examples 10 | /// 11 | /// ```rust 12 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 13 | /// # 14 | /// use async_std::io; 15 | /// use async_std::prelude::*; 16 | /// 17 | /// let mut buf = Vec::new(); 18 | /// let mut reader = io::empty(); 19 | /// reader.read_to_end(&mut buf).await?; 20 | /// 21 | /// assert!(buf.is_empty()); 22 | /// # 23 | /// # Ok(()) }) } 24 | /// ``` 25 | pub fn empty() -> Empty { 26 | Empty { _private: () } 27 | } 28 | 29 | /// A reader that contains no data. 30 | /// 31 | /// This reader is created by the [`empty`] function. See its 32 | /// documentation for more. 33 | /// 34 | /// [`empty`]: fn.empty.html 35 | pub struct Empty { 36 | _private: (), 37 | } 38 | 39 | impl fmt::Debug for Empty { 40 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 41 | f.pad("Empty { .. }") 42 | } 43 | } 44 | 45 | impl Read for Empty { 46 | #[inline] 47 | fn poll_read( 48 | self: Pin<&mut Self>, 49 | _: &mut Context<'_>, 50 | _: &mut [u8], 51 | ) -> Poll> { 52 | Poll::Ready(Ok(0)) 53 | } 54 | } 55 | 56 | impl BufRead for Empty { 57 | #[inline] 58 | fn poll_fill_buf<'a>( 59 | self: Pin<&'a mut Self>, 60 | _: &mut Context<'_>, 61 | ) -> Poll> { 62 | Poll::Ready(Ok(&[])) 63 | } 64 | 65 | #[inline] 66 | fn consume(self: Pin<&mut Self>, _: usize) {} 67 | } 68 | -------------------------------------------------------------------------------- /src/io/prelude.rs: -------------------------------------------------------------------------------- 1 | //! The async I/O prelude. 2 | //! 3 | //! The purpose of this module is to alleviate imports of many common I/O traits 4 | //! by adding a glob import to the top of I/O heavy modules: 5 | //! 6 | //! ``` 7 | //! # #![allow(unused_imports)] 8 | //! use async_std::io::prelude::*; 9 | //! ``` 10 | 11 | #[doc(no_inline)] 12 | pub use crate::io::BufRead; 13 | #[doc(no_inline)] 14 | pub use crate::io::Read; 15 | #[doc(no_inline)] 16 | pub use crate::io::Seek; 17 | #[doc(no_inline)] 18 | pub use crate::io::Write; 19 | 20 | #[doc(inline)] 21 | pub use crate::io::buf_read::BufReadExt; 22 | #[doc(inline)] 23 | pub use crate::io::read::ReadExt; 24 | #[doc(inline)] 25 | pub use crate::io::seek::SeekExt; 26 | #[doc(inline)] 27 | pub use crate::io::write::WriteExt; 28 | -------------------------------------------------------------------------------- /src/io/read/bytes.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | 3 | use crate::io::{self, Read}; 4 | use crate::stream::stream::Stream; 5 | use crate::task::{Context, Poll}; 6 | 7 | /// A stream over `u8` values of a reader. 8 | /// 9 | /// This struct is generally created by calling [`bytes`] on a reader. 10 | /// Please see the documentation of [`bytes`] for more details. 11 | /// 12 | /// [`bytes`]: trait.Read.html#method.bytes 13 | #[derive(Debug)] 14 | pub struct Bytes { 15 | pub(crate) inner: T, 16 | } 17 | 18 | impl Stream for Bytes { 19 | type Item = io::Result; 20 | 21 | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 22 | let mut byte = 0; 23 | 24 | let rd = Pin::new(&mut self.inner); 25 | 26 | match futures_core::ready!(rd.poll_read(cx, std::slice::from_mut(&mut byte))) { 27 | Ok(0) => Poll::Ready(None), 28 | Ok(..) => Poll::Ready(Some(Ok(byte))), 29 | Err(ref e) if e.kind() == io::ErrorKind::Interrupted => Poll::Pending, 30 | Err(e) => Poll::Ready(Some(Err(e))), 31 | } 32 | } 33 | } 34 | 35 | #[cfg(all(test, feature = "default", not(target_arch = "wasm32")))] 36 | mod tests { 37 | use crate::io; 38 | use crate::prelude::*; 39 | use crate::task; 40 | 41 | #[test] 42 | fn test_bytes_basics() -> std::io::Result<()> { 43 | task::block_on(async move { 44 | let raw: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8]; 45 | let source: io::Cursor> = io::Cursor::new(raw.clone()); 46 | 47 | let mut s = source.bytes(); 48 | 49 | // TODO(@dignifiedquire): Use collect, once it is stable. 50 | let mut result = Vec::new(); 51 | while let Some(byte) = s.next().await { 52 | result.push(byte?); 53 | } 54 | 55 | assert_eq!(result, raw); 56 | 57 | Ok(()) 58 | }) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/io/read/read.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use crate::io::{self, Read}; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct ReadFuture<'a, T: Unpin + ?Sized> { 10 | pub(crate) reader: &'a mut T, 11 | pub(crate) buf: &'a mut [u8], 12 | } 13 | 14 | impl Future for ReadFuture<'_, T> { 15 | type Output = io::Result; 16 | 17 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 18 | let Self { reader, buf } = &mut *self; 19 | Pin::new(reader).poll_read(cx, buf) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/io/read/read_exact.rs: -------------------------------------------------------------------------------- 1 | use std::mem; 2 | use std::pin::Pin; 3 | use std::future::Future; 4 | 5 | use crate::io::{self, Read}; 6 | use crate::task::{Context, Poll}; 7 | 8 | #[doc(hidden)] 9 | #[allow(missing_debug_implementations)] 10 | pub struct ReadExactFuture<'a, T: Unpin + ?Sized> { 11 | pub(crate) reader: &'a mut T, 12 | pub(crate) buf: &'a mut [u8], 13 | } 14 | 15 | impl Future for ReadExactFuture<'_, T> { 16 | type Output = io::Result<()>; 17 | 18 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 19 | let Self { reader, buf } = &mut *self; 20 | 21 | while !buf.is_empty() { 22 | let n = futures_core::ready!(Pin::new(&mut *reader).poll_read(cx, buf))?; 23 | let (_, rest) = mem::replace(buf, &mut []).split_at_mut(n); 24 | *buf = rest; 25 | 26 | if n == 0 { 27 | return Poll::Ready(Err(io::ErrorKind::UnexpectedEof.into())); 28 | } 29 | } 30 | 31 | Poll::Ready(Ok(())) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/io/read/read_to_string.rs: -------------------------------------------------------------------------------- 1 | use std::mem; 2 | use std::pin::Pin; 3 | use std::str; 4 | use std::future::Future; 5 | 6 | use super::read_to_end_internal; 7 | use crate::io::{self, Read}; 8 | use crate::task::{Context, Poll}; 9 | 10 | #[doc(hidden)] 11 | #[allow(missing_debug_implementations)] 12 | pub struct ReadToStringFuture<'a, T: Unpin + ?Sized> { 13 | pub(crate) reader: &'a mut T, 14 | pub(crate) buf: &'a mut String, 15 | pub(crate) bytes: Vec, 16 | pub(crate) start_len: usize, 17 | } 18 | 19 | impl Future for ReadToStringFuture<'_, T> { 20 | type Output = io::Result; 21 | 22 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 23 | let Self { 24 | reader, 25 | buf, 26 | bytes, 27 | start_len, 28 | } = &mut *self; 29 | let reader = Pin::new(reader); 30 | 31 | let ret = futures_core::ready!(read_to_end_internal(reader, cx, bytes, *start_len)); 32 | if str::from_utf8(&bytes).is_err() { 33 | Poll::Ready(ret.and_then(|_| { 34 | Err(io::Error::new( 35 | io::ErrorKind::InvalidData, 36 | "stream did not contain valid UTF-8", 37 | )) 38 | })) 39 | } else { 40 | #[allow(clippy::debug_assert_with_mut_call)] 41 | { 42 | debug_assert!(buf.is_empty()); 43 | } 44 | 45 | // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. 46 | mem::swap(unsafe { buf.as_mut_vec() }, bytes); 47 | Poll::Ready(ret) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/io/read/read_vectored.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use crate::io::{self, IoSliceMut, Read}; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct ReadVectoredFuture<'a, T: Unpin + ?Sized> { 10 | pub(crate) reader: &'a mut T, 11 | pub(crate) bufs: &'a mut [IoSliceMut<'a>], 12 | } 13 | 14 | impl Future for ReadVectoredFuture<'_, T> { 15 | type Output = io::Result; 16 | 17 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 18 | let Self { reader, bufs } = &mut *self; 19 | Pin::new(reader).poll_read_vectored(cx, bufs) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/io/repeat.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::pin::Pin; 3 | 4 | use crate::io::{self, Read}; 5 | use crate::task::{Context, Poll}; 6 | 7 | /// Creates an instance of a reader that infinitely repeats one byte. 8 | /// 9 | /// All reads from this reader will succeed by filling the specified buffer with the given byte. 10 | /// 11 | /// ## Examples 12 | /// 13 | /// ```rust 14 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 15 | /// # 16 | /// use async_std::io; 17 | /// use async_std::prelude::*; 18 | /// 19 | /// let mut buffer = [0; 3]; 20 | /// io::repeat(0b101).read_exact(&mut buffer).await?; 21 | /// 22 | /// assert_eq!(buffer, [0b101, 0b101, 0b101]); 23 | /// # 24 | /// # Ok(()) }) } 25 | /// ``` 26 | pub fn repeat(byte: u8) -> Repeat { 27 | Repeat { byte } 28 | } 29 | 30 | /// A reader which yields one byte over and over and over and over and over and... 31 | /// 32 | /// This reader is created by the [`repeat`] function. See its 33 | /// documentation for more. 34 | /// 35 | /// [`repeat`]: fn.repeat.html 36 | pub struct Repeat { 37 | byte: u8, 38 | } 39 | 40 | impl fmt::Debug for Repeat { 41 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 42 | f.pad("Empty { .. }") 43 | } 44 | } 45 | 46 | impl Read for Repeat { 47 | #[inline] 48 | fn poll_read( 49 | self: Pin<&mut Self>, 50 | _: &mut Context<'_>, 51 | buf: &mut [u8], 52 | ) -> Poll> { 53 | for b in &mut *buf { 54 | *b = self.byte; 55 | } 56 | Poll::Ready(Ok(buf.len())) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/io/seek/mod.rs: -------------------------------------------------------------------------------- 1 | mod seek; 2 | 3 | use seek::SeekFuture; 4 | 5 | use crate::io::SeekFrom; 6 | 7 | pub use futures_io::AsyncSeek as Seek; 8 | 9 | #[doc = r#" 10 | Extension methods for [`Seek`]. 11 | 12 | [`Seek`]: ../trait.Seek.html 13 | "#] 14 | pub trait SeekExt: Seek { 15 | #[doc = r#" 16 | Seeks to a new position in a byte stream. 17 | 18 | Returns the new position in the byte stream. 19 | 20 | A seek beyond the end of stream is allowed, but behavior is defined by the 21 | implementation. 22 | 23 | # Examples 24 | 25 | ```no_run 26 | # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 27 | # 28 | use async_std::fs::File; 29 | use async_std::io::SeekFrom; 30 | use async_std::prelude::*; 31 | 32 | let mut file = File::open("a.txt").await?; 33 | 34 | let file_len = file.seek(SeekFrom::End(0)).await?; 35 | # 36 | # Ok(()) }) } 37 | ``` 38 | "#] 39 | fn seek( 40 | &mut self, 41 | pos: SeekFrom, 42 | ) -> SeekFuture<'_, Self> 43 | where 44 | Self: Unpin, 45 | { 46 | SeekFuture { seeker: self, pos } 47 | } 48 | } 49 | 50 | impl SeekExt for T {} 51 | -------------------------------------------------------------------------------- /src/io/seek/seek.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use crate::io::{self, Seek, SeekFrom}; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct SeekFuture<'a, T: Unpin + ?Sized> { 10 | pub(crate) seeker: &'a mut T, 11 | pub(crate) pos: SeekFrom, 12 | } 13 | 14 | impl Future for SeekFuture<'_, T> { 15 | type Output = io::Result; 16 | 17 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 18 | let pos = self.pos; 19 | Pin::new(&mut *self.seeker).poll_seek(cx, pos) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/io/sink.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::pin::Pin; 3 | 4 | use crate::io::{self, Write}; 5 | use crate::task::{Context, Poll}; 6 | 7 | /// Creates a writer that consumes and drops all data. 8 | /// 9 | /// # Examples 10 | /// 11 | /// ```rust 12 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { 13 | /// # 14 | /// use async_std::io; 15 | /// use async_std::prelude::*; 16 | /// 17 | /// let mut writer = io::sink(); 18 | /// writer.write(b"hello world").await?; 19 | /// # 20 | /// # Ok(()) }) } 21 | /// ``` 22 | pub fn sink() -> Sink { 23 | Sink { _private: () } 24 | } 25 | 26 | /// A writer that consumes and drops all data. 27 | /// 28 | /// This writer is constructed by the [`sink`] function. See its documentation 29 | /// for more. 30 | /// 31 | /// [`sink`]: fn.sink.html 32 | pub struct Sink { 33 | _private: (), 34 | } 35 | 36 | impl fmt::Debug for Sink { 37 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 38 | f.pad("Sink { .. }") 39 | } 40 | } 41 | 42 | impl Write for Sink { 43 | #[inline] 44 | fn poll_write( 45 | self: Pin<&mut Self>, 46 | _: &mut Context<'_>, 47 | buf: &[u8], 48 | ) -> Poll> { 49 | Poll::Ready(Ok(buf.len())) 50 | } 51 | 52 | #[inline] 53 | fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 54 | Poll::Ready(Ok(())) 55 | } 56 | 57 | #[inline] 58 | fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 59 | Poll::Ready(Ok(())) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/io/stdio.rs: -------------------------------------------------------------------------------- 1 | //! Internal types for stdio. 2 | //! 3 | //! This module is a port of `libstd/io/stdio.rs`,and contains internal types for `print`/`eprint`. 4 | 5 | use crate::io::{stderr, stdout}; 6 | use crate::prelude::*; 7 | use std::fmt; 8 | 9 | #[doc(hidden)] 10 | pub async fn _print(args: fmt::Arguments<'_>) { 11 | if let Err(e) = stdout().write_fmt(args).await { 12 | panic!("failed printing to stdout: {}", e); 13 | } 14 | } 15 | 16 | #[doc(hidden)] 17 | pub async fn _eprint(args: fmt::Arguments<'_>) { 18 | if let Err(e) = stderr().write_fmt(args).await { 19 | panic!("failed printing to stderr: {}", e); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/io/utils.rs: -------------------------------------------------------------------------------- 1 | use crate::utils::Context; 2 | 3 | use std::{error::Error as StdError, fmt, io}; 4 | 5 | /// Wrap `std::io::Error` with additional message 6 | /// 7 | /// Keeps the original error kind and stores the original I/O error as `source`. 8 | impl Context for Result { 9 | fn context(self, message: impl Fn() -> String) -> Self { 10 | self.map_err(|e| VerboseError::wrap(e, message())) 11 | } 12 | } 13 | 14 | #[derive(Debug)] 15 | pub(crate) struct VerboseError { 16 | source: io::Error, 17 | message: String, 18 | } 19 | 20 | impl VerboseError { 21 | pub(crate) fn wrap(source: io::Error, message: impl Into) -> io::Error { 22 | io::Error::new( 23 | source.kind(), 24 | VerboseError { 25 | source, 26 | message: message.into(), 27 | }, 28 | ) 29 | } 30 | } 31 | 32 | impl fmt::Display for VerboseError { 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | write!(f, "{}", self.message) 35 | } 36 | } 37 | 38 | impl StdError for VerboseError { 39 | fn source(&self) -> Option<&(dyn StdError + 'static)> { 40 | Some(&self.source) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/io/write/flush.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use crate::io::{self, Write}; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct FlushFuture<'a, T: Unpin + ?Sized> { 10 | pub(crate) writer: &'a mut T, 11 | } 12 | 13 | impl Future for FlushFuture<'_, T> { 14 | type Output = io::Result<()>; 15 | 16 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 17 | Pin::new(&mut *self.writer).poll_flush(cx) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/io/write/write.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use crate::io::{self, Write}; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct WriteFuture<'a, T: Unpin + ?Sized> { 10 | pub(crate) writer: &'a mut T, 11 | pub(crate) buf: &'a [u8], 12 | } 13 | 14 | impl Future for WriteFuture<'_, T> { 15 | type Output = io::Result; 16 | 17 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 18 | let buf = self.buf; 19 | Pin::new(&mut *self.writer).poll_write(cx, buf) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/io/write/write_all.rs: -------------------------------------------------------------------------------- 1 | use std::mem; 2 | use std::pin::Pin; 3 | use std::future::Future; 4 | 5 | use crate::io::{self, Write}; 6 | use crate::task::{Context, Poll}; 7 | 8 | #[doc(hidden)] 9 | #[allow(missing_debug_implementations)] 10 | pub struct WriteAllFuture<'a, T: Unpin + ?Sized> { 11 | pub(crate) writer: &'a mut T, 12 | pub(crate) buf: &'a [u8], 13 | } 14 | 15 | impl Future for WriteAllFuture<'_, T> { 16 | type Output = io::Result<()>; 17 | 18 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 19 | let Self { writer, buf } = &mut *self; 20 | 21 | while !buf.is_empty() { 22 | let n = futures_core::ready!(Pin::new(&mut **writer).poll_write(cx, buf))?; 23 | let (_, rest) = mem::replace(buf, &[]).split_at(n); 24 | *buf = rest; 25 | 26 | if n == 0 { 27 | return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); 28 | } 29 | } 30 | 31 | Poll::Ready(Ok(())) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/io/write/write_fmt.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use crate::io::{self, Write}; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | #[must_use] 10 | pub struct WriteFmtFuture<'a, T: Unpin + ?Sized> { 11 | pub(crate) writer: &'a mut T, 12 | pub(crate) res: Option>>, 13 | pub(crate) buffer: Option>, 14 | pub(crate) amt: usize, 15 | } 16 | 17 | impl Future for WriteFmtFuture<'_, T> { 18 | type Output = io::Result<()>; 19 | 20 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 21 | // Process the internal Result the first time we run. 22 | if self.buffer.is_none() { 23 | match self.res.take().unwrap() { 24 | Err(err) => return Poll::Ready(Err(err)), 25 | Ok(buffer) => self.buffer = Some(buffer), 26 | }; 27 | } 28 | 29 | // Get the types from the future. 30 | let Self { 31 | writer, 32 | amt, 33 | buffer, 34 | .. 35 | } = &mut *self; 36 | let buffer = buffer.as_mut().unwrap(); 37 | 38 | // Copy the data from the buffer into the writer until it's done. 39 | loop { 40 | if *amt == buffer.len() { 41 | futures_core::ready!(Pin::new(&mut **writer).poll_flush(cx))?; 42 | return Poll::Ready(Ok(())); 43 | } 44 | let i = futures_core::ready!(Pin::new(&mut **writer).poll_write(cx, &buffer[*amt..]))?; 45 | if i == 0 { 46 | return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); 47 | } 48 | *amt += i; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/io/write/write_vectored.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::future::Future; 3 | 4 | use crate::io::{self, IoSlice, Write}; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct WriteVectoredFuture<'a, T: Unpin + ?Sized> { 10 | pub(crate) writer: &'a mut T, 11 | pub(crate) bufs: &'a [IoSlice<'a>], 12 | } 13 | 14 | impl Future for WriteVectoredFuture<'_, T> { 15 | type Output = io::Result; 16 | 17 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 18 | let bufs = self.bufs; 19 | Pin::new(&mut *self.writer).poll_write_vectored(cx, bufs) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/net/tcp/mod.rs: -------------------------------------------------------------------------------- 1 | pub use listener::{Incoming, TcpListener}; 2 | pub use stream::TcpStream; 3 | 4 | mod listener; 5 | mod stream; 6 | -------------------------------------------------------------------------------- /src/option/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | 3 | use crate::prelude::*; 4 | use crate::stream::{FromStream, IntoStream}; 5 | use std::convert::identity; 6 | 7 | impl FromStream> for Option 8 | where 9 | V: FromStream, 10 | { 11 | /// Takes each element in the stream: if it is `None`, no further 12 | /// elements are taken, and `None` is returned. Should no `None` 13 | /// occur, a container with the values of each `Option` is returned. 14 | #[inline] 15 | fn from_stream<'a, S: IntoStream> + 'a>( 16 | stream: S, 17 | ) -> Pin + 'a + Send>> 18 | where 19 | ::IntoStream: Send, 20 | { 21 | let stream = stream.into_stream(); 22 | 23 | Box::pin(async move { 24 | // Using `take_while` here because it is able to stop the stream early 25 | // if a failure occurs 26 | let mut found_none = false; 27 | let out: V = stream 28 | .take_while(|elem| { 29 | elem.is_some() || { 30 | found_none = true; 31 | // Stop processing the stream on `None` 32 | false 33 | } 34 | }) 35 | .filter_map(identity) 36 | .collect() 37 | .await; 38 | 39 | if found_none { None } else { Some(out) } 40 | }) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/option/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust core optional value type 2 | //! 3 | //! This module provides the `Option` type for returning and 4 | //! propagating optional values. 5 | 6 | mod from_stream; 7 | 8 | #[allow(unused)] 9 | #[doc(inline)] 10 | pub use std::option::Option; 11 | 12 | cfg_unstable! { 13 | mod product; 14 | mod sum; 15 | } 16 | -------------------------------------------------------------------------------- /src/os/mod.rs: -------------------------------------------------------------------------------- 1 | //! OS-specific extensions. 2 | 3 | cfg_unix! { 4 | pub mod unix; 5 | } 6 | 7 | cfg_windows! { 8 | pub mod windows; 9 | } 10 | -------------------------------------------------------------------------------- /src/os/unix/mod.rs: -------------------------------------------------------------------------------- 1 | //! Platform-specific extensions for Unix platforms. 2 | 3 | cfg_std! { 4 | pub mod io; 5 | } 6 | 7 | cfg_default! { 8 | pub mod fs; 9 | pub mod net; 10 | } 11 | 12 | #[cfg(all(feature = "unstable", feature = "std"))] 13 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 14 | #[doc(inline)] 15 | pub use async_process::unix as process; 16 | -------------------------------------------------------------------------------- /src/os/windows/mod.rs: -------------------------------------------------------------------------------- 1 | //! Platform-specific extensions for Windows. 2 | 3 | cfg_std! { 4 | pub mod io; 5 | } 6 | 7 | cfg_unstable! { 8 | #[cfg(feature = "default")] 9 | pub mod fs; 10 | #[cfg(feature = "std")] 11 | #[cfg(windows)] 12 | pub use async_process::windows as process; 13 | } 14 | -------------------------------------------------------------------------------- /src/path/ancestors.rs: -------------------------------------------------------------------------------- 1 | use std::iter::FusedIterator; 2 | 3 | use crate::path::Path; 4 | 5 | /// An iterator over [`Path`] and its ancestors. 6 | /// 7 | /// This `struct` is created by the [`ancestors`] method on [`Path`]. 8 | /// See its documentation for more. 9 | /// 10 | /// # Examples 11 | /// 12 | /// ``` 13 | /// use async_std::path::Path; 14 | /// 15 | /// let path = Path::new("/foo/bar"); 16 | /// 17 | /// for ancestor in path.ancestors() { 18 | /// println!("{}", ancestor.display()); 19 | /// } 20 | /// ``` 21 | /// 22 | /// [`ancestors`]: struct.Path.html#method.ancestors 23 | /// [`Path`]: struct.Path.html 24 | #[derive(Copy, Clone, Debug)] 25 | pub struct Ancestors<'a> { 26 | pub(crate) next: Option<&'a Path>, 27 | } 28 | 29 | impl<'a> Iterator for Ancestors<'a> { 30 | type Item = &'a Path; 31 | 32 | fn next(&mut self) -> Option { 33 | let next = self.next; 34 | self.next = next.and_then(Path::parent); 35 | next 36 | } 37 | } 38 | 39 | impl FusedIterator for Ancestors<'_> {} 40 | -------------------------------------------------------------------------------- /src/pin/mod.rs: -------------------------------------------------------------------------------- 1 | //! Types that pin data to its location in memory. 2 | //! 3 | //! For more documentation see [`std::pin`](https://doc.rust-lang.org/std/pin/index.html). 4 | 5 | #[doc(inline)] 6 | pub use std::pin::Pin; 7 | -------------------------------------------------------------------------------- /src/prelude.rs: -------------------------------------------------------------------------------- 1 | //! The async prelude. 2 | //! 3 | //! The prelude re-exports most commonly used traits and macros from this crate. 4 | //! 5 | //! # Examples 6 | //! 7 | //! Import the prelude with: 8 | //! 9 | //! ``` 10 | //! # #[allow(unused_imports)] 11 | //! use async_std::prelude::*; 12 | //! ``` 13 | 14 | cfg_std! { 15 | #[doc(no_inline)] 16 | pub use std::future::Future; 17 | #[doc(no_inline)] 18 | pub use crate::stream::Stream; 19 | 20 | #[doc(inline)] 21 | pub use crate::future::future::FutureExt; 22 | #[doc(inline)] 23 | pub use crate::stream::stream::StreamExt; 24 | #[doc(no_inline)] 25 | pub use crate::io::BufRead as _; 26 | #[doc(no_inline)] 27 | pub use crate::io::Read as _; 28 | #[doc(no_inline)] 29 | pub use crate::io::Seek as _; 30 | #[doc(no_inline)] 31 | pub use crate::io::Write as _; 32 | 33 | #[doc(no_inline)] 34 | pub use crate::io::prelude::BufReadExt as _; 35 | #[doc(no_inline)] 36 | pub use crate::io::prelude::ReadExt as _; 37 | #[doc(no_inline)] 38 | pub use crate::io::prelude::SeekExt as _; 39 | #[doc(no_inline)] 40 | pub use crate::io::prelude::WriteExt as _; 41 | } 42 | 43 | cfg_default! { 44 | #[doc(no_inline)] 45 | pub use crate::task_local; 46 | } 47 | 48 | cfg_unstable! { 49 | #[doc(no_inline)] 50 | pub use crate::stream::DoubleEndedStream; 51 | #[doc(no_inline)] 52 | pub use crate::stream::ExactSizeStream; 53 | } 54 | -------------------------------------------------------------------------------- /src/process.rs: -------------------------------------------------------------------------------- 1 | //! A module for working with processes. 2 | //! 3 | //! This module is mostly concerned with spawning and interacting with child processes, but it also 4 | //! provides abort and exit for terminating the current process. 5 | //! 6 | //! This is an async version of [`std::process`]. 7 | //! 8 | //! [`std::process`]: https://doc.rust-lang.org/std/process/index.html 9 | 10 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 11 | #[doc(inline)] 12 | pub use async_process::ExitStatus; 13 | 14 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 15 | #[doc(inline)] 16 | pub use async_process::Output; 17 | 18 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 19 | #[doc(inline)] 20 | pub use async_process::Stdio; 21 | 22 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 23 | #[doc(inline)] 24 | pub use async_process::Child; 25 | 26 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 27 | #[doc(inline)] 28 | pub use async_process::ChildStderr; 29 | 30 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 31 | #[doc(inline)] 32 | pub use async_process::ChildStdin; 33 | 34 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 35 | #[doc(inline)] 36 | pub use async_process::ChildStdout; 37 | 38 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 39 | #[doc(inline)] 40 | pub use async_process::Command; 41 | 42 | // Re-export functions. 43 | pub use std::process::{abort, exit, id}; 44 | -------------------------------------------------------------------------------- /src/result/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust core error handling type 2 | //! 3 | //! This module provides the `Result` type for returning and 4 | //! propagating errors. 5 | 6 | mod from_stream; 7 | 8 | #[allow(unused)] 9 | #[doc(inline)] 10 | pub use std::result::Result; 11 | 12 | cfg_unstable! { 13 | mod product; 14 | mod sum; 15 | } 16 | -------------------------------------------------------------------------------- /src/rt/mod.rs: -------------------------------------------------------------------------------- 1 | //! The runtime. 2 | 3 | use std::env; 4 | 5 | use once_cell::sync::Lazy; 6 | 7 | /// Dummy runtime struct. 8 | pub struct Runtime {} 9 | 10 | /// The global runtime. 11 | pub static RUNTIME: Lazy = Lazy::new(|| { 12 | // Create an executor thread pool. 13 | 14 | let thread_name = env::var("ASYNC_STD_THREAD_NAME").unwrap_or_else(|_| "async-std/runtime".to_string()); 15 | async_global_executor::init_with_config(async_global_executor::GlobalExecutorConfig::default().with_env_var("ASYNC_STD_THREAD_COUNT").with_thread_name_fn(move || thread_name.clone())); 16 | 17 | Runtime {} 18 | }); 19 | -------------------------------------------------------------------------------- /src/stream/double_ended_stream/next_back.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use core::future::Future; 3 | 4 | use crate::stream::DoubleEndedStream; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct NextBackFuture<'a, T: Unpin + ?Sized> { 10 | pub(crate) stream: &'a mut T, 11 | } 12 | 13 | impl Future for NextBackFuture<'_, T> { 14 | type Output = Option; 15 | 16 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 17 | Pin::new(&mut *self.stream).poll_next_back(cx) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/stream/double_ended_stream/nth_back.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | use core::task::{Context, Poll}; 4 | 5 | use crate::stream::DoubleEndedStream; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct NthBackFuture<'a, S> { 10 | stream: &'a mut S, 11 | n: usize, 12 | } 13 | 14 | impl<'a, S> NthBackFuture<'a, S> { 15 | pub(crate) fn new(stream: &'a mut S, n: usize) -> Self { 16 | NthBackFuture { stream, n } 17 | } 18 | } 19 | 20 | impl<'a, S> Future for NthBackFuture<'a, S> 21 | where 22 | S: DoubleEndedStream + Sized + Unpin, 23 | { 24 | type Output = Option; 25 | 26 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 27 | let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next_back(cx)); 28 | match next { 29 | Some(v) => match self.n { 30 | 0 => Poll::Ready(Some(v)), 31 | _ => { 32 | self.n -= 1; 33 | cx.waker().wake_by_ref(); 34 | Poll::Pending 35 | } 36 | }, 37 | None => Poll::Ready(None), 38 | } 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/stream/double_ended_stream/rfind.rs: -------------------------------------------------------------------------------- 1 | use core::task::{Context, Poll}; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use crate::stream::DoubleEndedStream; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct RFindFuture<'a, S, P> { 10 | stream: &'a mut S, 11 | p: P, 12 | } 13 | 14 | impl<'a, S, P> RFindFuture<'a, S, P> { 15 | pub(super) fn new(stream: &'a mut S, p: P) -> Self { 16 | RFindFuture { stream, p } 17 | } 18 | } 19 | 20 | impl Unpin for RFindFuture<'_, S, P> {} 21 | 22 | impl<'a, S, P> Future for RFindFuture<'a, S, P> 23 | where 24 | S: DoubleEndedStream + Unpin + Sized, 25 | P: FnMut(&S::Item) -> bool, 26 | { 27 | type Output = Option; 28 | 29 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 30 | let item = futures_core::ready!(Pin::new(&mut *self.stream).poll_next_back(cx)); 31 | 32 | match item { 33 | Some(v) if (&mut self.p)(&v) => Poll::Ready(Some(v)), 34 | Some(_) => { 35 | cx.waker().wake_by_ref(); 36 | Poll::Pending 37 | } 38 | None => Poll::Ready(None), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/stream/double_ended_stream/rfold.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | use core::task::{Context, Poll}; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::DoubleEndedStream; 8 | 9 | pin_project! { 10 | #[doc(hidden)] 11 | #[allow(missing_debug_implementations)] 12 | pub struct RFoldFuture { 13 | #[pin] 14 | stream: S, 15 | f: F, 16 | acc: Option, 17 | } 18 | } 19 | 20 | impl RFoldFuture { 21 | pub(super) fn new(stream: S, init: B, f: F) -> Self { 22 | RFoldFuture { 23 | stream, 24 | f, 25 | acc: Some(init), 26 | } 27 | } 28 | } 29 | 30 | impl Future for RFoldFuture 31 | where 32 | S: DoubleEndedStream + Sized, 33 | F: FnMut(B, S::Item) -> B, 34 | { 35 | type Output = B; 36 | 37 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 38 | let mut this = self.project(); 39 | loop { 40 | let next = futures_core::ready!(this.stream.as_mut().poll_next_back(cx)); 41 | 42 | match next { 43 | Some(v) => { 44 | let old = this.acc.take().unwrap(); 45 | let new = (this.f)(old, v); 46 | *this.acc = Some(new); 47 | } 48 | None => return Poll::Ready(this.acc.take().unwrap()), 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/stream/double_ended_stream/try_rfold.rs: -------------------------------------------------------------------------------- 1 | use crate::future::Future; 2 | use core::pin::Pin; 3 | use crate::task::{Context, Poll}; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::DoubleEndedStream; 8 | 9 | pin_project! { 10 | #[doc(hidden)] 11 | #[allow(missing_debug_implementations)] 12 | pub struct TryRFoldFuture { 13 | #[pin] 14 | stream: S, 15 | f: F, 16 | acc: Option, 17 | } 18 | } 19 | 20 | impl TryRFoldFuture { 21 | pub(super) fn new(stream: S, init: T, f: F) -> Self { 22 | TryRFoldFuture { 23 | stream, 24 | f, 25 | acc: Some(init), 26 | } 27 | } 28 | } 29 | 30 | impl Future for TryRFoldFuture 31 | where 32 | S: DoubleEndedStream + Unpin, 33 | F: FnMut(T, S::Item) -> Result, 34 | { 35 | type Output = Result; 36 | 37 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 38 | let mut this = self.project(); 39 | loop { 40 | let next = futures_core::ready!(this.stream.as_mut().poll_next_back(cx)); 41 | 42 | match next { 43 | Some(v) => { 44 | let old = this.acc.take().unwrap(); 45 | let new = (this.f)(old, v); 46 | 47 | match new { 48 | Ok(o) => *this.acc = Some(o), 49 | Err(e) => return Poll::Ready(Err(e)), 50 | } 51 | } 52 | None => return Poll::Ready(Ok(this.acc.take().unwrap())), 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/stream/empty.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use core::pin::Pin; 3 | 4 | use crate::stream::Stream; 5 | use crate::task::{Context, Poll}; 6 | 7 | /// Creates a stream that doesn't yield any items. 8 | /// 9 | /// This `struct` is created by the [`empty`] function. See its 10 | /// documentation for more. 11 | /// 12 | /// [`empty`]: fn.empty.html 13 | /// 14 | /// # Examples 15 | /// 16 | /// ``` 17 | /// # async_std::task::block_on(async { 18 | /// # 19 | /// use async_std::prelude::*; 20 | /// use async_std::stream; 21 | /// 22 | /// let mut s = stream::empty::(); 23 | /// 24 | /// assert_eq!(s.next().await, None); 25 | /// # 26 | /// # }) 27 | /// ``` 28 | pub fn empty() -> Empty { 29 | Empty { 30 | _marker: PhantomData, 31 | } 32 | } 33 | 34 | /// A stream that doesn't yield any items. 35 | /// 36 | /// This stream is constructed by the [`empty`] function. 37 | /// 38 | /// [`empty`]: fn.empty.html 39 | #[derive(Debug)] 40 | pub struct Empty { 41 | _marker: PhantomData, 42 | } 43 | 44 | impl Stream for Empty { 45 | type Item = T; 46 | 47 | fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 48 | Poll::Ready(None) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stream/from_fn.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use crate::stream::Stream; 4 | use crate::task::{Context, Poll}; 5 | 6 | /// A stream that yields elements by calling a closure. 7 | /// 8 | /// This stream is created by the [`from_fn`] function. See its 9 | /// documentation for more. 10 | /// 11 | /// [`from_fn`]: fn.from_fn.html 12 | #[derive(Clone, Debug)] 13 | pub struct FromFn { 14 | f: F, 15 | } 16 | 17 | impl Unpin for FromFn {} 18 | 19 | /// Creates a new stream where to produce each new element a provided closure is called. 20 | /// 21 | /// This allows creating a custom stream with any behaviour without using the more verbose 22 | /// syntax of creating a dedicated type and implementing a `Stream` trait for it. 23 | /// 24 | /// # Examples 25 | /// 26 | /// ``` 27 | /// # async_std::task::block_on(async { 28 | /// # 29 | /// use async_std::prelude::*; 30 | /// use async_std::stream; 31 | /// 32 | /// let mut count = 0u8; 33 | /// let s = stream::from_fn(|| { 34 | /// count += 1; 35 | /// if count > 3 { 36 | /// None 37 | /// } else { 38 | /// Some(count) 39 | /// } 40 | /// }); 41 | /// 42 | /// pin_utils::pin_mut!(s); 43 | /// 44 | /// assert_eq!(s.next().await, Some(1)); 45 | /// assert_eq!(s.next().await, Some(2)); 46 | /// assert_eq!(s.next().await, Some(3)); 47 | /// assert_eq!(s.next().await, None); 48 | /// # 49 | /// # }) 50 | /// ``` 51 | pub fn from_fn(f: F) -> FromFn 52 | where 53 | F: FnMut() -> Option, 54 | { 55 | FromFn { f } 56 | } 57 | 58 | impl Stream for FromFn 59 | where 60 | F: FnMut() -> Option, 61 | { 62 | type Item = T; 63 | 64 | fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 65 | let item = (&mut self.f)(); 66 | Poll::Ready(item) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/stream/from_iter.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | #[cfg(feature = "unstable")] 7 | use crate::stream::double_ended_stream::DoubleEndedStream; 8 | use crate::task::{Context, Poll}; 9 | 10 | pin_project! { 11 | /// A stream that was created from iterator. 12 | /// 13 | /// This stream is created by the [`from_iter`] function. 14 | /// See it documentation for more. 15 | /// 16 | /// [`from_iter`]: fn.from_iter.html 17 | #[derive(Clone, Debug)] 18 | pub struct FromIter { 19 | iter: I, 20 | } 21 | } 22 | 23 | /// Converts an iterator into a stream. 24 | /// 25 | /// # Examples 26 | /// 27 | /// ``` 28 | /// # async_std::task::block_on(async { 29 | /// # 30 | /// use async_std::prelude::*; 31 | /// use async_std::stream; 32 | /// 33 | /// let mut s = stream::from_iter(vec![0, 1, 2, 3]); 34 | /// 35 | /// assert_eq!(s.next().await, Some(0)); 36 | /// assert_eq!(s.next().await, Some(1)); 37 | /// assert_eq!(s.next().await, Some(2)); 38 | /// assert_eq!(s.next().await, Some(3)); 39 | /// assert_eq!(s.next().await, None); 40 | /// # 41 | /// # }) 42 | /// ``` 43 | pub fn from_iter(iter: I) -> FromIter { 44 | FromIter { 45 | iter: iter.into_iter(), 46 | } 47 | } 48 | 49 | impl Stream for FromIter { 50 | type Item = I::Item; 51 | 52 | fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { 53 | Poll::Ready(self.iter.next()) 54 | } 55 | } 56 | 57 | #[cfg(feature = "unstable")] 58 | impl DoubleEndedStream for FromIter { 59 | fn poll_next_back(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { 60 | Poll::Ready(self.iter.next_back()) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/stream/fused_stream.rs: -------------------------------------------------------------------------------- 1 | use crate::stream::Stream; 2 | 3 | /// A stream that always continues to yield `None` when exhausted. 4 | /// 5 | /// Calling next on a fused stream that has returned `None` once is guaranteed 6 | /// to return [`None`] again. This trait should be implemented by all streams 7 | /// that behave this way because it allows optimizing [`Stream::fuse`]. 8 | /// 9 | /// Note: In general, you should not use `FusedStream` in generic bounds if 10 | /// you need a fused stream. Instead, you should just call [`Stream::fuse`] 11 | /// on the stream. If the stream is already fused, the additional [`Fuse`] 12 | /// wrapper will be a no-op with no performance penalty. 13 | /// 14 | /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None 15 | /// [`Stream::fuse`]: trait.Stream.html#method.fuse 16 | /// [`Fuse`]: struct.Fuse.html 17 | #[cfg(feature = "unstable")] 18 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 19 | pub trait FusedStream: Stream {} 20 | 21 | impl FusedStream for &mut S {} 22 | -------------------------------------------------------------------------------- /src/stream/into_stream.rs: -------------------------------------------------------------------------------- 1 | use crate::stream::Stream; 2 | 3 | /// Conversion into a `Stream`. 4 | /// 5 | /// By implementing `IntoIterator` for a type, you define how it will be 6 | /// converted to an iterator. This is common for types which describe a 7 | /// collection of some kind. 8 | /// 9 | /// [`from_stream`]: #tymethod.from_stream 10 | /// [`Stream`]: trait.Stream.html 11 | /// [`collect`]: trait.Stream.html#method.collect 12 | /// 13 | /// See also: [`FromStream`]. 14 | /// 15 | /// [`FromStream`]: trait.FromStream.html 16 | #[cfg(feature = "unstable")] 17 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 18 | pub trait IntoStream { 19 | /// The type of the elements being iterated over. 20 | type Item; 21 | 22 | /// Which kind of stream are we turning this into? 23 | type IntoStream: Stream; 24 | 25 | /// Creates a stream from a value. 26 | fn into_stream(self) -> Self::IntoStream; 27 | } 28 | 29 | impl IntoStream for I { 30 | type Item = I::Item; 31 | type IntoStream = I; 32 | 33 | #[inline] 34 | fn into_stream(self) -> I { 35 | self 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/stream/once.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | #[cfg(feature = "unstable")] 9 | use crate::stream::DoubleEndedStream; 10 | 11 | /// Creates a stream that yields a single item. 12 | /// 13 | /// # Examples 14 | /// 15 | /// ``` 16 | /// # async_std::task::block_on(async { 17 | /// # 18 | /// use async_std::prelude::*; 19 | /// use async_std::stream; 20 | /// 21 | /// let mut s = stream::once(7); 22 | /// 23 | /// assert_eq!(s.next().await, Some(7)); 24 | /// assert_eq!(s.next().await, None); 25 | /// # 26 | /// # }) 27 | /// ``` 28 | pub fn once(t: T) -> Once { 29 | Once { value: Some(t) } 30 | } 31 | 32 | pin_project! { 33 | /// A stream that yields a single item. 34 | /// 35 | /// This stream is created by the [`once`] function. See its 36 | /// documentation for more. 37 | /// 38 | /// [`once`]: fn.once.html 39 | #[derive(Clone, Debug)] 40 | pub struct Once { 41 | value: Option, 42 | } 43 | } 44 | 45 | impl Stream for Once { 46 | type Item = T; 47 | 48 | fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 49 | Poll::Ready(self.project().value.take()) 50 | } 51 | } 52 | 53 | #[cfg(feature = "unstable")] 54 | impl DoubleEndedStream for Once { 55 | fn poll_next_back(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { 56 | Poll::Ready(self.project().value.take()) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/stream/pending.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use core::pin::Pin; 3 | use core::task::{Context, Poll}; 4 | 5 | use crate::stream::{DoubleEndedStream, ExactSizeStream, FusedStream, Stream}; 6 | 7 | /// A stream that never returns any items. 8 | /// 9 | /// This stream is created by the [`pending`] function. See its 10 | /// documentation for more. 11 | /// 12 | /// [`pending`]: fn.pending.html 13 | #[derive(Debug)] 14 | pub struct Pending { 15 | _marker: PhantomData, 16 | } 17 | 18 | /// Creates a stream that never returns any items. 19 | /// 20 | /// The returned stream will always return `Pending` when polled. 21 | /// # Examples 22 | /// 23 | /// ``` 24 | /// # async_std::task::block_on(async { 25 | /// # 26 | /// use std::time::Duration; 27 | /// 28 | /// use async_std::prelude::*; 29 | /// use async_std::stream; 30 | /// 31 | /// let dur = Duration::from_millis(100); 32 | /// let mut s = stream::pending::<()>().timeout(dur); 33 | /// 34 | /// let item = s.next().await; 35 | /// 36 | /// assert!(item.is_some()); 37 | /// assert!(item.unwrap().is_err()); 38 | /// 39 | /// # 40 | /// # }) 41 | /// ``` 42 | pub fn pending() -> Pending { 43 | Pending { 44 | _marker: PhantomData, 45 | } 46 | } 47 | 48 | impl Stream for Pending { 49 | type Item = T; 50 | 51 | fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 52 | Poll::Pending 53 | } 54 | } 55 | 56 | impl DoubleEndedStream for Pending { 57 | fn poll_next_back(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 58 | Poll::Pending 59 | } 60 | } 61 | 62 | impl FusedStream for Pending {} 63 | 64 | impl ExactSizeStream for Pending { 65 | fn len(&self) -> usize { 66 | 0 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/stream/repeat.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use crate::stream::Stream; 4 | use crate::task::{Context, Poll}; 5 | 6 | /// Creates a stream that yields the same item repeatedly. 7 | /// 8 | /// # Examples 9 | /// 10 | /// ``` 11 | /// # async_std::task::block_on(async { 12 | /// # 13 | /// use async_std::prelude::*; 14 | /// use async_std::stream; 15 | /// 16 | /// let mut s = stream::repeat(7); 17 | /// 18 | /// assert_eq!(s.next().await, Some(7)); 19 | /// assert_eq!(s.next().await, Some(7)); 20 | /// # 21 | /// # }) 22 | /// ``` 23 | pub fn repeat(item: T) -> Repeat 24 | where 25 | T: Clone, 26 | { 27 | Repeat { item } 28 | } 29 | 30 | /// A stream that yields the same item repeatedly. 31 | /// 32 | /// This stream is created by the [`repeat`] function. See its 33 | /// documentation for more. 34 | /// 35 | /// [`repeat`]: fn.repeat.html 36 | #[derive(Clone, Debug)] 37 | pub struct Repeat { 38 | item: T, 39 | } 40 | 41 | impl Stream for Repeat { 42 | type Item = T; 43 | 44 | fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { 45 | Poll::Ready(Some(self.item.clone())) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/stream/stream/all.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use core::pin::Pin; 3 | use core::future::Future; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | #[doc(hidden)] 9 | #[allow(missing_debug_implementations)] 10 | pub struct AllFuture<'a, S, F, T> { 11 | pub(crate) stream: &'a mut S, 12 | pub(crate) f: F, 13 | pub(crate) _marker: PhantomData, 14 | } 15 | 16 | impl<'a, S, F, T> AllFuture<'a, S, F, T> { 17 | pub(crate) fn new(stream: &'a mut S, f: F) -> Self { 18 | Self { 19 | stream, 20 | f, 21 | _marker: PhantomData, 22 | } 23 | } 24 | } 25 | 26 | impl Unpin for AllFuture<'_, S, F, T> {} 27 | 28 | impl Future for AllFuture<'_, S, F, S::Item> 29 | where 30 | S: Stream + Unpin + Sized, 31 | F: FnMut(S::Item) -> bool, 32 | { 33 | type Output = bool; 34 | 35 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 36 | let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); 37 | 38 | match next { 39 | Some(v) => { 40 | let result = (&mut self.f)(v); 41 | 42 | if result { 43 | // don't forget to wake this task again to pull the next item from stream 44 | cx.waker().wake_by_ref(); 45 | Poll::Pending 46 | } else { 47 | Poll::Ready(false) 48 | } 49 | } 50 | None => Poll::Ready(true), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/stream/stream/any.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use core::pin::Pin; 3 | use core::future::Future; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | #[doc(hidden)] 9 | #[allow(missing_debug_implementations)] 10 | pub struct AnyFuture<'a, S, F, T> { 11 | pub(crate) stream: &'a mut S, 12 | pub(crate) f: F, 13 | pub(crate) _marker: PhantomData, 14 | } 15 | 16 | impl<'a, S, F, T> AnyFuture<'a, S, F, T> { 17 | pub(crate) fn new(stream: &'a mut S, f: F) -> Self { 18 | Self { 19 | stream, 20 | f, 21 | _marker: PhantomData, 22 | } 23 | } 24 | } 25 | 26 | impl Unpin for AnyFuture<'_, S, F, T> {} 27 | 28 | impl Future for AnyFuture<'_, S, F, S::Item> 29 | where 30 | S: Stream + Unpin + Sized, 31 | F: FnMut(S::Item) -> bool, 32 | { 33 | type Output = bool; 34 | 35 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 36 | let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); 37 | 38 | match next { 39 | Some(v) => { 40 | let result = (&mut self.f)(v); 41 | 42 | if result { 43 | Poll::Ready(true) 44 | } else { 45 | // don't forget to wake this task again to pull the next item from stream 46 | cx.waker().wake_by_ref(); 47 | Poll::Pending 48 | } 49 | } 50 | None => Poll::Ready(false), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/stream/stream/chain.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use super::fuse::Fuse; 6 | use crate::stream::stream::StreamExt; 7 | use crate::stream::Stream; 8 | use crate::task::{Context, Poll}; 9 | 10 | pin_project! { 11 | /// A stream that chains two streams one after another. 12 | /// 13 | /// This `struct` is created by the [`chain`] method on [`Stream`]. See its 14 | /// documentation for more. 15 | /// 16 | /// [`chain`]: trait.Stream.html#method.chain 17 | /// [`Stream`]: trait.Stream.html 18 | #[derive(Debug)] 19 | pub struct Chain { 20 | #[pin] 21 | first: Fuse, 22 | #[pin] 23 | second: Fuse, 24 | } 25 | } 26 | 27 | impl Chain { 28 | pub(super) fn new(first: S, second: U) -> Self { 29 | Self { 30 | first: first.fuse(), 31 | second: second.fuse(), 32 | } 33 | } 34 | } 35 | 36 | impl> Stream for Chain { 37 | type Item = S::Item; 38 | 39 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 40 | let mut this = self.project(); 41 | if !this.first.done { 42 | let next = futures_core::ready!(this.first.as_mut().poll_next(cx)); 43 | if let Some(next) = next { 44 | return Poll::Ready(Some(next)); 45 | } 46 | } 47 | 48 | if !this.second.done { 49 | let next = futures_core::ready!(this.second.as_mut().poll_next(cx)); 50 | if let Some(next) = next { 51 | return Poll::Ready(Some(next)); 52 | } 53 | } 54 | 55 | if this.first.done && this.second.done { 56 | return Poll::Ready(None); 57 | } 58 | 59 | Poll::Pending 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/stream/stream/cloned.rs: -------------------------------------------------------------------------------- 1 | use crate::stream::Stream; 2 | use crate::task::{Context, Poll}; 3 | use pin_project_lite::pin_project; 4 | use core::pin::Pin; 5 | 6 | pin_project! { 7 | /// A stream that clones the elements of an underlying stream. 8 | #[derive(Debug)] 9 | pub struct Cloned { 10 | #[pin] 11 | stream: S, 12 | } 13 | } 14 | 15 | impl Cloned { 16 | pub(super) fn new(stream: S) -> Self { 17 | Self { stream } 18 | } 19 | } 20 | 21 | impl<'a, S, T: 'a> Stream for Cloned 22 | where 23 | S: Stream, 24 | T: Clone, 25 | { 26 | type Item = T; 27 | 28 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 29 | let this = self.project(); 30 | let next = futures_core::ready!(this.stream.poll_next(cx)); 31 | Poll::Ready(next.cloned()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/stream/stream/copied.rs: -------------------------------------------------------------------------------- 1 | use crate::stream::Stream; 2 | use crate::task::{Context, Poll}; 3 | use pin_project_lite::pin_project; 4 | use core::pin::Pin; 5 | 6 | pin_project! { 7 | /// A stream that copies the elements of an underlying stream. 8 | #[derive(Debug)] 9 | pub struct Copied { 10 | #[pin] 11 | stream: S, 12 | } 13 | } 14 | 15 | impl Copied { 16 | pub(super) fn new(stream: S) -> Self { 17 | Self { stream } 18 | } 19 | } 20 | 21 | impl<'a, S, T: 'a> Stream for Copied 22 | where 23 | S: Stream, 24 | T: Copy, 25 | { 26 | type Item = T; 27 | 28 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 29 | let this = self.project(); 30 | let next = futures_core::ready!(this.stream.poll_next(cx)); 31 | Poll::Ready(next.copied()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/stream/stream/count.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::stream::Stream; 7 | use crate::task::{Context, Poll}; 8 | 9 | pin_project! { 10 | #[doc(hidden)] 11 | #[allow(missing_debug_implementations)] 12 | #[cfg(feature = "unstable")] 13 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 14 | pub struct CountFuture { 15 | #[pin] 16 | stream: S, 17 | count: usize, 18 | } 19 | } 20 | 21 | impl CountFuture { 22 | pub(crate) fn new(stream: S) -> Self { 23 | Self { stream, count: 0 } 24 | } 25 | } 26 | 27 | impl Future for CountFuture 28 | where 29 | S: Stream, 30 | { 31 | type Output = usize; 32 | 33 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 34 | let this = self.project(); 35 | let next = futures_core::ready!(this.stream.poll_next(cx)); 36 | 37 | match next { 38 | Some(_) => { 39 | cx.waker().wake_by_ref(); 40 | *this.count += 1; 41 | Poll::Pending 42 | } 43 | None => Poll::Ready(*this.count), 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/stream/stream/cycle.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use futures_core::ready; 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::stream::Stream; 7 | use crate::task::{Context, Poll}; 8 | 9 | pin_project! { 10 | /// A stream that will repeatedly yield the same list of elements. 11 | #[derive(Debug)] 12 | pub struct Cycle { 13 | orig: S, 14 | #[pin] 15 | source: S, 16 | } 17 | } 18 | 19 | impl Cycle 20 | where 21 | S: Stream + Clone, 22 | { 23 | pub(crate) fn new(source: S) -> Self { 24 | Self { 25 | orig: source.clone(), 26 | source, 27 | } 28 | } 29 | } 30 | 31 | impl Stream for Cycle 32 | where 33 | S: Stream + Clone, 34 | { 35 | type Item = S::Item; 36 | 37 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 38 | let mut this = self.project(); 39 | 40 | match ready!(this.source.as_mut().poll_next(cx)) { 41 | None => { 42 | this.source.set(this.orig.clone()); 43 | this.source.poll_next(cx) 44 | } 45 | item => Poll::Ready(item), 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/stream/stream/delay.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | use core::time::Duration; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::Stream; 8 | use crate::task::{Context, Poll}; 9 | use crate::utils::{timer_after, Timer}; 10 | 11 | pin_project! { 12 | #[doc(hidden)] 13 | #[allow(missing_debug_implementations)] 14 | pub struct Delay { 15 | #[pin] 16 | stream: S, 17 | #[pin] 18 | delay: Timer, 19 | delay_done: bool, 20 | } 21 | } 22 | 23 | impl Delay { 24 | pub(super) fn new(stream: S, dur: Duration) -> Self { 25 | Delay { 26 | stream, 27 | delay: timer_after(dur), 28 | delay_done: false, 29 | } 30 | } 31 | } 32 | 33 | impl Stream for Delay 34 | where 35 | S: Stream, 36 | { 37 | type Item = S::Item; 38 | 39 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 40 | let this = self.project(); 41 | 42 | if !*this.delay_done { 43 | futures_core::ready!(this.delay.poll(cx)); 44 | *this.delay_done = true; 45 | } 46 | 47 | this.stream.poll_next(cx) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/stream/stream/enumerate.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | #[derive(Debug)] 10 | pub struct Enumerate { 11 | #[pin] 12 | stream: S, 13 | i: usize, 14 | } 15 | } 16 | 17 | impl Enumerate { 18 | pub(super) fn new(stream: S) -> Self { 19 | Self { stream, i: 0 } 20 | } 21 | } 22 | 23 | impl Stream for Enumerate 24 | where 25 | S: Stream, 26 | { 27 | type Item = (usize, S::Item); 28 | 29 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 30 | let this = self.project(); 31 | let next = futures_core::ready!(this.stream.poll_next(cx)); 32 | 33 | match next { 34 | Some(v) => { 35 | let ret = (*this.i, v); 36 | *this.i += 1; 37 | Poll::Ready(Some(ret)) 38 | } 39 | None => Poll::Ready(None), 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/stream/stream/eq.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use super::fuse::Fuse; 7 | use crate::stream::stream::StreamExt; 8 | use crate::stream::Stream; 9 | use crate::task::{Context, Poll}; 10 | 11 | pin_project! { 12 | // Lexicographically compares the elements of this `Stream` with those 13 | // of another. 14 | #[doc(hidden)] 15 | #[allow(missing_debug_implementations)] 16 | pub struct EqFuture { 17 | #[pin] 18 | l: Fuse, 19 | #[pin] 20 | r: Fuse, 21 | } 22 | } 23 | 24 | impl EqFuture 25 | where 26 | L::Item: PartialEq, 27 | { 28 | pub(super) fn new(l: L, r: R) -> Self { 29 | Self { 30 | l: l.fuse(), 31 | r: r.fuse(), 32 | } 33 | } 34 | } 35 | 36 | impl Future for EqFuture 37 | where 38 | L: Stream + Sized, 39 | R: Stream + Sized, 40 | L::Item: PartialEq, 41 | { 42 | type Output = bool; 43 | 44 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 45 | let mut this = self.project(); 46 | 47 | loop { 48 | let l_val = futures_core::ready!(this.l.as_mut().poll_next(cx)); 49 | let r_val = futures_core::ready!(this.r.as_mut().poll_next(cx)); 50 | 51 | if this.l.done && this.r.done { 52 | return Poll::Ready(true); 53 | } 54 | 55 | match (l_val, r_val) { 56 | (Some(l), Some(r)) if l != r => { 57 | return Poll::Ready(false); 58 | } 59 | _ => {} 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/stream/stream/filter.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream to filter elements of another stream with a predicate. 10 | /// 11 | /// This `struct` is created by the [`filter`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`filter`]: trait.Stream.html#method.filter 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Debug)] 17 | pub struct Filter { 18 | #[pin] 19 | stream: S, 20 | predicate: P, 21 | } 22 | } 23 | 24 | impl Filter { 25 | pub(super) fn new(stream: S, predicate: P) -> Self { 26 | Self { 27 | stream, 28 | predicate, 29 | } 30 | } 31 | } 32 | 33 | impl Stream for Filter 34 | where 35 | S: Stream, 36 | P: FnMut(&S::Item) -> bool, 37 | { 38 | type Item = S::Item; 39 | 40 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 41 | let this = self.project(); 42 | let next = futures_core::ready!(this.stream.poll_next(cx)); 43 | 44 | match next { 45 | Some(v) if (this.predicate)(&v) => Poll::Ready(Some(v)), 46 | Some(_) => { 47 | cx.waker().wake_by_ref(); 48 | Poll::Pending 49 | } 50 | None => Poll::Ready(None), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/stream/stream/filter_map.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use core::task::{Context, Poll}; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::stream::Stream; 7 | 8 | pin_project! { 9 | #[derive(Debug)] 10 | pub struct FilterMap { 11 | #[pin] 12 | stream: S, 13 | f: F, 14 | } 15 | } 16 | 17 | impl FilterMap { 18 | pub(crate) fn new(stream: S, f: F) -> Self { 19 | Self { stream, f } 20 | } 21 | } 22 | 23 | impl Stream for FilterMap 24 | where 25 | S: Stream, 26 | F: FnMut(S::Item) -> Option, 27 | { 28 | type Item = B; 29 | 30 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 31 | let this = self.project(); 32 | let next = futures_core::ready!(this.stream.poll_next(cx)); 33 | match next { 34 | Some(v) => match (this.f)(v) { 35 | Some(b) => Poll::Ready(Some(b)), 36 | None => { 37 | cx.waker().wake_by_ref(); 38 | Poll::Pending 39 | } 40 | }, 41 | None => Poll::Ready(None), 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/stream/stream/find.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use crate::stream::Stream; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct FindFuture<'a, S, P> { 10 | stream: &'a mut S, 11 | p: P, 12 | } 13 | 14 | impl<'a, S, P> FindFuture<'a, S, P> { 15 | pub(super) fn new(stream: &'a mut S, p: P) -> Self { 16 | Self { stream, p } 17 | } 18 | } 19 | 20 | impl Unpin for FindFuture<'_, S, P> {} 21 | 22 | impl<'a, S, P> Future for FindFuture<'a, S, P> 23 | where 24 | S: Stream + Unpin + Sized, 25 | P: FnMut(&S::Item) -> bool, 26 | { 27 | type Output = Option; 28 | 29 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 30 | let item = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); 31 | 32 | match item { 33 | Some(v) if (&mut self.p)(&v) => Poll::Ready(Some(v)), 34 | Some(_) => { 35 | cx.waker().wake_by_ref(); 36 | Poll::Pending 37 | } 38 | None => Poll::Ready(None), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/stream/stream/find_map.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | use core::task::{Context, Poll}; 4 | 5 | use crate::stream::Stream; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct FindMapFuture<'a, S, F> { 10 | stream: &'a mut S, 11 | f: F, 12 | } 13 | 14 | impl<'a, S, F> FindMapFuture<'a, S, F> { 15 | pub(super) fn new(stream: &'a mut S, f: F) -> Self { 16 | Self { stream, f } 17 | } 18 | } 19 | 20 | impl Unpin for FindMapFuture<'_, S, F> {} 21 | 22 | impl<'a, S, B, F> Future for FindMapFuture<'a, S, F> 23 | where 24 | S: Stream + Unpin + Sized, 25 | F: FnMut(S::Item) -> Option, 26 | { 27 | type Output = Option; 28 | 29 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 30 | let item = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); 31 | 32 | match item { 33 | Some(v) => match (&mut self.f)(v) { 34 | Some(v) => Poll::Ready(Some(v)), 35 | None => { 36 | cx.waker().wake_by_ref(); 37 | Poll::Pending 38 | } 39 | }, 40 | None => Poll::Ready(None), 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/stream/stream/fold.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::stream::Stream; 7 | use crate::task::{Context, Poll}; 8 | 9 | pin_project! { 10 | #[derive(Debug)] 11 | pub struct FoldFuture { 12 | #[pin] 13 | stream: S, 14 | f: F, 15 | acc: Option, 16 | } 17 | } 18 | 19 | impl FoldFuture { 20 | pub(super) fn new(stream: S, init: B, f: F) -> Self { 21 | Self { 22 | stream, 23 | f, 24 | acc: Some(init), 25 | } 26 | } 27 | } 28 | 29 | impl Future for FoldFuture 30 | where 31 | S: Stream + Sized, 32 | F: FnMut(B, S::Item) -> B, 33 | { 34 | type Output = B; 35 | 36 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 37 | let mut this = self.project(); 38 | loop { 39 | let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); 40 | 41 | match next { 42 | Some(v) => { 43 | let old = this.acc.take().unwrap(); 44 | let new = (this.f)(old, v); 45 | *this.acc = Some(new); 46 | } 47 | None => return Poll::Ready(this.acc.take().unwrap()), 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/stream/stream/for_each.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use core::future::Future; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::stream::Stream; 7 | use crate::task::{Context, Poll}; 8 | 9 | pin_project! { 10 | #[doc(hidden)] 11 | #[allow(missing_debug_implementations)] 12 | pub struct ForEachFuture { 13 | #[pin] 14 | stream: S, 15 | f: F, 16 | } 17 | } 18 | 19 | impl ForEachFuture { 20 | pub(super) fn new(stream: S, f: F) -> Self { 21 | Self { 22 | stream, 23 | f, 24 | } 25 | } 26 | } 27 | 28 | impl Future for ForEachFuture 29 | where 30 | S: Stream + Sized, 31 | F: FnMut(S::Item), 32 | { 33 | type Output = (); 34 | 35 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 36 | let mut this = self.project(); 37 | loop { 38 | let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); 39 | 40 | match next { 41 | Some(v) => (this.f)(v), 42 | None => return Poll::Ready(()), 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/stream/stream/fuse.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream that yields `None` forever after the underlying stream yields `None` once. 10 | /// 11 | /// This `struct` is created by the [`fuse`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`fuse`]: trait.Stream.html#method.fuse 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Clone, Debug)] 17 | pub struct Fuse { 18 | #[pin] 19 | pub(crate) stream: S, 20 | pub(crate) done: bool, 21 | } 22 | } 23 | 24 | impl Fuse { 25 | pub(super) fn new(stream: S) -> Self { 26 | Self { 27 | stream, 28 | done: false, 29 | } 30 | } 31 | } 32 | 33 | impl Stream for Fuse { 34 | type Item = S::Item; 35 | 36 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 37 | let this = self.project(); 38 | if *this.done { 39 | Poll::Ready(None) 40 | } else { 41 | let next = futures_core::ready!(this.stream.poll_next(cx)); 42 | if next.is_none() { 43 | *this.done = true; 44 | } 45 | Poll::Ready(next) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/stream/stream/ge.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use super::partial_cmp::PartialCmpFuture; 8 | use crate::stream::stream::StreamExt; 9 | use crate::stream::Stream; 10 | use crate::task::{Context, Poll}; 11 | 12 | pin_project! { 13 | // Determines if the elements of this `Stream` are lexicographically 14 | // greater than or equal to those of another. 15 | #[doc(hidden)] 16 | #[allow(missing_debug_implementations)] 17 | pub struct GeFuture { 18 | #[pin] 19 | partial_cmp: PartialCmpFuture, 20 | } 21 | } 22 | 23 | impl GeFuture 24 | where 25 | L::Item: PartialOrd, 26 | { 27 | pub(super) fn new(l: L, r: R) -> Self { 28 | Self { 29 | partial_cmp: l.partial_cmp(r), 30 | } 31 | } 32 | } 33 | 34 | impl Future for GeFuture 35 | where 36 | L: Stream, 37 | R: Stream, 38 | L::Item: PartialOrd, 39 | { 40 | type Output = bool; 41 | 42 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 43 | let result = futures_core::ready!(self.project().partial_cmp.poll(cx)); 44 | 45 | match result { 46 | Some(Ordering::Greater) | Some(Ordering::Equal) => Poll::Ready(true), 47 | _ => Poll::Ready(false), 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stream/stream/gt.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use super::partial_cmp::PartialCmpFuture; 8 | use crate::stream::stream::StreamExt; 9 | use crate::stream::Stream; 10 | use crate::task::{Context, Poll}; 11 | 12 | pin_project! { 13 | // Determines if the elements of this `Stream` are lexicographically 14 | // greater than those of another. 15 | #[doc(hidden)] 16 | #[allow(missing_debug_implementations)] 17 | pub struct GtFuture { 18 | #[pin] 19 | partial_cmp: PartialCmpFuture, 20 | } 21 | } 22 | 23 | impl GtFuture 24 | where 25 | L::Item: PartialOrd, 26 | { 27 | pub(super) fn new(l: L, r: R) -> Self { 28 | Self { 29 | partial_cmp: l.partial_cmp(r), 30 | } 31 | } 32 | } 33 | 34 | impl Future for GtFuture 35 | where 36 | L: Stream + Sized, 37 | R: Stream + Sized, 38 | L::Item: PartialOrd, 39 | { 40 | type Output = bool; 41 | 42 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 43 | let result = futures_core::ready!(self.project().partial_cmp.poll(cx)); 44 | 45 | match result { 46 | Some(Ordering::Greater) => Poll::Ready(true), 47 | _ => Poll::Ready(false), 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stream/stream/inspect.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream that does something with each element of another stream. 10 | /// 11 | /// This `struct` is created by the [`inspect`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`inspect`]: trait.Stream.html#method.inspect 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Debug)] 17 | pub struct Inspect { 18 | #[pin] 19 | stream: S, 20 | f: F, 21 | } 22 | } 23 | 24 | impl Inspect { 25 | pub(super) fn new(stream: S, f: F) -> Self { 26 | Self { 27 | stream, 28 | f, 29 | } 30 | } 31 | } 32 | 33 | impl Stream for Inspect 34 | where 35 | S: Stream, 36 | F: FnMut(&S::Item), 37 | { 38 | type Item = S::Item; 39 | 40 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 41 | let mut this = self.project(); 42 | let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); 43 | 44 | Poll::Ready(next.map(|x| { 45 | (this.f)(&x); 46 | x 47 | })) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/stream/stream/last.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::stream::Stream; 7 | use crate::task::{Context, Poll}; 8 | 9 | pin_project! { 10 | #[doc(hidden)] 11 | #[allow(missing_debug_implementations)] 12 | pub struct LastFuture { 13 | #[pin] 14 | stream: S, 15 | last: Option, 16 | } 17 | } 18 | 19 | impl LastFuture { 20 | pub(crate) fn new(stream: S) -> Self { 21 | Self { stream, last: None } 22 | } 23 | } 24 | 25 | impl Future for LastFuture 26 | where 27 | S: Stream + Unpin + Sized, 28 | S::Item: Copy, 29 | { 30 | type Output = Option; 31 | 32 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 33 | let this = self.project(); 34 | let next = futures_core::ready!(this.stream.poll_next(cx)); 35 | 36 | match next { 37 | Some(new) => { 38 | cx.waker().wake_by_ref(); 39 | *this.last = Some(new); 40 | Poll::Pending 41 | } 42 | None => Poll::Ready(*this.last), 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/stream/stream/le.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use super::partial_cmp::PartialCmpFuture; 8 | use crate::stream::stream::StreamExt; 9 | use crate::stream::Stream; 10 | use crate::task::{Context, Poll}; 11 | 12 | pin_project! { 13 | /// Determines if the elements of this `Stream` are lexicographically 14 | /// less or equal to those of another. 15 | #[doc(hidden)] 16 | #[allow(missing_debug_implementations)] 17 | pub struct LeFuture { 18 | #[pin] 19 | partial_cmp: PartialCmpFuture, 20 | } 21 | } 22 | 23 | impl LeFuture 24 | where 25 | L::Item: PartialOrd, 26 | { 27 | pub(super) fn new(l: L, r: R) -> Self { 28 | Self { 29 | partial_cmp: l.partial_cmp(r), 30 | } 31 | } 32 | } 33 | 34 | impl Future for LeFuture 35 | where 36 | L: Stream + Sized, 37 | R: Stream + Sized, 38 | L::Item: PartialOrd, 39 | { 40 | type Output = bool; 41 | 42 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 43 | let result = futures_core::ready!(self.project().partial_cmp.poll(cx)); 44 | 45 | match result { 46 | Some(Ordering::Less) | Some(Ordering::Equal) => Poll::Ready(true), 47 | _ => Poll::Ready(false), 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stream/stream/lt.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use super::partial_cmp::PartialCmpFuture; 8 | use crate::stream::stream::StreamExt; 9 | use crate::stream::Stream; 10 | use crate::task::{Context, Poll}; 11 | 12 | pin_project! { 13 | // Determines if the elements of this `Stream` are lexicographically 14 | // less than those of another. 15 | #[doc(hidden)] 16 | #[allow(missing_debug_implementations)] 17 | pub struct LtFuture { 18 | #[pin] 19 | partial_cmp: PartialCmpFuture, 20 | } 21 | } 22 | 23 | impl LtFuture 24 | where 25 | L::Item: PartialOrd, 26 | { 27 | pub(super) fn new(l: L, r: R) -> Self { 28 | Self { 29 | partial_cmp: l.partial_cmp(r), 30 | } 31 | } 32 | } 33 | 34 | impl Future for LtFuture 35 | where 36 | L: Stream + Sized, 37 | R: Stream + Sized, 38 | L::Item: PartialOrd, 39 | { 40 | type Output = bool; 41 | 42 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 43 | let result = futures_core::ready!(self.project().partial_cmp.poll(cx)); 44 | 45 | match result { 46 | Some(Ordering::Less) => Poll::Ready(true), 47 | _ => Poll::Ready(false), 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stream/stream/map.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream that maps value of another stream with a function. 10 | #[derive(Debug)] 11 | pub struct Map { 12 | #[pin] 13 | stream: S, 14 | f: F, 15 | } 16 | } 17 | 18 | impl Map { 19 | pub(crate) fn new(stream: S, f: F) -> Self { 20 | Self { 21 | stream, 22 | f, 23 | } 24 | } 25 | } 26 | 27 | impl Stream for Map 28 | where 29 | S: Stream, 30 | F: FnMut(S::Item) -> B, 31 | { 32 | type Item = B; 33 | 34 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 35 | let this = self.project(); 36 | let next = futures_core::ready!(this.stream.poll_next(cx)); 37 | Poll::Ready(next.map(this.f)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/stream/stream/max.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::{Ord, Ordering}; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::Stream; 8 | use crate::task::{Context, Poll}; 9 | 10 | pin_project! { 11 | #[doc(hidden)] 12 | #[allow(missing_debug_implementations)] 13 | pub struct MaxFuture { 14 | #[pin] 15 | stream: S, 16 | max: Option, 17 | } 18 | } 19 | 20 | impl MaxFuture { 21 | pub(super) fn new(stream: S) -> Self { 22 | Self { stream, max: None } 23 | } 24 | } 25 | 26 | impl Future for MaxFuture 27 | where 28 | S: Stream, 29 | S::Item: Ord, 30 | { 31 | type Output = Option; 32 | 33 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 34 | let this = self.project(); 35 | let next = futures_core::ready!(this.stream.poll_next(cx)); 36 | 37 | match next { 38 | Some(new) => { 39 | cx.waker().wake_by_ref(); 40 | match this.max.take() { 41 | None => *this.max = Some(new), 42 | 43 | Some(old) => match new.cmp(&old) { 44 | Ordering::Greater => *this.max = Some(new), 45 | _ => *this.max = Some(old), 46 | }, 47 | } 48 | Poll::Pending 49 | } 50 | None => Poll::Ready(this.max.take()), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/stream/stream/max_by.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::pin::Pin; 3 | use core::future::Future; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::Stream; 8 | use crate::task::{Context, Poll}; 9 | 10 | pin_project! { 11 | #[doc(hidden)] 12 | #[allow(missing_debug_implementations)] 13 | pub struct MaxByFuture { 14 | #[pin] 15 | stream: S, 16 | compare: F, 17 | max: Option, 18 | } 19 | } 20 | 21 | impl MaxByFuture { 22 | pub(super) fn new(stream: S, compare: F) -> Self { 23 | Self { 24 | stream, 25 | compare, 26 | max: None, 27 | } 28 | } 29 | } 30 | 31 | impl Future for MaxByFuture 32 | where 33 | S: Stream, 34 | F: FnMut(&S::Item, &S::Item) -> Ordering, 35 | { 36 | type Output = Option; 37 | 38 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 39 | let this = self.project(); 40 | let next = futures_core::ready!(this.stream.poll_next(cx)); 41 | 42 | match next { 43 | Some(new) => { 44 | cx.waker().wake_by_ref(); 45 | match this.max.take() { 46 | None => *this.max = Some(new), 47 | Some(old) => match (this.compare)(&new, &old) { 48 | Ordering::Greater => *this.max = Some(new), 49 | _ => *this.max = Some(old), 50 | }, 51 | } 52 | Poll::Pending 53 | } 54 | None => Poll::Ready(this.max.take()), 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/stream/stream/max_by_key.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::Stream; 8 | use crate::task::{Context, Poll}; 9 | 10 | pin_project! { 11 | #[doc(hidden)] 12 | #[allow(missing_debug_implementations)] 13 | pub struct MaxByKeyFuture { 14 | #[pin] 15 | stream: S, 16 | max: Option<(T, T)>, 17 | key_by: K, 18 | } 19 | } 20 | 21 | impl MaxByKeyFuture { 22 | pub(super) fn new(stream: S, key_by: K) -> Self { 23 | Self { 24 | stream, 25 | max: None, 26 | key_by, 27 | } 28 | } 29 | } 30 | 31 | impl Future for MaxByKeyFuture 32 | where 33 | S: Stream, 34 | K: FnMut(&S::Item) -> S::Item, 35 | S::Item: Ord, 36 | { 37 | type Output = Option; 38 | 39 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 40 | fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { 41 | move |x| (f(&x), x) 42 | } 43 | 44 | let this = self.project(); 45 | let next = futures_core::ready!(this.stream.poll_next(cx)); 46 | 47 | match next { 48 | Some(new) => { 49 | let (key, value) = key(this.key_by)(new); 50 | cx.waker().wake_by_ref(); 51 | 52 | match this.max.take() { 53 | None => *this.max = Some((key, value)), 54 | 55 | Some(old) => match key.cmp(&old.0) { 56 | Ordering::Greater => *this.max = Some((key, value)), 57 | _ => *this.max = Some(old), 58 | }, 59 | } 60 | Poll::Pending 61 | } 62 | None => Poll::Ready(this.max.take().map(|max| max.1)), 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/stream/stream/min.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::{Ord, Ordering}; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::Stream; 8 | use crate::task::{Context, Poll}; 9 | 10 | pin_project! { 11 | #[doc(hidden)] 12 | #[allow(missing_debug_implementations)] 13 | pub struct MinFuture { 14 | #[pin] 15 | stream: S, 16 | min: Option, 17 | } 18 | } 19 | 20 | impl MinFuture { 21 | pub(super) fn new(stream: S) -> Self { 22 | Self { stream, min: None } 23 | } 24 | } 25 | 26 | impl Future for MinFuture 27 | where 28 | S: Stream, 29 | S::Item: Ord, 30 | { 31 | type Output = Option; 32 | 33 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 34 | let this = self.project(); 35 | let next = futures_core::ready!(this.stream.poll_next(cx)); 36 | 37 | match next { 38 | Some(new) => { 39 | cx.waker().wake_by_ref(); 40 | match this.min.take() { 41 | None => *this.min = Some(new), 42 | 43 | Some(old) => match new.cmp(&old) { 44 | Ordering::Less => *this.min = Some(new), 45 | _ => *this.min = Some(old), 46 | }, 47 | } 48 | Poll::Pending 49 | } 50 | None => Poll::Ready(this.min.take()), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/stream/stream/min_by.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::pin::Pin; 3 | use core::future::Future; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::Stream; 8 | use crate::task::{Context, Poll}; 9 | 10 | pin_project! { 11 | #[doc(hidden)] 12 | #[allow(missing_debug_implementations)] 13 | pub struct MinByFuture { 14 | #[pin] 15 | stream: S, 16 | compare: F, 17 | min: Option, 18 | } 19 | } 20 | 21 | impl MinByFuture { 22 | pub(super) fn new(stream: S, compare: F) -> Self { 23 | Self { 24 | stream, 25 | compare, 26 | min: None, 27 | } 28 | } 29 | } 30 | 31 | impl Future for MinByFuture 32 | where 33 | S: Stream + Unpin + Sized, 34 | S::Item: Copy, 35 | F: FnMut(&S::Item, &S::Item) -> Ordering, 36 | { 37 | type Output = Option; 38 | 39 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 40 | let this = self.project(); 41 | let next = futures_core::ready!(this.stream.poll_next(cx)); 42 | 43 | match next { 44 | Some(new) => { 45 | cx.waker().wake_by_ref(); 46 | match this.min.take() { 47 | None => *this.min = Some(new), 48 | Some(old) => match (this.compare)(&new, &old) { 49 | Ordering::Less => *this.min = Some(new), 50 | _ => *this.min = Some(old), 51 | }, 52 | } 53 | Poll::Pending 54 | } 55 | None => Poll::Ready(*this.min), 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/stream/stream/min_by_key.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::future::Future; 3 | use core::pin::Pin; 4 | 5 | use pin_project_lite::pin_project; 6 | 7 | use crate::stream::Stream; 8 | use crate::task::{Context, Poll}; 9 | 10 | pin_project! { 11 | #[doc(hidden)] 12 | #[allow(missing_debug_implementations)] 13 | pub struct MinByKeyFuture { 14 | #[pin] 15 | stream: S, 16 | min: Option<(T, T)>, 17 | key_by: K, 18 | } 19 | } 20 | 21 | impl MinByKeyFuture { 22 | pub(super) fn new(stream: S, key_by: K) -> Self { 23 | Self { 24 | stream, 25 | min: None, 26 | key_by, 27 | } 28 | } 29 | } 30 | 31 | impl Future for MinByKeyFuture 32 | where 33 | S: Stream, 34 | K: FnMut(&S::Item) -> S::Item, 35 | S::Item: Ord, 36 | { 37 | type Output = Option; 38 | 39 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 40 | fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { 41 | move |x| (f(&x), x) 42 | } 43 | 44 | let this = self.project(); 45 | let next = futures_core::ready!(this.stream.poll_next(cx)); 46 | 47 | match next { 48 | Some(new) => { 49 | let (key, value) = key(this.key_by)(new); 50 | cx.waker().wake_by_ref(); 51 | 52 | match this.min.take() { 53 | None => *this.min = Some((key, value)), 54 | 55 | Some(old) => match key.cmp(&old.0) { 56 | Ordering::Less => *this.min = Some((key, value)), 57 | _ => *this.min = Some(old), 58 | }, 59 | } 60 | Poll::Pending 61 | } 62 | None => Poll::Ready(this.min.take().map(|min| min.1)), 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/stream/stream/ne.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use super::fuse::Fuse; 7 | use crate::stream::stream::StreamExt; 8 | use crate::stream::Stream; 9 | use crate::task::{Context, Poll}; 10 | 11 | pin_project! { 12 | // Lexicographically compares the elements of this `Stream` with those 13 | // of another. 14 | #[doc(hidden)] 15 | #[allow(missing_debug_implementations)] 16 | pub struct NeFuture { 17 | #[pin] 18 | l: Fuse, 19 | #[pin] 20 | r: Fuse, 21 | } 22 | } 23 | 24 | impl NeFuture 25 | where 26 | L::Item: PartialEq, 27 | { 28 | pub(super) fn new(l: L, r: R) -> Self { 29 | Self { 30 | l: l.fuse(), 31 | r: r.fuse(), 32 | } 33 | } 34 | } 35 | 36 | impl Future for NeFuture 37 | where 38 | L: Stream + Sized, 39 | R: Stream + Sized, 40 | L::Item: PartialEq, 41 | { 42 | type Output = bool; 43 | 44 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 45 | let mut this = self.project(); 46 | 47 | loop { 48 | let l_val = futures_core::ready!(this.l.as_mut().poll_next(cx)); 49 | let r_val = futures_core::ready!(this.r.as_mut().poll_next(cx)); 50 | 51 | if this.l.done || this.r.done { 52 | return Poll::Ready(false); 53 | } 54 | 55 | match (l_val, r_val) { 56 | (Some(l), Some(r)) if l == r => { 57 | continue; 58 | } 59 | _ => { 60 | return Poll::Ready(true); 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/stream/stream/next.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use core::future::Future; 3 | 4 | use crate::stream::Stream; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct NextFuture<'a, T: Unpin + ?Sized> { 10 | pub(crate) stream: &'a mut T, 11 | } 12 | 13 | impl Future for NextFuture<'_, T> { 14 | type Output = Option; 15 | 16 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 17 | Pin::new(&mut *self.stream).poll_next(cx) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/stream/stream/nth.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use core::task::{Context, Poll}; 3 | use core::future::Future; 4 | 5 | use crate::stream::Stream; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct NthFuture<'a, S> { 10 | stream: &'a mut S, 11 | n: usize, 12 | } 13 | 14 | impl Unpin for NthFuture<'_, S> {} 15 | 16 | impl<'a, S> NthFuture<'a, S> { 17 | pub(crate) fn new(stream: &'a mut S, n: usize) -> Self { 18 | Self { stream, n } 19 | } 20 | } 21 | 22 | impl<'a, S> Future for NthFuture<'a, S> 23 | where 24 | S: Stream + Unpin + Sized, 25 | { 26 | type Output = Option; 27 | 28 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 29 | let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); 30 | match next { 31 | Some(v) => match self.n { 32 | 0 => Poll::Ready(Some(v)), 33 | _ => { 34 | self.n -= 1; 35 | cx.waker().wake_by_ref(); 36 | Poll::Pending 37 | } 38 | }, 39 | None => Poll::Ready(None), 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/stream/stream/partition.rs: -------------------------------------------------------------------------------- 1 | use pin_project_lite::pin_project; 2 | use core::default::Default; 3 | use core::future::Future; 4 | use core::pin::Pin; 5 | 6 | use crate::stream::Stream; 7 | use crate::task::{Context, Poll}; 8 | 9 | pin_project! { 10 | #[derive(Debug)] 11 | #[cfg(feature = "unstable")] 12 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 13 | pub struct PartitionFuture { 14 | #[pin] 15 | stream: S, 16 | f: F, 17 | res: Option<(B, B)>, 18 | } 19 | } 20 | 21 | impl PartitionFuture { 22 | pub(super) fn new(stream: S, f: F) -> Self { 23 | Self { 24 | stream, 25 | f, 26 | res: Some((B::default(), B::default())), 27 | } 28 | } 29 | } 30 | 31 | impl Future for PartitionFuture 32 | where 33 | S: Stream + Sized, 34 | F: FnMut(&S::Item) -> bool, 35 | B: Default + Extend, 36 | { 37 | type Output = (B, B); 38 | 39 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 40 | let mut this = self.project(); 41 | 42 | loop { 43 | let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); 44 | 45 | match next { 46 | Some(v) => { 47 | let res = this.res.as_mut().unwrap(); 48 | 49 | if (this.f)(&v) { 50 | res.0.extend(Some(v)) 51 | } else { 52 | res.1.extend(Some(v)) 53 | } 54 | } 55 | None => return Poll::Ready(this.res.take().unwrap()), 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/stream/stream/position.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use crate::stream::Stream; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct PositionFuture<'a, S, P> { 10 | stream: &'a mut S, 11 | predicate: P, 12 | index: usize, 13 | } 14 | 15 | impl<'a, S, P> Unpin for PositionFuture<'a, S, P> {} 16 | 17 | impl<'a, S, P> PositionFuture<'a, S, P> { 18 | pub(super) fn new(stream: &'a mut S, predicate: P) -> Self { 19 | Self { 20 | stream, 21 | predicate, 22 | index: 0, 23 | } 24 | } 25 | } 26 | 27 | impl<'a, S, P> Future for PositionFuture<'a, S, P> 28 | where 29 | S: Stream + Unpin, 30 | P: FnMut(S::Item) -> bool, 31 | { 32 | type Output = Option; 33 | 34 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 35 | let next = futures_core::ready!(Pin::new(&mut self.stream).poll_next(cx)); 36 | 37 | match next { 38 | Some(v) => { 39 | if (&mut self.predicate)(v) { 40 | Poll::Ready(Some(self.index)) 41 | } else { 42 | cx.waker().wake_by_ref(); 43 | self.index += 1; 44 | Poll::Pending 45 | } 46 | } 47 | None => Poll::Ready(None), 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stream/stream/scan.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream to maintain state while polling another stream. 10 | /// 11 | /// This `struct` is created by the [`scan`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`scan`]: trait.Stream.html#method.scan 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Debug)] 17 | pub struct Scan { 18 | #[pin] 19 | stream: S, 20 | state_f: (St, F), 21 | } 22 | } 23 | 24 | impl Scan { 25 | pub(crate) fn new(stream: S, initial_state: St, f: F) -> Self { 26 | Self { 27 | stream, 28 | state_f: (initial_state, f), 29 | } 30 | } 31 | } 32 | 33 | impl Stream for Scan 34 | where 35 | S: Stream, 36 | F: FnMut(&mut St, S::Item) -> Option, 37 | { 38 | type Item = B; 39 | 40 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 41 | let mut this = self.project(); 42 | let poll_result = this.stream.as_mut().poll_next(cx); 43 | poll_result.map(|item| { 44 | item.and_then(|item| { 45 | let (state, f) = this.state_f; 46 | f(state, item) 47 | }) 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stream/stream/skip.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | use core::task::{Context, Poll}; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::stream::Stream; 7 | 8 | pin_project! { 9 | /// A stream to skip first n elements of another stream. 10 | /// 11 | /// This `struct` is created by the [`skip`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`skip`]: trait.Stream.html#method.skip 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Debug)] 17 | pub struct Skip { 18 | #[pin] 19 | stream: S, 20 | n: usize, 21 | } 22 | } 23 | 24 | impl Skip { 25 | pub(crate) fn new(stream: S, n: usize) -> Self { 26 | Self { stream, n } 27 | } 28 | } 29 | 30 | impl Stream for Skip 31 | where 32 | S: Stream, 33 | { 34 | type Item = S::Item; 35 | 36 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 37 | let mut this = self.project(); 38 | loop { 39 | let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); 40 | 41 | match next { 42 | Some(v) => match *this.n { 43 | 0 => return Poll::Ready(Some(v)), 44 | _ => *this.n -= 1, 45 | }, 46 | None => return Poll::Ready(None), 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stream/stream/skip_while.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream to skip elements of another stream based on a predicate. 10 | /// 11 | /// This `struct` is created by the [`skip_while`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`skip_while`]: trait.Stream.html#method.skip_while 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Debug)] 17 | pub struct SkipWhile { 18 | #[pin] 19 | stream: S, 20 | predicate: Option

, 21 | } 22 | } 23 | 24 | impl SkipWhile { 25 | pub(crate) fn new(stream: S, predicate: P) -> Self { 26 | Self { 27 | stream, 28 | predicate: Some(predicate), 29 | } 30 | } 31 | } 32 | 33 | impl Stream for SkipWhile 34 | where 35 | S: Stream, 36 | P: FnMut(&S::Item) -> bool, 37 | { 38 | type Item = S::Item; 39 | 40 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 41 | let mut this = self.project(); 42 | loop { 43 | let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); 44 | 45 | match next { 46 | Some(v) => match this.predicate { 47 | Some(p) => { 48 | if !p(&v) { 49 | *this.predicate = None; 50 | return Poll::Ready(Some(v)); 51 | } 52 | } 53 | None => return Poll::Ready(Some(v)), 54 | }, 55 | None => return Poll::Ready(None), 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/stream/stream/step_by.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream that steps a given amount of elements of another stream. 10 | /// 11 | /// This `struct` is created by the [`step_by`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`step_by`]: trait.Stream.html#method.step_by 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Debug)] 17 | pub struct StepBy { 18 | #[pin] 19 | stream: S, 20 | step: usize, 21 | i: usize, 22 | } 23 | } 24 | 25 | impl StepBy { 26 | pub(crate) fn new(stream: S, step: usize) -> Self { 27 | Self { 28 | stream, 29 | step: step.checked_sub(1).unwrap(), 30 | i: 0, 31 | } 32 | } 33 | } 34 | 35 | impl Stream for StepBy 36 | where 37 | S: Stream, 38 | { 39 | type Item = S::Item; 40 | 41 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 42 | let mut this = self.project(); 43 | loop { 44 | let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); 45 | 46 | match next { 47 | Some(v) => match this.i { 48 | 0 => { 49 | *this.i = *this.step; 50 | return Poll::Ready(Some(v)); 51 | } 52 | _ => *this.i -= 1, 53 | }, 54 | None => return Poll::Ready(None), 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/stream/stream/take.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream that yields the first `n` items of another stream. 10 | /// 11 | /// This `struct` is created by the [`take`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`take`]: trait.Stream.html#method.take 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Clone, Debug)] 17 | pub struct Take { 18 | #[pin] 19 | pub(crate) stream: S, 20 | pub(crate) remaining: usize, 21 | } 22 | } 23 | 24 | impl Take { 25 | pub(super) fn new(stream: S, remaining: usize) -> Self { 26 | Self { 27 | stream, 28 | remaining, 29 | } 30 | } 31 | } 32 | 33 | impl Stream for Take { 34 | type Item = S::Item; 35 | 36 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 37 | let this = self.project(); 38 | if *this.remaining == 0 { 39 | Poll::Ready(None) 40 | } else { 41 | let next = futures_core::ready!(this.stream.poll_next(cx)); 42 | match next { 43 | Some(_) => *this.remaining -= 1, 44 | None => *this.remaining = 0, 45 | } 46 | Poll::Ready(next) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/stream/stream/take_while.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use pin_project_lite::pin_project; 4 | 5 | use crate::stream::Stream; 6 | use crate::task::{Context, Poll}; 7 | 8 | pin_project! { 9 | /// A stream that yields elements based on a predicate. 10 | /// 11 | /// This `struct` is created by the [`take_while`] method on [`Stream`]. See its 12 | /// documentation for more. 13 | /// 14 | /// [`take_while`]: trait.Stream.html#method.take_while 15 | /// [`Stream`]: trait.Stream.html 16 | #[derive(Debug)] 17 | pub struct TakeWhile { 18 | #[pin] 19 | stream: S, 20 | predicate: P, 21 | } 22 | } 23 | 24 | impl TakeWhile { 25 | pub(super) fn new(stream: S, predicate: P) -> Self { 26 | Self { 27 | stream, 28 | predicate, 29 | } 30 | } 31 | } 32 | 33 | impl Stream for TakeWhile 34 | where 35 | S: Stream, 36 | P: FnMut(&S::Item) -> bool, 37 | { 38 | type Item = S::Item; 39 | 40 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 41 | let this = self.project(); 42 | let next = futures_core::ready!(this.stream.poll_next(cx)); 43 | 44 | match next { 45 | Some(v) => { 46 | if (this.predicate)(&v) { 47 | Poll::Ready(Some(v)) 48 | } else { 49 | Poll::Ready(None) 50 | } 51 | } 52 | None => Poll::Ready(None), 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/stream/stream/try_fold.rs: -------------------------------------------------------------------------------- 1 | use core::pin::Pin; 2 | 3 | use crate::future::Future; 4 | use crate::stream::Stream; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct TryFoldFuture<'a, S, F, T> { 10 | stream: &'a mut S, 11 | f: F, 12 | acc: Option, 13 | } 14 | 15 | impl<'a, S, F, T> Unpin for TryFoldFuture<'a, S, F, T> {} 16 | 17 | impl<'a, S, F, T> TryFoldFuture<'a, S, F, T> { 18 | pub(super) fn new(stream: &'a mut S, init: T, f: F) -> Self { 19 | Self { 20 | stream, 21 | f, 22 | acc: Some(init), 23 | } 24 | } 25 | } 26 | 27 | impl<'a, S, F, T, E> Future for TryFoldFuture<'a, S, F, T> 28 | where 29 | S: Stream + Unpin, 30 | F: FnMut(T, S::Item) -> Result, 31 | { 32 | type Output = Result; 33 | 34 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 35 | loop { 36 | let next = futures_core::ready!(Pin::new(&mut self.stream).poll_next(cx)); 37 | 38 | match next { 39 | Some(v) => { 40 | let old = self.acc.take().unwrap(); 41 | let new = (&mut self.f)(old, v); 42 | 43 | match new { 44 | Ok(o) => self.acc = Some(o), 45 | Err(e) => return Poll::Ready(Err(e)), 46 | } 47 | } 48 | None => return Poll::Ready(Ok(self.acc.take().unwrap())), 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/stream/stream/try_for_each.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use crate::stream::Stream; 5 | use crate::task::{Context, Poll}; 6 | 7 | #[doc(hidden)] 8 | #[allow(missing_debug_implementations)] 9 | pub struct TryForEachFuture<'a, S, F> { 10 | stream: &'a mut S, 11 | f: F, 12 | } 13 | 14 | impl<'a, S, F> Unpin for TryForEachFuture<'a, S, F> {} 15 | 16 | impl<'a, S, F> TryForEachFuture<'a, S, F> { 17 | pub(crate) fn new(stream: &'a mut S, f: F) -> Self { 18 | Self { stream, f } 19 | } 20 | } 21 | 22 | impl<'a, S, F, E> Future for TryForEachFuture<'a, S, F> 23 | where 24 | S: Stream + Unpin, 25 | F: FnMut(S::Item) -> Result<(), E>, 26 | { 27 | type Output = Result<(), E>; 28 | 29 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 30 | loop { 31 | let item = futures_core::ready!(Pin::new(&mut self.stream).poll_next(cx)); 32 | 33 | match item { 34 | None => return Poll::Ready(Ok(())), 35 | Some(v) => { 36 | let res = (&mut self.f)(v); 37 | if let Err(e) = res { 38 | return Poll::Ready(Err(e)); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/stream/stream/unzip.rs: -------------------------------------------------------------------------------- 1 | use core::future::Future; 2 | use core::pin::Pin; 3 | 4 | use pin_project_lite::pin_project; 5 | 6 | use crate::stream::Stream; 7 | use crate::task::{Context, Poll}; 8 | 9 | pin_project! { 10 | #[derive(Clone, Debug)] 11 | #[cfg(feature = "unstable")] 12 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 13 | pub struct UnzipFuture { 14 | #[pin] 15 | stream: S, 16 | res: Option<(FromA, FromB)>, 17 | } 18 | } 19 | 20 | impl UnzipFuture 21 | where 22 | FromA: Default, 23 | FromB: Default, 24 | { 25 | pub(super) fn new(stream: S) -> Self { 26 | UnzipFuture { 27 | stream, 28 | res: Some((FromA::default(), FromB::default())), 29 | } 30 | } 31 | } 32 | 33 | impl Future for UnzipFuture 34 | where 35 | S: Stream, 36 | FromA: Default + Extend, 37 | FromB: Default + Extend, 38 | { 39 | type Output = (FromA, FromB); 40 | 41 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 42 | let mut this = self.project(); 43 | 44 | loop { 45 | let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); 46 | 47 | match next { 48 | Some((a, b)) => { 49 | let res = this.res.as_mut().unwrap(); 50 | res.0.extend(Some(a)); 51 | res.1.extend(Some(b)); 52 | } 53 | None => return Poll::Ready(this.res.take().unwrap()), 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/string/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust core string library 2 | //! 3 | //! This library provides a UTF-8 encoded, growable string. 4 | 5 | mod extend; 6 | mod from_stream; 7 | 8 | #[allow(unused)] 9 | #[doc(inline)] 10 | pub use std::string::String; 11 | -------------------------------------------------------------------------------- /src/task/block_on.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | 3 | use crate::task::Builder; 4 | 5 | /// Spawns a task and blocks the current thread on its result. 6 | /// 7 | /// Calling this function is similar to [spawning] a thread and immediately [joining] it, except an 8 | /// asynchronous task will be spawned. 9 | /// 10 | /// See also: [`task::spawn_blocking`]. 11 | /// 12 | /// [`task::spawn_blocking`]: fn.spawn_blocking.html 13 | /// 14 | /// [spawning]: https://doc.rust-lang.org/std/thread/fn.spawn.html 15 | /// [joining]: https://doc.rust-lang.org/std/thread/struct.JoinHandle.html#method.join 16 | /// 17 | /// # Examples 18 | /// 19 | /// ```no_run 20 | /// use async_std::task; 21 | /// 22 | /// task::block_on(async { 23 | /// println!("Hello, world!"); 24 | /// }) 25 | /// ``` 26 | #[cfg(not(target_os = "unknown"))] 27 | pub fn block_on(future: F) -> T 28 | where 29 | F: Future, 30 | { 31 | Builder::new().blocking(future) 32 | } 33 | 34 | /// Spawns a task and waits for it to finish. 35 | #[cfg(target_os = "unknown")] 36 | pub fn block_on(future: F) 37 | where 38 | F: Future + 'static, 39 | T: 'static, 40 | { 41 | Builder::new().local(future).unwrap(); 42 | } 43 | -------------------------------------------------------------------------------- /src/task/current.rs: -------------------------------------------------------------------------------- 1 | use crate::task::{Task, TaskLocalsWrapper}; 2 | 3 | /// Returns a handle to the current task. 4 | /// 5 | /// # Panics 6 | /// 7 | /// This function will panic if not called within the context of a task created by [`block_on`], 8 | /// [`spawn`], or [`Builder::spawn`]. 9 | /// 10 | /// [`block_on`]: fn.block_on.html 11 | /// [`spawn`]: fn.spawn.html 12 | /// [`Builder::spawn`]: struct.Builder.html#method.spawn 13 | /// 14 | /// # Examples 15 | /// 16 | /// ``` 17 | /// # async_std::task::block_on(async { 18 | /// # 19 | /// use async_std::task; 20 | /// 21 | /// println!("The name of this task is {:?}", task::current().name()); 22 | /// # 23 | /// # }) 24 | /// ``` 25 | pub fn current() -> Task { 26 | try_current().expect("`task::current()` called outside the context of a task") 27 | } 28 | 29 | /// Returns a handle to the current task if called within the context of a task created by [`block_on`], 30 | /// [`spawn`], or [`Builder::spawn`], otherwise returns `None`. 31 | /// 32 | /// [`block_on`]: fn.block_on.html 33 | /// [`spawn`]: fn.spawn.html 34 | /// [`Builder::spawn`]: struct.Builder.html#method.spawn 35 | /// 36 | /// # Examples 37 | /// 38 | /// ``` 39 | /// use async_std::task; 40 | /// 41 | /// match task::try_current() { 42 | /// Some(t) => println!("The name of this task is {:?}", t.name()), 43 | /// None => println!("Not inside a task!"), 44 | /// } 45 | /// ``` 46 | pub fn try_current() -> Option { 47 | TaskLocalsWrapper::get_current(|t| t.task().clone()) 48 | } -------------------------------------------------------------------------------- /src/task/ready.rs: -------------------------------------------------------------------------------- 1 | /// Extracts the successful type of a `Poll`. 2 | /// 3 | /// This macro bakes in propagation of `Pending` signals by returning early. 4 | pub use futures_core::ready; 5 | -------------------------------------------------------------------------------- /src/task/sleep.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use crate::future; 4 | use crate::io; 5 | 6 | /// Sleeps for the specified amount of time. 7 | /// 8 | /// This function might sleep for slightly longer than the specified duration but never less. 9 | /// 10 | /// This function is an async version of [`std::thread::sleep`]. 11 | /// 12 | /// [`std::thread::sleep`]: https://doc.rust-lang.org/std/thread/fn.sleep.html 13 | /// 14 | /// See also: [`stream::interval`]. 15 | /// 16 | /// [`stream::interval`]: ../stream/fn.interval.html 17 | /// 18 | /// # Examples 19 | /// 20 | /// ``` 21 | /// # async_std::task::block_on(async { 22 | /// # 23 | /// use std::time::Duration; 24 | /// 25 | /// use async_std::task; 26 | /// 27 | /// task::sleep(Duration::from_secs(1)).await; 28 | /// # 29 | /// # }) 30 | /// ``` 31 | pub async fn sleep(dur: Duration) { 32 | let _: io::Result<()> = io::timeout(dur, future::pending()).await; 33 | } 34 | -------------------------------------------------------------------------------- /src/task/spawn.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | 3 | use crate::task::{Builder, JoinHandle}; 4 | 5 | /// Spawns a task. 6 | /// 7 | /// This function is similar to [`std::thread::spawn`], except it spawns an asynchronous task. 8 | /// 9 | /// [`std::thread`]: https://doc.rust-lang.org/std/thread/fn.spawn.html 10 | /// 11 | /// # Examples 12 | /// 13 | /// ``` 14 | /// # async_std::task::block_on(async { 15 | /// # 16 | /// use async_std::task; 17 | /// 18 | /// let handle = task::spawn(async { 19 | /// 1 + 2 20 | /// }); 21 | /// 22 | /// assert_eq!(handle.await, 3); 23 | /// # 24 | /// # }) 25 | /// ``` 26 | pub fn spawn(future: F) -> JoinHandle 27 | where 28 | F: Future + Send + 'static, 29 | T: Send + 'static, 30 | { 31 | Builder::new().spawn(future).expect("cannot spawn task") 32 | } 33 | -------------------------------------------------------------------------------- /src/task/spawn_blocking.rs: -------------------------------------------------------------------------------- 1 | use crate::task::{self, JoinHandle}; 2 | 3 | /// Spawns a blocking task. 4 | /// 5 | /// The task will be spawned onto a thread pool specifically dedicated to blocking tasks. This 6 | /// is useful to prevent long-running synchronous operations from blocking the main futures 7 | /// executor. 8 | /// 9 | /// See also: [`task::block_on`], [`task::spawn`]. 10 | /// 11 | /// [`task::block_on`]: fn.block_on.html 12 | /// [`task::spawn`]: fn.spawn.html 13 | /// 14 | /// # Examples 15 | /// 16 | /// Basic usage: 17 | /// 18 | /// ``` 19 | /// # async_std::task::block_on(async { 20 | /// # 21 | /// use async_std::task; 22 | /// 23 | /// task::spawn_blocking(|| { 24 | /// println!("long-running task here"); 25 | /// }) 26 | /// .await; 27 | /// # 28 | /// # }) 29 | /// ``` 30 | #[inline] 31 | pub fn spawn_blocking(f: F) -> JoinHandle 32 | where 33 | F: FnOnce() -> T + Send + 'static, 34 | T: Send + 'static, 35 | { 36 | task::spawn(async_global_executor::spawn_blocking(f)) 37 | } 38 | -------------------------------------------------------------------------------- /src/task/spawn_local.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | 3 | use crate::task::{Builder, JoinHandle}; 4 | 5 | /// Spawns a task onto the thread-local executor. 6 | /// 7 | /// # Examples 8 | /// 9 | /// ``` 10 | /// # #[cfg(feature = "unstable")] 11 | /// # async_std::task::block_on(async { 12 | /// # 13 | /// use async_std::task; 14 | /// 15 | /// let handle = task::spawn_local(async { 16 | /// 1 + 2 17 | /// }); 18 | /// 19 | /// assert_eq!(handle.await, 3); 20 | /// # 21 | /// # }) 22 | /// ``` 23 | #[cfg_attr(feature = "docs", doc(cfg(unstable)))] 24 | #[inline] 25 | pub fn spawn_local(future: F) -> JoinHandle 26 | where 27 | F: Future + 'static, 28 | T: 'static, 29 | { 30 | Builder::new().local(future).expect("cannot spawn task") 31 | } 32 | -------------------------------------------------------------------------------- /src/task/task.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::sync::Arc; 3 | 4 | use crate::task::TaskId; 5 | 6 | /// A handle to a task. 7 | #[derive(Clone)] 8 | pub struct Task { 9 | /// The task ID. 10 | id: TaskId, 11 | 12 | /// The optional task name. 13 | name: Option>, 14 | } 15 | 16 | impl Task { 17 | /// Creates a new task handle. 18 | #[inline] 19 | pub(crate) fn new(name: Option>) -> Task { 20 | Task { 21 | id: TaskId::generate(), 22 | name, 23 | } 24 | } 25 | 26 | /// Gets the task's unique identifier. 27 | #[inline] 28 | pub fn id(&self) -> TaskId { 29 | self.id 30 | } 31 | 32 | /// Returns the name of this task. 33 | /// 34 | /// The name is configured by [`Builder::name`] before spawning. 35 | /// 36 | /// [`Builder::name`]: struct.Builder.html#method.name 37 | pub fn name(&self) -> Option<&str> { 38 | self.name.as_ref().map(|s| s.as_str()) 39 | } 40 | } 41 | 42 | impl fmt::Debug for Task { 43 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 44 | f.debug_struct("Task") 45 | .field("id", &self.id()) 46 | .field("name", &self.name()) 47 | .finish() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/task/task_id.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::sync::atomic::{AtomicUsize, Ordering}; 3 | 4 | /// A unique identifier for a task. 5 | /// 6 | /// # Examples 7 | /// 8 | /// ``` 9 | /// use async_std::task; 10 | /// 11 | /// task::block_on(async { 12 | /// println!("id = {:?}", task::current().id()); 13 | /// }) 14 | /// ``` 15 | #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] 16 | pub struct TaskId(pub(crate) usize); 17 | 18 | impl TaskId { 19 | /// Generates a new `TaskId`. 20 | pub(crate) fn generate() -> TaskId { 21 | // TODO: find a good version to emulate u64 atomics on 32 bit systems. 22 | static COUNTER: AtomicUsize = AtomicUsize::new(1); 23 | 24 | let id = COUNTER.fetch_add(1, Ordering::Relaxed); 25 | if id > usize::max_value() / 2 { 26 | std::process::abort(); 27 | } 28 | TaskId(id) 29 | } 30 | } 31 | 32 | impl fmt::Display for TaskId { 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | write!(f, "{}", self.0) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/task/yield_now.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | use std::pin::Pin; 3 | 4 | use crate::task::{Context, Poll}; 5 | 6 | /// Cooperatively gives up a timeslice to the task scheduler. 7 | /// 8 | /// Calling this function will move the currently executing future to the back 9 | /// of the execution queue, making room for other futures to execute. This is 10 | /// especially useful after running CPU-intensive operations inside a future. 11 | /// 12 | /// See also [`task::spawn_blocking`]. 13 | /// 14 | /// [`task::spawn_blocking`]: fn.spawn_blocking.html 15 | /// 16 | /// # Examples 17 | /// 18 | /// Basic usage: 19 | /// 20 | /// ``` 21 | /// # async_std::task::block_on(async { 22 | /// # 23 | /// use async_std::task; 24 | /// 25 | /// task::yield_now().await; 26 | /// # 27 | /// # }) 28 | /// ``` 29 | #[inline] 30 | pub async fn yield_now() { 31 | YieldNow(false).await 32 | } 33 | 34 | struct YieldNow(bool); 35 | 36 | impl Future for YieldNow { 37 | type Output = (); 38 | 39 | // The futures executor is implemented as a FIFO queue, so all this future 40 | // does is re-schedule the future back to the end of the queue, giving room 41 | // for other futures to progress. 42 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 43 | if !self.0 { 44 | self.0 = true; 45 | cx.waker().wake_by_ref(); 46 | Poll::Pending 47 | } else { 48 | Poll::Ready(()) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/unit/extend.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | 3 | use crate::prelude::*; 4 | use crate::stream::{self, IntoStream}; 5 | 6 | impl stream::Extend<()> for () { 7 | fn extend<'a, S: IntoStream + 'a>( 8 | &'a mut self, 9 | stream: S, 10 | ) -> Pin + 'a + Send>> 11 | where 12 | ::IntoStream: Send, 13 | { 14 | let stream = stream.into_stream(); 15 | 16 | Box::pin(async move { 17 | pin_utils::pin_mut!(stream); 18 | 19 | while let Some(_) = stream.next().await {} 20 | }) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/unit/from_stream.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | 3 | use crate::prelude::*; 4 | use crate::stream::{FromStream, IntoStream}; 5 | 6 | impl FromStream<()> for () { 7 | #[inline] 8 | fn from_stream<'a, S: IntoStream + 'a>( 9 | stream: S, 10 | ) -> Pin + 'a + Send>> 11 | where 12 | ::IntoStream: Send, 13 | { 14 | Box::pin(stream.into_stream().for_each(drop)) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/unit/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust primitive `()` type, sometimes called "unit" or "nil". 2 | //! 3 | //! This module provides types and implementations for working 4 | //! asynchronously with values of type `()`. 5 | 6 | mod from_stream; 7 | mod extend; 8 | -------------------------------------------------------------------------------- /src/vec/extend.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | 3 | use crate::prelude::*; 4 | use crate::stream::{self, IntoStream}; 5 | 6 | impl stream::Extend for Vec { 7 | fn extend<'a, S: IntoStream + 'a>( 8 | &'a mut self, 9 | stream: S, 10 | ) -> Pin + 'a + Send>> 11 | where 12 | ::IntoStream: Send, 13 | { 14 | let stream = stream.into_stream(); 15 | 16 | self.reserve(stream.size_hint().0); 17 | 18 | Box::pin(stream.for_each(move |item| self.push(item))) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/vec/mod.rs: -------------------------------------------------------------------------------- 1 | //! The Rust core allocation and collections library 2 | //! 3 | //! This library provides smart pointers and collections for managing 4 | //! heap-allocated values. 5 | 6 | mod extend; 7 | mod from_stream; 8 | 9 | #[allow(unused)] 10 | #[doc(inline)] 11 | pub use std::vec::Vec; 12 | -------------------------------------------------------------------------------- /tests/collect.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "unstable")] 2 | #[test] 3 | fn test_send() { 4 | use async_std::prelude::*; 5 | use async_std::{stream, task}; 6 | 7 | task::block_on(async { 8 | fn test_send_trait(_: &T) {} 9 | 10 | let stream = stream::repeat(1u8).take(10); 11 | test_send_trait(&stream); 12 | 13 | let fut = stream.collect::>(); 14 | 15 | // This line triggers a compilation error 16 | test_send_trait(&fut); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /tests/io_timeout.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use async_std::io; 4 | use async_std::task; 5 | 6 | #[test] 7 | #[should_panic(expected = "timed out")] 8 | #[cfg(not(any( 9 | target_os = "unknown", 10 | target_arch = "arm", 11 | target_arch = "mips", 12 | target_arch = "powerpc", 13 | target_arch = "powerpc64", 14 | target_arch = "x86", 15 | )))] // stdin tests fail when running through cross 16 | fn io_timeout_timedout() { 17 | task::block_on(async { 18 | io::timeout(Duration::from_secs(1), async { 19 | let stdin = io::stdin(); 20 | let mut line = String::new(); 21 | let _n = stdin.read_line(&mut line).await?; 22 | Ok(()) 23 | }) 24 | .await 25 | .unwrap(); // We should panic with a timeout error 26 | }); 27 | } 28 | 29 | #[test] 30 | #[should_panic(expected = "My custom error")] 31 | fn io_timeout_future_err() { 32 | task::block_on(async { 33 | io::timeout(Duration::from_secs(1), async { 34 | Err::<(), io::Error>(io::Error::new(io::ErrorKind::Other, "My custom error")) 35 | }) 36 | .await 37 | .unwrap(); // We should panic with our own error 38 | }); 39 | } 40 | 41 | #[test] 42 | fn io_timeout_future_ok() { 43 | task::block_on(async { 44 | io::timeout(Duration::from_secs(1), async { Ok(()) }) 45 | .await 46 | .unwrap(); // We shouldn't panic at all 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /tests/task_local.rs: -------------------------------------------------------------------------------- 1 | use std::sync::atomic::{AtomicBool, Ordering}; 2 | 3 | use async_std::task; 4 | use async_std::task_local; 5 | 6 | #[cfg(not(target_os = "unknown"))] 7 | use async_std::task::spawn; 8 | #[cfg(target_os = "unknown")] 9 | use async_std::task::spawn_local as spawn; 10 | 11 | #[cfg(target_arch = "wasm32")] 12 | wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); 13 | 14 | #[test] 15 | #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] 16 | fn drop_local() { 17 | static DROP_LOCAL: AtomicBool = AtomicBool::new(false); 18 | 19 | struct Local; 20 | 21 | impl Drop for Local { 22 | fn drop(&mut self) { 23 | DROP_LOCAL.store(true, Ordering::SeqCst); 24 | } 25 | } 26 | 27 | task_local! { 28 | static LOCAL: Local = Local; 29 | } 30 | 31 | // Spawn a task that just touches its task-local. 32 | let handle = spawn(async { 33 | LOCAL.with(|_| ()); 34 | }); 35 | let task = handle.task().clone(); 36 | 37 | // Wait for the task to finish and make sure its task-local has been dropped. 38 | task::block_on(async { 39 | handle.await; 40 | assert!(DROP_LOCAL.load(Ordering::SeqCst)); 41 | drop(task); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /tests/timeout.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use async_std::future::timeout; 4 | use async_std::task; 5 | 6 | #[cfg(target_arch = "wasm32")] 7 | wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); 8 | 9 | #[test] 10 | #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] 11 | fn timeout_future_many() { 12 | task::block_on(async { 13 | let futures = (0..10) 14 | .map(|i| { 15 | timeout(Duration::from_millis(i * 50), async move { 16 | task::sleep(Duration::from_millis(i)).await; 17 | Ok::<(), async_std::future::TimeoutError>(()) 18 | }) 19 | }) 20 | .collect::>(); 21 | 22 | for future in futures { 23 | future.await.unwrap().unwrap(); 24 | } 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /tests/udp.rs: -------------------------------------------------------------------------------- 1 | #![cfg(not(target_os = "unknown"))] 2 | 3 | use async_std::io; 4 | use async_std::net::UdpSocket; 5 | use async_std::task; 6 | 7 | const THE_MERCHANT_OF_VENICE: &[u8] = b" 8 | If you prick us, do we not bleed? 9 | If you tickle us, do we not laugh? 10 | If you poison us, do we not die? 11 | And if you wrong us, shall we not revenge? 12 | "; 13 | 14 | #[test] 15 | fn send_recv_peek() -> io::Result<()> { 16 | task::block_on(async { 17 | let socket1 = UdpSocket::bind("127.0.0.1:0").await?; 18 | let socket2 = UdpSocket::bind("127.0.0.1:0").await?; 19 | 20 | socket1.connect(socket2.local_addr()?).await?; 21 | socket2.connect(socket1.local_addr()?).await?; 22 | assert_eq!(socket1.peer_addr()?, socket2.local_addr()?); 23 | socket1.send(THE_MERCHANT_OF_VENICE).await?; 24 | 25 | let mut buf = [0u8; 1024]; 26 | let n = socket2.peek(&mut buf).await?; 27 | assert_eq!(&buf[..n], THE_MERCHANT_OF_VENICE); 28 | 29 | let n = socket2.recv(&mut buf).await?; 30 | assert_eq!(&buf[..n], THE_MERCHANT_OF_VENICE); 31 | 32 | Ok(()) 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /tests/verbose_errors.rs: -------------------------------------------------------------------------------- 1 | #![cfg(not(target_os = "unknown"))] 2 | 3 | use async_std::{fs, io, net::ToSocketAddrs, task}; 4 | 5 | #[test] 6 | fn open_file() { 7 | task::block_on(async { 8 | let non_existing_file = "/ashjudlkahasdasdsikdhajik/asdasdasdasdasdasd/fjuiklashdbflasas"; 9 | let res = fs::File::open(non_existing_file).await; 10 | match res { 11 | Ok(_) => panic!("Found file with random name: We live in a simulation"), 12 | Err(e) => assert_eq!( 13 | "could not open `/ashjudlkahasdasdsikdhajik/asdasdasdasdasdasd/fjuiklashdbflasas`", 14 | &format!("{}", e) 15 | ), 16 | } 17 | }) 18 | } 19 | 20 | #[test] 21 | fn resolve_address() { 22 | task::block_on(async { 23 | let non_existing_addr = "ashjudlkahasdasdsikdhajik.asdasdasdasdasdasd.fjuiklashdbflasas:80"; 24 | let res: Result<_, io::Error> = non_existing_addr.to_socket_addrs().await; 25 | match res { 26 | Ok(_) => panic!("Found address with random name: We live in a simulation"), 27 | Err(e) => assert_eq!( 28 | "could not resolve address `\"ashjudlkahasdasdsikdhajik.asdasdasdasdasdasd.fjuiklashdbflasas:80\"`", 29 | &format!("{}", e) 30 | ), 31 | } 32 | }) 33 | } 34 | --------------------------------------------------------------------------------