pax_global_header00006660000000000000000000000064147653740700014527gustar00rootroot0000000000000052 comment=96f564672a8588ac0516e86580c249009ad3e94f async-rs-async-std-57f61ae/000077500000000000000000000000001476537407000156115ustar00rootroot00000000000000async-rs-async-std-57f61ae/.github/000077500000000000000000000000001476537407000171515ustar00rootroot00000000000000async-rs-async-std-57f61ae/.github/CONTRIBUTING.md000066400000000000000000000001571476537407000214050ustar00rootroot00000000000000Our contribution policy can be found at [async.rs/contribute][policy]. [policy]: https://async.rs/contribute/ async-rs-async-std-57f61ae/.github/workflows/000077500000000000000000000000001476537407000212065ustar00rootroot00000000000000async-rs-async-std-57f61ae/.github/workflows/ci.yml000066400000000000000000000117351476537407000223330ustar00rootroot00000000000000name: CI on: pull_request: push: branches: - main - staging - trying env: RUSTFLAGS: -Dwarnings jobs: build_and_test: name: Build and test runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] rust: [nightly, beta, stable, 1.63] steps: - uses: actions/checkout@v3 - name: Install ${{ matrix.rust }} uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust }} override: true - name: check uses: actions-rs/cargo@v1 with: command: check args: --all --bins --tests - name: check unstable uses: actions-rs/cargo@v1 with: command: check args: --features unstable --all --bins --examples --tests - name: check wasm uses: actions-rs/cargo@v1 with: command: check target: wasm32-unknown-unknown override: true args: --features unstable --all --bins --tests - name: check bench uses: actions-rs/cargo@v1 if: matrix.rust == 'nightly' with: command: check args: --benches - name: check std only uses: actions-rs/cargo@v1 with: command: check args: --no-default-features --features std - name: check attributes uses: actions-rs/cargo@v1 with: command: check args: --features attributes - name: build unstable only uses: actions-rs/cargo@v1 with: command: build args: --no-default-features --features unstable - name: tests uses: actions-rs/cargo@v1 with: command: test args: --all --features "unstable attributes" build__with_no_std: name: Build with no-std runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: setup run: | rustup default nightly rustup target add thumbv7m-none-eabi - name: check no_std uses: actions-rs/cargo@v1 with: command: check args: --no-default-features --features alloc --target thumbv7m-none-eabi -Z avoid-dev-deps check_tokio_02_feature: name: Check tokio02 feature runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: check tokio02 uses: actions-rs/cargo@v1 with: command: check args: --all --features tokio02 check_io_safety_feature: name: Check io_safety feature runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest] steps: - uses: actions/checkout@v3 - name: check io_safety uses: actions-rs/cargo@v1 with: command: check args: --all --features io_safety cross: name: Cross compile runs-on: ubuntu-latest strategy: matrix: target: - i686-unknown-linux-gnu - powerpc-unknown-linux-gnu - powerpc64-unknown-linux-gnu # - mips-unknown-linux-gnu - arm-linux-androideabi steps: - uses: actions/checkout@v3 - name: Install nightly uses: actions-rs/toolchain@v1 with: toolchain: nightly override: true - name: Install cross run: cargo install cross - name: check run: cross check --all --target ${{ matrix.target }} - name: check unstable run: cross check --all --features unstable --target ${{ matrix.target }} - name: test run: cross test --all --features unstable --target ${{ matrix.target }} check_wasm: name: Check wasm targets runs-on: ubuntu-latest strategy: matrix: rust: [nightly, beta, stable] steps: - uses: actions/checkout@v3 - name: Install rust with wasm32-unknown-unknown uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust }} target: wasm32-unknown-unknown override: true - name: Cache cargo registry uses: actions/cache@v2 with: path: ~/.cargo/registry key: wasm32-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.toml') }} - name: check uses: actions-rs/cargo@v1 with: command: check args: --target wasm32-unknown-unknown - name: check unstable uses: actions-rs/cargo@v1 with: command: check args: --target wasm32-unknown-unknown --tests --all --features unstable check_fmt_and_docs: name: Checking fmt and docs runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: nightly override: true components: rustfmt - name: setup run: | rustup component add rustfmt test -x $HOME/.cargo/bin/mdbook || ./ci/install-mdbook.sh rustc --version - name: mdbook run: | mdbook build docs - name: fmt run: cargo fmt --all -- --check - name: Docs run: cargo doc --features docs async-rs-async-std-57f61ae/.gitignore000066400000000000000000000000361476537407000176000ustar00rootroot00000000000000/target **/*.rs.bk Cargo.lock async-rs-async-std-57f61ae/CHANGELOG.md000066400000000000000000001142001476537407000174200ustar00rootroot00000000000000# Changelog All notable changes to async-std will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://book.async.rs/overview/stability-guarantees.html). # [1.13.1] - 2025-02-21 `async-std` has officially been discontinued. We recommend that all users and libraries migrate to the excellent [`smol`](https://github.com/smol-rs/smol/) project. # [1.13.0] - 2024-09-06 ## Added - IO Safety traits implementations ## Changed - Various dependencies updates - Export `BufReadExt` and `SeekExt` from `async_std::io` # [1.12.0] - 2022-06-18 ## Added - `async_std::task::spawn_blocking` is now stabilized. We consider it a fundamental API for bridging between blocking code and async code, and we widely use it within async-std's own implementation. - Add `TryFrom` implementations to convert `TcpListener`, `TcpStream`, `UdpSocket`, `UnixDatagram`, `UnixListener`, and `UnixStream` to their synchronous equivalents, including putting them back into blocking mode. ## Changed - async-std no longer depends on `num_cpus`; it uses functionality in the standard library instead (via `async-global-executor`). - Miscellaneous documentation fixes and cleanups. # [1.11.0] - 2022-03-22 This release improves compile times by up to 55% on initial builds, and up to 75% on recompilation. Additionally we've added a few new APIs and made some tweaks. ## Added - `TcpListener::into_incoming` to convert a `TcpListener` into a stream of incoming TCP connections ## Removed - The internal `extension_trait` macro had been removed. This drastically improves compile times for `async-std`, but changes the way our documentation is rendered. This is a cosmetic change only, and all existing code should continue to work as it did before. ## Changed - Some internal code has been de-macro-ified, making for quicker compile times. - We now use the default recursion limit. ## Docs - Several docs improvements / fixes. # [1.10.0] - 2021-08-25 This release comes with an assortment of small features and fixes. ## Added - `File` now implements `Clone` so that `File`s can be passed into closures for use in `spawn_blocking`. - `File`'s contents are already wrapped in `Arc`s, so the implementation of `Clone` is straightforward. - `task::try_current()` which returns a handle to the current task if called within the context of a task created by async-std. - `async_std::io` now re-exports `WriteExt` directly. ## Fixed - `write!` now takes already written bytes into account on `File`. ## Internal - `TcpStream` now properly makes use of vectored IO. - The `net::*::Incoming` implementations now do less allocation. ## Docs - Several docs improvements / fixes. # [1.9.0] - 2021-01-15 This patch stabilizes the `async_std::channel` submodule, removes the deprecated `sync::channel` types, and introduces the `tokio1` feature. ## New Channels As part of our `1.8.0` release last month we introduced the new `async_std::channel` submodule and deprecated the unstable `async_std::sync::channel` types. You can read our full motivation for this change in the last patch notes. But the short version is that the old channels had some fundamental problems, and the `sync` submodule is a bit of a mess. This release of `async-std` promotes `async_std::channel` to stable, and fully removes the `async_std::sync::channel` types. In practice many libraries have already been upgraded to the new channels in the past month, and this will enable much of the ecosystem to switch off "unstable" versions of `async-std`. ```rust use async_std::channel; let (sender, receiver) = channel::unbounded(); assert_eq!(sender.send("Hello").await, Ok(())); assert_eq!(receiver.recv().await, Ok("Hello")); ``` ## Tokio 1.0 compat The Tokio project recently released version 1.0 of their runtime, and the async-std team would like to congratulate the Tokio team on achieving this milestone. This release of `async-std` adds the `tokio1` feature flag, enabling Tokio's TLS constructors to be initialized within the `async-std` runtime. This is in addition to the `tokio02` and `tokio03` feature flags which we were already exposing. In terms of stability it's worth noting that we will continue to provide support for the `tokio02`, `tokio03`, and `tokio1` on the current major release line of `async-std`. These flags are part of our public API, and removing compat support for older Tokio versions is considered a breaking change. ## Added - Added the `tokio1` feature ([#924](https://github.com/async-rs/async-std/pull/924)) - Stabilized the `async_std::channel` submodule ([#934](https://github.com/async-rs/async-std/pull/934)) ## Removed - Removed deprecated `sync::channel` ([#933](https://github.com/async-rs/async-std/pull/933)) ## Fixed - Fixed a typo for [sic] `FuturesExt` trait ([#930](https://github.com/async-rs/async-std/pull/930)) - Update the link to `cargo-edit` in the installation section of the docs ([#932](https://github.com/async-rs/async-std/pull/932)) - Fixed a small typo for stream ([#926](https://github.com/async-rs/async-std/pull/926)) ## Internal - Updated `rand` to 0.8 ([#923](https://github.com/async-rs/async-std/pull/923)) - Migrated `RwLock` and `Barrier` to use the `async-lock` crate internally ([#925](https://github.com/async-rs/async-std/pull/925)) - Replaced uses of deprecated the `compare_and_swap` method with `compare_exchange` ([#927](https://github.com/async-rs/async-std/pull/927)) # [1.8.0] - 2020-12-04 This patch introduces `async_std::channel`, a new submodule for our async channels implementation. `channels` have been one of async-std's most requested features, and have existed as "unstable" for the past year. We've been cautious about stabilizing channels, and this caution turned out to be warranted: we realized our channels could hang indefinitely under certain circumstances, and people ended up expressing a need for unbounded channels. So today we're introducing the new `async_std::channel` submodule which exports the `async-channel` crate, and we're marking the older unstable `async_std::sync::channel` API as "deprecated". This release includes both APIs, but we intend to stabilize `async_std::channel` and remove the older API in January. This should give dependent projects a month to upgrade, though we can extend that if it proves to be too short. The rationale for adding a new top-level `channel` submodule, rather than extending `sync` is that the `std::sync` and `async_std::sync` submodule are a bit of a mess, and the libs team [has been talking about splitting `std::sync` up]([https://github.com/rust-lang/rfcs/pull/2788#discussion_r339092478](https://github.com/rust-lang/rfcs/pull/2788#discussion_r339092478)) into separate modules. The stdlib has to guarantee it'll forever be backwards compatible, but `async-std` does not (we fully expect a 2.0 once we have async closures & traits). So we're experimenting with this change before `std` does, with the expectation that this change can serve as a data point when the libs team decides how to proceed in std. ### Added - `async_std::channel` as "unstable" #915 - `async_std::process` as "unstable" #916 ### Fixed - Fixed mentions of the `tokio03` flags in the docs #909 - Fixed a double drop issue in `StreamExt::cycle` #903 ### Internal - updated `pin-project` to `v0.2.0` # [1.7.0] - 2020-10-30 This patch adds a feature to enable compatibility with the new `tokio` 0.3.0 release, and updates internal dependencies. ## Added - Add `tokio03` feature ([#895](https://github.com/async-rs/async-std/pull/895)) ## Internal - chore: update dependencies ([#897](https://github.com/async-rs/async-std/pull/897)) # [1.6.5] - 2020-09-28 ## Fixed - Fix `TcpListener::incoming`. ([#889](https://github.com/async-rs/async-std/pull/889)) - Fix tokio compatibility flag. ([#882](https://github.com/async-rs/async-std/pull/882)) # [1.6.4] - 2020-09-16 ## Added - Added `UdpSocket::peek` and `UdpSocket::peek_from` ([#853](https://github.com/async-rs/async-std/pull/853)) ## Changed - Extracted the executor into [async-global-executor](https://github.com/async-rs/async-global-executor) ([#867](https://github.com/async-rs/async-std/pull/867)) - Updated various dependencies ## Fixed - Ensure `UnixStream::into_raw_fd` doesn't close the file descriptor ([#855](https://github.com/async-rs/async-std/issues/855)) - Fixed wasm builds and ensured better dependency management depending on the compile target ([#863](https://github.com/async-rs/async-std/pull/863)) # [1.6.3] - 2020-07-31 ## Added ## Changed - Switched from smol to individual executor parts. ([#836](https://github.com/async-rs/async-std/pull/836)) - Replaced internal `Mutex` implementation with `async-mutex`. ([#822](https://github.com/async-rs/async-std/pull/822)) ## Fixed - Added missing `Send` guards to `Stream::collect`. ([#665](https://github.com/async-rs/async-std/pull/665)) # [1.6.2] - 2020-06-19 ## Added - Add `UdpSocket::peer_addr` ([#816](https://github.com/async-rs/async-std/pull/816)) ## Changed ## Fixed - Ensure the reactor is running for sockets and timers ([#819](https://github.com/async-rs/async-std/pull/819)). - Avoid excessive polling in `flatten` and `flat_map` ([#701](https://github.com/async-rs/async-std/pull/701)) # [1.6.1] - 2020-06-11 ## Added - Added `tokio02` feature flag, to allow compatibility usage with tokio@0.2 ([#804](https://github.com/async-rs/async-std/pull/804)). ## Changed - Removed unstable `stdio` lock methods, due to their unsoundness ([#807](https://github.com/async-rs/async-std/pull/807)). ## Fixed - Fixed wrong slice index for file reading ([#802](https://github.com/async-rs/async-std/pull/802)). - Fixed recursive calls to `block_on` ([#799](https://github.com/async-rs/async-std/pull/799)) and ([#809](https://github.com/async-rs/async-std/pull/809)). - Remove `default` feature requirement for the `unstable` feature ([#806](https://github.com/async-rs/async-std/pull/806)). # [1.6.0] - 2020-05-22 See `1.6.0-beta.1` and `1.6.0-beta.2`. # [1.6.0-beta.2] - 2020-05-19 ## Added - Added an environment variable to configure the thread pool size of the runtime. ([#774](https://github.com/async-rs/async-std/pull/774)) - Implement `Clone` for `UnixStream` ([#772](https://github.com/async-rs/async-std/pull/772)) ## Changed - For `wasm`, switched underlying `Timer` implementation to [`futures-timer`](https://github.com/async-rs/futures-timer). ([#776](https://github.com/async-rs/async-std/pull/776)) ## Fixed - Use `smol::block_on` to handle drop of `File`, avoiding nested executor panic. ([#768](https://github.com/async-rs/async-std/pull/768)) # [1.6.0-beta.1] - 2020-05-07 ## Added - Added `task::spawn_local`. ([#757](https://github.com/async-rs/async-std/pull/757)) - Added out of the box support for `wasm`. ([#757](https://github.com/async-rs/async-std/pull/757)) - Added `JoinHandle::cancel` ([#757](https://github.com/async-rs/async-std/pull/757)) - Added `sync::Condvar` ([#369](https://github.com/async-rs/async-std/pull/369)) - Added `sync::Sender::try_send` and `sync::Receiver::try_recv` ([#585](https://github.com/async-rs/async-std/pull/585)) - Added `no_std` support for `task`, `future` and `stream` ([#680](https://github.com/async-rs/async-std/pull/680)) ## Changed - Switched underlying runtime to [`smol`](https://github.com/stjepang/smol/). ([#757](https://github.com/async-rs/async-std/pull/757)) - Switched implementation of `sync::Barrier` to use `sync::Condvar` like `std` does. ([#581](https://github.com/async-rs/async-std/pull/581)) ## Fixed - Allow compilation on 32 bit targets, by using `AtomicUsize` for `TaskId`. ([#756](https://github.com/async-rs/async-std/pull/756)) # [1.5.0] - 2020-02-03 [API Documentation](https://docs.rs/async-std/1.5.0/async-std) This patch includes various quality of life improvements to async-std. Including improved performance, stability, and the addition of various `Clone` impls that replace the use of `Arc` in many cases. ## Added - Added links to various ecosystem projects from the README ([#660](https://github.com/async-rs/async-std/pull/660)) - Added an example on `FromStream` for `Result` ([#643](https://github.com/async-rs/async-std/pull/643)) - Added `stream::pending` as "unstable" ([#615](https://github.com/async-rs/async-std/pull/615)) - Added an example of `stream::timeout` to document the error flow ([#675](https://github.com/async-rs/async-std/pull/675)) - Implement `Clone` for `DirEntry` ([#682](https://github.com/async-rs/async-std/pull/682)) - Implement `Clone` for `TcpStream` ([#689](https://github.com/async-rs/async-std/pull/689)) ## Changed - Removed internal comment on `stream::Interval` ([#645](https://github.com/async-rs/async-std/pull/645)) - The "unstable" feature can now be used without requiring the "default" feature ([#647](https://github.com/async-rs/async-std/pull/647)) - Removed unnecessary trait bound on `stream::FlatMap` ([#651](https://github.com/async-rs/async-std/pull/651)) - Updated the "broadcaster" dependency used by "unstable" to `1.0.0` ([#681](https://github.com/async-rs/async-std/pull/681)) - Updated `async-task` to 1.2.1 ([#676](https://github.com/async-rs/async-std/pull/676)) - `task::block_on` now parks after a single poll, improving performance in many cases ([#684](https://github.com/async-rs/async-std/pull/684)) - Improved reading flow of the "client" part of the async-std tutorial ([#550](https://github.com/async-rs/async-std/pull/550)) - Use `take_while` instead of `scan` in `impl` of `Product`, `Sum` and `FromStream` ([#667](https://github.com/async-rs/async-std/pull/667)) - `TcpStream::connect` no longer uses a thread from the threadpool, improving performance ([#687](https://github.com/async-rs/async-std/pull/687)) ## Fixed - Fixed crate documentation typo ([#655](https://github.com/async-rs/async-std/pull/655)) - Fixed documentation for `UdpSocket::recv` ([#648](https://github.com/async-rs/async-std/pull/648)) - Fixed documentation for `UdpSocket::send` ([#671](https://github.com/async-rs/async-std/pull/671)) - Fixed typo in stream documentation ([#650](https://github.com/async-rs/async-std/pull/650)) - Fixed typo on `sync::JoinHandle` documentation ([#659](https://github.com/async-rs/async-std/pull/659)) - Removed use of `std::error::Error::description` which failed CI ([#661](https://github.com/async-rs/async-std/pull/661)) - Removed the use of rustfmt's unstable `format_code_in_doc_comments` option which failed CI ([#685](https://github.com/async-rs/async-std/pull/685)) - Fixed a code typo in the `task::sleep` example ([#688](https://github.com/async-rs/async-std/pull/688)) # [1.4.0] - 2019-12-20 [API Documentation](https://docs.rs/async-std/1.4.0/async-std) This patch adds `Future::timeout`, providing a method counterpart to the `future::timeout` free function. And includes several bug fixes around missing APIs. Notably we're not shipping our new executor yet, first announced [on our blog](https://async.rs/blog/stop-worrying-about-blocking-the-new-async-std-runtime/). ## Examples ```rust use async_std::prelude::*; use async_std::future; use std::time::Duration; let fut = future::pending::<()>(); // This future will never resolve. let res = fut.timeout(Duration::from_millis(100)).await; assert!(res.is_err()); // The future timed out, returning an err. ``` ## Added - Added `Future::timeout` as "unstable" [(#600)](https://github.com/async-rs/async-std/pull/600) ## Fixes - Fixed a doc test and enabled it on CI [(#597)](https://github.com/async-rs/async-std/pull/597) - Fixed a rendering issue with the `stream` submodule documentation [(#621)](https://github.com/async-rs/async-std/pull/621) - `Write::write_fmt`'s future is now correctly marked as `#[must_use]` [(#628)](https://github.com/async-rs/async-std/pull/628) - Fixed the missing `io::Bytes` export [(#633)](https://github.com/async-rs/async-std/pull/633) - Fixed the missing `io::Chain` export [(#633)](https://github.com/async-rs/async-std/pull/633) - Fixed the missing `io::Take` export [(#633)](https://github.com/async-rs/async-std/pull/633) # [1.3.0] - 2019-12-12 [API Documentation](https://docs.rs/async-std/1.3.0/async-std) This patch introduces `Stream::delay`, more methods on `DoubleEndedStream`, and improves compile times. `Stream::delay` is a new API that's similar to [`task::sleep`](https://docs.rs/async-std/1.2.0/async_std/task/fn.sleep.html), but can be passed as part of as stream, rather than as a separate block. This is useful for examples, or when manually debugging race conditions. ## Examples ```rust let start = Instant::now(); let mut s = stream::from_iter(vec![0u8, 1]).delay(Duration::from_millis(200)); // The first time will take more than 200ms due to delay. s.next().await; assert!(start.elapsed().as_millis() >= 200); // There will be no delay after the first time. s.next().await; assert!(start.elapsed().as_millis() <= 210); ``` ## Added - Added `Stream::delay` as "unstable" [(#309)](https://github.com/async-rs/async-std/pull/309) - Added `DoubleEndedStream::next_back` as "unstable" [(#562)](https://github.com/async-rs/async-std/pull/562) - Added `DoubleEndedStream::nth_back` as "unstable" [(#562)](https://github.com/async-rs/async-std/pull/562) - Added `DoubleEndedStream::rfind` as "unstable" [(#562)](https://github.com/async-rs/async-std/pull/562) - Added `DoubleEndedStream::rfold` as "unstable" [(#562)](https://github.com/async-rs/async-std/pull/562) - Added `DoubleEndedStream::try_rfold` as "unstable" [(#562)](https://github.com/async-rs/async-std/pull/562) - `stream::Once` now implements `DoubleEndedStream` [(#562)](https://github.com/async-rs/async-std/pull/562) - `stream::FromIter` now implements `DoubleEndedStream` [(#562)](https://github.com/async-rs/async-std/pull/562) ## Changed - Removed our dependency on `async-macros`, speeding up compilation [(#610)](https://github.com/async-rs/async-std/pull/610) ## Fixes - Fixed a link in the task docs [(#598)](https://github.com/async-rs/async-std/pull/598) - Fixed the `UdpSocket::recv` example [(#603)](https://github.com/async-rs/async-std/pull/603) - Fixed a link to `task::block_on` [(#608)](https://github.com/async-rs/async-std/pull/608) - Fixed an incorrect API mention in `task::Builder` [(#612)](https://github.com/async-rs/async-std/pull/612) - Fixed leftover mentions of `futures-preview` [(#595)](https://github.com/async-rs/async-std/pull/595) - Fixed a typo in the tutorial [(#614)](https://github.com/async-rs/async-std/pull/614) - `::poll_close` now closes the write half of the stream [(#618)](https://github.com/async-rs/async-std/pull/618) # [1.2.0] - 2019-11-27 [API Documentation](https://docs.rs/async-std/1.2.0/async-std) This patch includes some minor quality-of-life improvements, introduces a new `Stream::unzip` API, and adds verbose errors to our networking types. This means if you can't connect to a socket, you'll never have to wonder again *which* address it was you couldn't connect to, instead of having to go through the motions to debug what the address was. ## Example Unzip a stream of tuples into two collections: ```rust use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![(1,2), (3,4)]); let (left, right): (Vec<_>, Vec<_>) = s.unzip().await; assert_eq!(left, [1, 3]); assert_eq!(right, [2, 4]); ``` ## Added - Added `Stream::unzip` as "unstable". - Added verbose errors to the networking types. ## Changed - Enabled CI. - `Future::join` and `Future::try_join` can now join futures with different output types. ## Fixed - Fixed the docs and `Debug` output of `BufWriter`. - Fixed a bug in `Stream::throttle` that made it consume too much CPU. # [1.1.0] - 2019-11-21 [API Documentation](https://docs.rs/async-std/1.1.0/async-std) This patch introduces a faster scheduler algorithm, `Stream::throttle`, and stabilizes `task::yield_now`. Additionally we're introducing several more stream APIs, bringing us to almost complete parity with the standard library. Furthermore our `path` submodule now returns more context in errors. So if opening a file fails, async-std will tell you *which* file was failed to open, making it easier to write and debug programs. ## Examples ```rust let start = Instant::now(); let mut s = stream::interval(Duration::from_millis(5)) .throttle(Duration::from_millis(10)) .take(2); s.next().await; assert!(start.elapsed().as_millis() >= 5); s.next().await; assert!(start.elapsed().as_millis() >= 15); s.next().await; assert!(start.elapsed().as_millis() >= 25); ``` ## Added - Added `Stream::throttle` as "unstable". - Added `Stream::count` as "unstable". - Added `Stream::max` as "unstable". - Added `Stream::successors` as "unstable". - Added `Stream::by_ref` as "unstable". - Added `Stream::partition` as "unstable". - Added contextual errors to the `path` submodule. - Added `os::windows::symlink_dir` as "unstable". - Added `os::windows::symlink_file` as "unstable". - Stabilized `task::yield_now`. ## Fixes - We now ignore seek errors when rolling back failed `read` calls on `File`. - Fixed a bug where `Stream::max_by_key` was returning the wrong result. - Fixed a bug where `Stream::min_by_key` was returning the wrong result. ## Changed - Applied various fixes to the tutorial. - Fixed an issue with Clippy. - Optimized an internal code generation macro, improving compilation speeds. - Removed an `Unpin` bound from `stream::Once`. - Removed various extra internal uses of `pin_mut!`. - Simplified `Stream::any` and `Stream::all`'s internals. - The `surf` example is now enabled again. - Tweaked some streams internals. - Updated `futures-timer` to 2.0.0, improving compilation speed. - Upgraded `async-macros` to 2.0.0. - `Stream::merge` now uses randomized ordering to reduce overall latency. - The scheduler is now more efficient by keeping a slot for the next task to run. This is similar to Go's scheduler, and Tokio's scheduler. - Fixed the documentation of the `channel` types to link back to the `channel` function. # [1.0.1] - 2019-11-12 [API Documentation](https://docs.rs/async-std/1.0.1/async-std) We were seeing a regression in our fs performance, caused by too many long-running tasks. This patch fixes that regression by being more proactive about closing down idle threads. ## Changes - Improved thread startup/shutdown algorithm in `task::spawn_blocking`. - Fixed a typo in the tutorial. # [1.0.0] - 2019-11-11 [API Documentation](https://docs.rs/async-std/1.0.0/async-std) This release marks the `1.0.0` release of async-std; a major milestone for our development. This release itself mostly includes quality of life improvements for all of modules, including more consistent API bounds for a lot of our submodules. The biggest change is that we're now using the full semver range, `major.minor.patch`, and any breaking changes to our "stable" APIs will require an update of the `major` number. We're excited we've hit this milestone together with you all. Thank you! ## Added - Added `Future::join` as "unstable", replacing `future::join!`. - Added `Future::try_join` as "unstable", replacing `future::try_join!`. - Enabled `stable` and `beta` channel testing on CI. - Implemented `FromIterator` and `Extend` for `PathBuf`. - Implemented `FromStream` for `PathBuf`. - Loosened the trait bounds of `io::copy` on "unstable". ## Changed - Added a `Sync` bound to `RwLock`, resolving a memory safety issue. - Fixed a bug in `Stream::take_while` where it could continue after it should've ended. - Fixed a bug where our `attributes` Cargo feature wasn't working as intended. - Improved documentation of `Stream::merge`, documenting ordering guarantees. - Update doc imports in examples to prefer async-std's types. - Various quality of life improvements to the `future` submodule. - Various quality of life improvements to the `path` submodule. - Various quality of life improvements to the `stream` submodule. ## Removed - Removed `future::join!` in favor of `Future::join`. - Removed `future::try_join!` in favor of `Future::try_join`. # [0.99.12] - 2019-11-07 [API Documentation](https://docs.rs/async-std/0.99.12/async-std) This patch upgrades us to `futures` 0.3, support for `async/await` on Rust Stable, performance improvements, and brand new module-level documentation. ## Added - Added `Future::flatten` as "unstable". - Added `Future::race` as "unstable" (replaces `future::select!`). - Added `Future::try_race` as "unstable" (replaces `future::try_select!`). - Added `Stderr::lock` as "unstable". - Added `Stdin::lock` as "unstable". - Added `Stdout::lock` as "unstable". - Added `Stream::copied` as "unstable". - Added `Stream::eq` as "unstable". - Added `Stream::max_by_key` as "unstable". - Added `Stream::min` as "unstable". - Added `Stream::ne` as "unstable". - Added `Stream::position` as "unstable". - Added `StreamExt` and `FutureExt` as enumerable in the `prelude`. - Added `TcpListener` and `TcpStream` integration tests. - Added `stream::from_iter`. - Added `sync::WakerSet` for internal use. - Added an example to handle both `IP v4` and `IP v6` connections. - Added the `default` Cargo feature. - Added the `attributes` Cargo feature. - Added the `std` Cargo feature. ## Changed - Fixed a bug in the blocking threadpool where it didn't spawn more than one thread. - Fixed a bug with `Stream::merge` where sometimes it ended too soon. - Fixed a bug with our GitHub actions setup. - Fixed an issue where our channels could spuriously deadlock. - Refactored the `task` module. - Removed a deprecated GitHub action. - Replaced `futures-preview` with `futures`. - Replaced `lazy_static` with `once_cell`. - Replaced all uses of `VecDequeue` in the examples with `stream::from_iter`. - Simplified `sync::RwLock` using the internal `sync::WakerSet` type. - Updated the `path` submodule documentation to match std. - Updated the mod-level documentation to match std. ## Removed - Removed `future::select!` (replaced by `Future::race`). - Removed `future::try_select!` (replaced by `Future::try_race`). # [0.99.11] - 2019-10-29 This patch introduces `async_std::sync::channel`, a novel asynchronous port of the ultra-fast Crossbeam channels. This has been one of the most anticipated features for async-std, and we're excited to be providing a first version of this! In addition to channels, this patch has the regular list of new methods, types, and doc fixes. ## Examples __Send and receive items from a channel__ ```rust // Create a bounded channel with a max-size of 1 let (s, r) = channel(1); // This call returns immediately because there is enough space in the channel. s.send(1).await; task::spawn(async move { // This call blocks the current task because the channel is full. // It will be able to complete only after the first message is received. s.send(2).await; }); // Receive items from the channel task::sleep(Duration::from_secs(1)).await; assert_eq!(r.recv().await, Some(1)); assert_eq!(r.recv().await, Some(2)); ``` ## Added - Added `Future::delay` as "unstable" - Added `Stream::flat_map` as "unstable" - Added `Stream::flatten` as "unstable" - Added `Stream::product` as "unstable" - Added `Stream::sum` as "unstable" - Added `Stream::min_by_key` - Added `Stream::max_by` - Added `Stream::timeout` as "unstable" - Added `sync::channel` as "unstable". - Added doc links from instantiated structs to the methods that create them. - Implemented `Extend` + `FromStream` for `PathBuf`. ## Changed - Fixed an issue with `block_on` so it works even when nested. - Fixed issues with our Clippy check on CI. - Replaced our uses of `cfg_if` with our own macros, simplifying the codebase. - Updated the homepage link in `Cargo.toml` to point to [async.rs](https://async.rs). - Updated the module-level documentation for `stream` and `sync`. - Various typos and grammar fixes. - Removed redundant file flushes, improving the performance of `File` operations ## Removed Nothing was removed in this release. # [0.99.10] - 2019-10-16 This patch stabilizes several core concurrency macros, introduces async versions of `Path` and `PathBuf`, and adds almost 100 other commits. ## Examples __Asynchronously read directories from the filesystem__ ```rust use async_std::fs; use async_std::path::Path; use async_std::prelude::*; let path = Path::new("/laputa"); let mut dir = fs::read_dir(&path).await.unwrap(); while let Some(entry) = dir.next().await { if let Ok(entry) = entry { println!("{:?}", entry.path()); } } ``` __Cooperatively reschedule the current task on the executor__ ```rust use async_std::prelude::*; use async_std::task; task::spawn(async { let x = fibonacci(1000); // Do expensive work task::yield_now().await; // Allow other tasks to run x + fibonacci(100) // Do more work }) ``` __Create an interval stream__ ```rust use async_std::prelude::*; use async_std::stream; use std::time::Duration; let mut interval = stream::interval(Duration::from_secs(4)); while let Some(_) = interval.next().await { println!("prints every four seconds"); } ``` ## Added - Added `FutureExt` to the `prelude`, allowing us to extend `Future` - Added `Stream::cmp` - Added `Stream::ge` - Added `Stream::last` - Added `Stream::le` - Added `Stream::lt` - Added `Stream::merge` as "unstable", replacing `stream::join!` - Added `Stream::partial_cmp` - Added `Stream::take_while` - Added `Stream::try_fold` - Added `future::IntoFuture` as "unstable" - Added `io::BufRead::split` - Added `io::Write::write_fmt` - Added `print!`, `println!`, `eprint!`, `eprintln!` macros as "unstable" - Added `process` as "unstable", re-exporting std types only for now - Added `std::net` re-exports to the `net` submodule - Added `std::path::PathBuf` with all associated methods - Added `std::path::Path` with all associated methods - Added `stream::ExactSizeStream` as "unstable" - Added `stream::FusedStream` as "unstable" - Added `stream::Product` - Added `stream::Sum` - Added `stream::from_fn` - Added `stream::interval` as "unstable" - Added `stream::repeat_with` - Added `task::spawn_blocking` as "unstable", replacing `task::blocking` - Added `task::yield_now` - Added `write!` and `writeln!` macros as "unstable" - Stabilized `future::join!` and `future::try_join!` - Stabilized `future::timeout` - Stabilized `path` - Stabilized `task::ready!` ## Changed - Fixed `BufWriter::into_inner` so it calls `flush` before yielding - Refactored `io::BufWriter` internals - Refactored `net::ToSocketAddrs` internals - Removed Travis CI entirely - Rewrote the README.md - Stabilized `io::Cursor` - Switched bors over to use GitHub actions - Updated the `io` documentation to match std's `io` docs - Updated the `task` documentation to match std's `thread` docs ## Removed - Removed the "unstable" `stream::join!` in favor of `Stream::merge` - Removed the "unstable" `task::blocking` in favor of `task::spawn_blocking` # [0.99.9] - 2019-10-08 This patch upgrades our `futures-rs` version, allowing us to build on the 1.39 beta. Additionally we've introduced `map` and `for_each` to `Stream`. And we've added about a dozen new `FromStream` implementations for `std` types, bringing us up to par with std's `FromIterator` implementations. And finally we've added a new "unstable" `task::blocking` function which can be used to convert blocking code into async code using a threadpool. We've been using this internally for a while now to async-std to power our `fs` and `net::SocketAddr` implementations. With this patch userland code now finally has access to this too. ## Example __Create a stream of tuples, and collect into a hashmap__ ```rust let a = stream::once(1u8); let b = stream::once(0u8); let s = a.zip(b); let map: HashMap = s.collect().await; assert_eq!(map.get(&1), Some(&0u8)); ``` __Spawn a blocking task on a dedicated threadpool__ ```rust task::blocking(async { println!("long-running task here"); }).await; ``` ## Added - Added `stream::Stream::map` - Added `stream::Stream::for_each` - Added `stream::Stream::try_for_each` - Added `task::blocking` as "unstable" - Added `FromStream` for all `std::{option, collections, result, string, sync}` types. - Added the `path` submodule as "unstable". ## Changed - Updated `futures-preview` to `0.3.0-alpha.19`, allowing us to build on `rustc 1.39.0-beta`. - As a consequence of this upgrade, all of our concrete stream implementations now make use of `Stream::size_hint` to optimize internal allocations. - We now use GitHub Actions through [actions-rs](https://github.com/actions-rs), in addition to Travis CI. We intend to fully switch in the near future. - Fixed a bug introduced in 0.99.6 where Unix Domain Listeners would sometimes become unresponsive. - Updated our `sync::Barrier` docs to match std. - Updated our `stream::FromStream` docs to match std's `FromIterator`. # [0.99.8] - 2019-09-28 ## Added - Added README to examples directory. - Added concurrency documentation to the futures submodule. - Added `io::Read::take` method. - Added `io::Read::by_ref` method. - Added `io::Read::chain` method. ## Changed - Pin futures-preview to `0.3.0-alpha.18`, to avoid rustc upgrade problems. - Simplified extension traits using a macro. - Use the `broadcast` module with `std::sync::Mutex`, reducing dependencies. # [0.99.7] - 2019-09-26 ## Added - Added `future::join` macro as "unstable" - Added `future::select` macro as "unstable" - Added `future::try_join` macro as "unstable" - Added `future::try_select` macro as "unstable" - Added `io::BufWriter` struct - Added `stream::Extend` trait - Added `stream::Stream::chain` method - Added `stream::Stream::filter` method - Added `stream::Stream::inspect` method - Added `stream::Stream::skip_while` method - Added `stream::Stream::skip` method - Added `stream::Stream::step_by` method - Added `sync::Arc` struct from stdlib - Added `sync::Barrier` struct as "unstable" - Added `sync::Weak` struct from stdlib - Added `task::ready` macro as "unstable" ## Changed - Correctly marked the `pin` submodule as "unstable" in the docs - Updated tutorial to have certain functions suffixed with `_loop` - `io` traits are now re-exports of futures-rs types, allowing them to be implemented - `stream` traits are now re-exports of futures-rs types, allowing them to be implemented - `prelude::*` now needs to be in scope for functions `io` and `stream` traits to work # [0.99.6] - 2019-09-19 ## Added - Added `stream::Stream::collect` as "unstable" - Added `stream::Stream::enumerate` - Added `stream::Stream::fuse` - Added `stream::Stream::fold` - Added `stream::Stream::scan` - Added `stream::Stream::zip` - Added `stream::join` macro as "unstable" - Added `stream::DoubleEndedStream` as "unstable" - Added `stream::FromStream` trait as "unstable" - Added `stream::IntoStream` trait as "unstable" - Added `io::Cursor` as "unstable" - Added `io::BufRead::consume` method - Added `io::repeat` - Added `io::Slice` and `io::SliceMut` - Added documentation for feature flags - Added `pin` submodule as "unstable" - Added the ability to `collect` a stream of `Result`s into a `Result, E>` ## Changed - Refactored the scheduling algorithm of our executor to use work stealing - Refactored the network driver, removing 400 lines of code - Removed the `Send` bound from `task::block_on` - Removed `Unpin` bound from `impl Stream for T` # [0.99.5] - 2019-09-12 ## Added - Added tests for `io::timeout` - Added `io::BufRead::fill_buf`, an `async fn` counterpart to `poll_fill_buf` - Added `fs::create_dir_all` - Added `future::timeout`, a free function to time out futures after a threshold - Added `io::prelude` - Added `net::ToSocketAddrs`, a non-blocking version of std's `ToSocketAddrs` - Added `stream::Stream::all` - Added `stream::Stream::filter_map` - Added `stream::Stream::find_map` - Added `stream::Stream::find` - Added `stream::Stream::min_by` - Added `stream::Stream::nth` ## Changed - Polished the text and examples of the tutorial - `cargo fmt` on all examples - Simplified internals of `TcpStream::connect_to` - Modularized our CI setup, enabled a rustfmt fallback, and improved caching - Reduced our dependency on the `futures-rs` crate, improving compilation times - Split `io::Read`, `io::Write`, `io::BufRead`, and `stream::Stream` into multiple files - `fs::File` now flushes more often to prevent flushes during `seek` - Updated all dependencies - Fixed a bug in the conversion of `File` into raw handle - Fixed compilation errors on the latest nightly ## Removed # [0.99.4] - 2019-08-21 ## Changes - Many small changes in the book, mostly typos - Documentation fixes correcting examples - Now works with recent nightly with stabilised async/await (> 2019-08-21) # [0.99.3] - 2019-08-16 - Initial beta release [Unreleased]: https://github.com/async-rs/async-std/compare/v1.7.0...HEAD [1.7.0]: https://github.com/async-rs/async-std/compare/v1.6.5...1.7.0 [1.6.5]: https://github.com/async-rs/async-std/compare/v1.6.4...v1.6.5 [1.6.4]: https://github.com/async-rs/async-std/compare/v1.6.3...v1.6.4 [1.6.3]: https://github.com/async-rs/async-std/compare/v1.6.2...v1.6.3 [1.6.2]: https://github.com/async-rs/async-std/compare/v1.6.1...v1.6.2 [1.6.1]: https://github.com/async-rs/async-std/compare/v1.6.0...v1.6.1 [1.6.0]: https://github.com/async-rs/async-std/compare/v1.5.0...v1.6.0 [1.6.0-beta.2]: https://github.com/async-rs/async-std/compare/v1.6.0-beta.1...v1.6.0-beta.2 [1.6.0-beta.1]: https://github.com/async-rs/async-std/compare/v1.5.0...v1.6.0-beta.1 [1.5.0]: https://github.com/async-rs/async-std/compare/v1.4.0...v1.5.0 [1.4.0]: https://github.com/async-rs/async-std/compare/v1.3.0...v1.4.0 [1.3.0]: https://github.com/async-rs/async-std/compare/v1.2.0...v1.3.0 [1.2.0]: https://github.com/async-rs/async-std/compare/v1.1.0...v1.2.0 [1.1.0]: https://github.com/async-rs/async-std/compare/v1.0.1...v1.1.0 [1.0.1]: https://github.com/async-rs/async-std/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/async-rs/async-std/compare/v0.99.12...v1.0.0 [0.99.12]: https://github.com/async-rs/async-std/compare/v0.99.11...v0.99.12 [0.99.11]: https://github.com/async-rs/async-std/compare/v0.99.10...v0.99.11 [0.99.10]: https://github.com/async-rs/async-std/compare/v0.99.9...v0.99.10 [0.99.9]: https://github.com/async-rs/async-std/compare/v0.99.8...v0.99.9 [0.99.8]: https://github.com/async-rs/async-std/compare/v0.99.7...v0.99.8 [0.99.7]: https://github.com/async-rs/async-std/compare/v0.99.6...v0.99.7 [0.99.6]: https://github.com/async-rs/async-std/compare/v0.99.5...v0.99.6 [0.99.5]: https://github.com/async-rs/async-std/compare/v0.99.4...v0.99.5 [0.99.4]: https://github.com/async-rs/async-std/compare/v0.99.3...v0.99.4 [0.99.3]: https://github.com/async-rs/async-std/tree/v0.99.3 async-rs-async-std-57f61ae/CODE_OF_CONDUCT.md000066400000000000000000000064261476537407000204200ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at stjepang@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq async-rs-async-std-57f61ae/Cargo.toml000066400000000000000000000063001476537407000175400ustar00rootroot00000000000000[package] name = "async-std" version = "1.13.1" authors = [ "Stjepan Glavina ", "Yoshua Wuyts ", "Friedel Ziegelmayer ", "Contributors to async-std", ] edition = "2018" rust-version = "1.63" license = "Apache-2.0 OR MIT" repository = "https://github.com/async-rs/async-std" homepage = "https://async.rs" description = "Deprecated in favor of `smol` - Async version of the Rust standard library" keywords = ["async", "await", "future", "std", "task"] categories = ["asynchronous", "concurrency", "network-programming"] [package.metadata.docs.rs] features = ["docs"] rustdoc-args = ["--cfg", "feature=\"docs\""] [features] default = [ "std", "async-global-executor", "async-io", "futures-lite", "kv-log-macro", "log", "pin-project-lite", "gloo-timers", ] docs = ["attributes", "unstable", "default"] unstable = [ "std", "async-io", "async-process", ] attributes = ["async-attributes"] std = [ "alloc", "crossbeam-utils", "futures-core/std", "futures-io", "memchr", "once_cell", "pin-utils", "slab", "wasm-bindgen-futures", "futures-channel", "async-channel", "async-lock", ] alloc = [ "futures-core/alloc", "pin-project-lite", ] tokio1 = ["async-global-executor/tokio"] tokio02 = ["async-global-executor/tokio02"] tokio03 = ["async-global-executor/tokio03"] io_safety = [] [dependencies] async-attributes = { version = "1.1.2", optional = true } async-lock = { version = "3.1.0", optional = true } crossbeam-utils = { version = "0.8.0", optional = true } futures-core = { version = "0.3.4", optional = true, default-features = false } futures-io = { version = "0.3.4", optional = true } kv-log-macro = { version = "1.0.6", optional = true } log = { version = "0.4.8", features = ["kv_unstable"], optional = true } memchr = { version = "2.3.3", optional = true } once_cell = { version = "1.3.1", optional = true } pin-project-lite = { version = "0.2.0", optional = true } pin-utils = { version = "0.1.0-alpha.4", optional = true } slab = { version = "0.4.2", optional = true } async-channel = { version = "1.8.0", optional = true } # dev dependency, but they are not allowed to be optional :/ surf = { version = "2.0.0", optional = true } [target.'cfg(not(target_os = "unknown"))'.dependencies] async-global-executor = { version = "2.4.0", optional = true, features = ["async-io"] } async-io = { version = "2.2.0", optional = true } futures-lite = { version = "2.0.0", optional = true } async-process = { version = "2.0.0", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] gloo-timers = { version = "0.3.0", features = ["futures"], optional = true } wasm-bindgen-futures = { version = "0.4.10", optional = true } futures-channel = { version = "0.3.4", optional = true } [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test = "0.3.10" getrandom = { version = "0.2.0", features = ["js"] } [dev-dependencies] femme = "2.1.1" rand = "0.8.0" tempfile = "3.1.0" futures = "0.3.4" rand_xorshift = "0.3.0" [[test]] name = "stream" required-features = ["unstable"] [[example]] name = "tcp-ipv4-and-6-echo" required-features = ["unstable"] [[example]] name = "surf-web" required-features = ["surf"] async-rs-async-std-57f61ae/LICENSE-APACHE000066400000000000000000000251371476537407000175450ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. async-rs-async-std-57f61ae/LICENSE-MIT000066400000000000000000000017771476537407000172610ustar00rootroot00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. async-rs-async-std-57f61ae/README.md000066400000000000000000000065551476537407000171030ustar00rootroot00000000000000# `async-std` has been discontinued; use `smol` instead We created `async-std` to demonstrate the value of making a library as close to `std` as possible, but async. We think that demonstration was successful, and we hope it will influence future design and development directions of async in `std`. However, in the meantime, the [`smol`](https://github.com/smol-rs/smol/) project came about and provided a great executor and libraries for asynchronous use in the Rust ecosystem. We think that resources would be better spent consolidating around `smol`, rather than continuing to provide occasional maintenance of `async-std`. As such, we recommend that all users of `async-std`, and all libraries built on `async-std`, switch to `smol` instead. In addition to the `smol` project as a direct replacement, you may find other parts of the futures ecosystem useful, including `futures-concurrency`, `async-io`, `futures-lite`, and `async-compat`.
This crate provides an async version of [`std`]. It provides all the interfaces you are used to, but in an async version and ready for Rust's `async`/`await` syntax. [`std`]: https://doc.rust-lang.org/std/index.html ## Features - __Modern:__ Built from the ground up for `std::future` and `async/await` with blazing fast compilation time. - __Fast:__ Our robust allocator and threadpool designs provide ultra-high throughput with predictably low latency. - __Intuitive:__ Complete parity with the stdlib means you only need to learn APIs once. - __Clear:__ [Detailed documentation][docs] and [accessible guides][book] mean using async Rust was never easier. [docs]: https://docs.rs/async-std [book]: https://book.async.rs ## Examples ```rust use async_std::task; async fn say_hello() { println!("Hello, world!"); } fn main() { task::block_on(say_hello()) } ``` More examples, including networking and file access, can be found in our [`examples`] directory and in our [documentation]. [`examples`]: https://github.com/async-rs/async-std/tree/HEAD/examples [documentation]: https://docs.rs/async-std#examples [`task::block_on`]: https://docs.rs/async-std/*/async_std/task/fn.block_on.html [`"attributes"` feature]: https://docs.rs/async-std/#features ## Philosophy We believe Async Rust should be as easy to pick up as Sync Rust. We also believe that the best API is the one you already know. And finally, we believe that providing an asynchronous counterpart to the standard library is the best way stdlib provides a reliable basis for both performance and productivity. Async-std is the embodiment of that vision. It combines single-allocation task creation, with an adaptive lock-free executor, threadpool and network driver to create a smooth system that processes work at a high pace with low latency, using Rust's familiar stdlib API. ## License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. async-rs-async-std-57f61ae/benches/000077500000000000000000000000001476537407000172205ustar00rootroot00000000000000async-rs-async-std-57f61ae/benches/mutex.rs000066400000000000000000000013311476537407000207260ustar00rootroot00000000000000#![feature(test)] extern crate test; use async_std::sync::{Arc, Mutex}; use async_std::task; use test::Bencher; #[bench] fn create(b: &mut Bencher) { b.iter(|| Mutex::new(())); } #[bench] fn contention(b: &mut Bencher) { b.iter(|| task::block_on(run(10, 1000))); } #[bench] fn no_contention(b: &mut Bencher) { b.iter(|| task::block_on(run(1, 10000))); } async fn run(task: usize, iter: usize) { let m = Arc::new(Mutex::new(())); let mut tasks = Vec::new(); for _ in 0..task { let m = m.clone(); tasks.push(task::spawn(async move { for _ in 0..iter { let _ = m.lock().await; } })); } for t in tasks { t.await; } } async-rs-async-std-57f61ae/benches/task.rs000066400000000000000000000002431476537407000205270ustar00rootroot00000000000000#![feature(test)] extern crate test; use async_std::task; use test::Bencher; #[bench] fn block_on(b: &mut Bencher) { b.iter(|| task::block_on(async {})); } async-rs-async-std-57f61ae/benches/task_local.rs000066400000000000000000000005121476537407000217000ustar00rootroot00000000000000#![feature(test)] extern crate test; use async_std::task; use async_std::task_local; use test::{black_box, Bencher}; #[bench] fn get(b: &mut Bencher) { task_local! { static VAL: u64 = 1; } let mut sum = 0; task::block_on(async { b.iter(|| VAL.with(|v| sum += v)); }); black_box(sum); } async-rs-async-std-57f61ae/ci/000077500000000000000000000000001476537407000162045ustar00rootroot00000000000000async-rs-async-std-57f61ae/ci/install-mdbook.sh000077500000000000000000000011671476537407000214670ustar00rootroot00000000000000set -euxo pipefail # Based on the Rust-Embedded WG's book CI # https://github.com/rust-embedded/book/blob/HEAD/ci/install.sh main() { # Note - this will only accept releases tagged with v0.3.x local tag=$(git ls-remote --tags --refs --exit-code \ https://github.com/rust-lang-nursery/mdbook \ | cut -d/ -f3 \ | grep -E '^v0\.3\.[0-9]+$' \ | sort --version-sort \ | tail -n1) curl -LSfs https://japaric.github.io/trust/install.sh | \ sh -s -- --git rust-lang-nursery/mdbook --tag $tag } main async-rs-async-std-57f61ae/docs/000077500000000000000000000000001476537407000165415ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/.gitignore000066400000000000000000000000051476537407000205240ustar00rootroot00000000000000book async-rs-async-std-57f61ae/docs/book.toml000066400000000000000000000004411476537407000203670ustar00rootroot00000000000000[book] authors = ["The async-std maintainers"] language = "en" multilingual = false src = "src" title = "Async programming in Rust with async-std" [build] create-missing = false [output.html] git-repository-url = "https://github.com/async-rs/async-std" git-repository-icon = "fa-github" async-rs-async-std-57f61ae/docs/src/000077500000000000000000000000001476537407000173305ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/src/SUMMARY.md000066400000000000000000000024141476537407000210100ustar00rootroot00000000000000# Summary - [Introduction](./introduction.md) - [Welcome to `async-std`!](./overview/async-std.md) - [Stability guarantees](./overview/stability-guarantees.md) - [Async concepts using async-std](./concepts.md) - [Futures](./concepts/futures.md) - [Tasks](./concepts/tasks.md) - [Async read/write](./concepts/async-read-write.md) - [Streams and Channels](./concepts/streams.md) - [Tutorial: Implementing a chat](./tutorial/index.md) - [Specification and Getting started](./tutorial/specification.md) - [Writing an Accept Loop](./tutorial/accept_loop.md) - [Receiving Messages](./tutorial/receiving_messages.md) - [Sending Messages](./tutorial/sending_messages.md) - [Connecting Readers and Writers](./tutorial/connecting_readers_and_writers.md) - [All Together](./tutorial/all_together.md) - [Clean Shutdown](./tutorial/clean_shutdown.md) - [Handling Disconnection](./tutorial/handling_disconnection.md) - [Implementing a Client](./tutorial/implementing_a_client.md) - [Async Patterns](./patterns.md) - [TODO: Collected Small Patterns](./patterns/small-patterns.md) - [Production-Ready Accept Loop](./patterns/accept-loop.md) - [Security practices](./security/index.md) - [Security Disclosures and Policy](./security/policy.md) - [Glossary](./glossary.md) async-rs-async-std-57f61ae/docs/src/concepts.md000066400000000000000000000025751476537407000215010ustar00rootroot00000000000000# Async concepts using async-std [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. 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. 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. 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. 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. Let's start with a little bit of motivation, though. [futures]: https://en.wikipedia.org/wiki/Futures_and_promises async-rs-async-std-57f61ae/docs/src/concepts/000077500000000000000000000000001476537407000211465ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/src/concepts/async-read-write.md000066400000000000000000000000311476537407000246400ustar00rootroot00000000000000# TODO: Async read/write async-rs-async-std-57f61ae/docs/src/concepts/data.csv000066400000000000000000000000001476537407000225620ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/src/concepts/futures.md000066400000000000000000000250711476537407000231720ustar00rootroot00000000000000# Futures A notable point about Rust is [*fearless concurrency*](https://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html). That is the notion that you should be empowered to do concurrent things, without giving up safety. Also, Rust being a low-level language, it's about fearless concurrency *without picking a specific implementation strategy*. This means we *must* abstract over the strategy, to allow choice *later*, if we want to have any way to share code between users of different strategies. Futures abstract over *computation*. They describe the "what", independent of the "where" and the "when". For that, they aim to break code into small, composable actions that can then be executed by a part of our system. Let's take a tour through what it means to compute things to find where we can abstract. ## Send and Sync Luckily, concurrent Rust already has two well-known and effective concepts abstracting over sharing between concurrent parts of a program: `Send` and `Sync`. Notably, both the `Send` and `Sync` traits abstract over *strategies* of concurrent work, compose neatly, and don't prescribe an implementation. As a quick summary: - `Send` abstracts over *passing data* in a computation to another concurrent computation (let's call it the receiver), losing access to it on the sender side. In many programming languages, this strategy is commonly implemented, but missing support from the language side, and expects you to enforce the "losing access" behaviour yourself. This is a regular source of bugs: senders keeping handles to sent things around and maybe even working with them after sending. Rust mitigates this problem by making this behaviour known. Types can be `Send` or not (by implementing the appropriate marker trait), allowing or disallowing sending them around, and the ownership and borrowing rules prevent subsequent access. - `Sync` is about *sharing data* between two concurrent parts of a program. This is another common pattern: as writing to a memory location or reading while another party is writing is inherently unsafe, this access needs to be moderated through synchronisation.[^1] There are many common ways for two parties to agree on not using the same part in memory at the same time, for example mutexes and spinlocks. Again, Rust gives you the option of (safely!) not caring. Rust gives you the ability to express that something *needs* synchronisation while not being specific about the *how*. Note how we avoided any word like *"thread"*, but instead opted for "computation". The full power of `Send` and `Sync` is that they relieve you of the burden of knowing *what* shares. At the point of implementation, you only need to know which method of sharing is appropriate for the type at hand. This keeps reasoning local and is not influenced by whatever implementation the user of that type later uses. `Send` and `Sync` can be composed in interesting fashions, but that's beyond the scope here. You can find examples in the [Rust Book][rust-book-sync]. [rust-book-sync]: https://doc.rust-lang.org/stable/book/ch16-04-extensible-concurrency-sync-and-send.html To sum up: Rust gives us the ability to safely abstract over important properties of concurrent programs, their data sharing. It does so in a very lightweight fashion; the language itself only knows about the two markers `Send` and `Sync` and helps us a little by deriving them itself, when possible. The rest is a library concern. ## An easy view of computation While computation is a subject to write a whole [book](https://computationbook.com/) about, a very simplified view suffices for us: A sequence of composable operations which can branch based on a decision, run to succession and yield a result or yield an error ## Deferring computation As mentioned above, `Send` and `Sync` are about data. But programs are not only about data, they also talk about *computing* the data. And that's what [`Futures`][futures] do. We are going to have a close look at how that works in the next chapter. Let's look at what Futures allow us to express, in English. Futures go from this plan: - Do X - If X succeeded, do Y towards: - Start doing X - Once X succeeds, start doing Y Remember the talk about "deferred computation" in the intro? That's all it is. Instead of telling the computer what to execute and decide upon *now*, you tell it what to start doing and how to react on potential events in the... well... `Future`. [futures]: https://doc.rust-lang.org/std/future/trait.Future.html ## Orienting towards the beginning Let's have a look at a simple function, specifically the return value: ```rust,edition2018 # use std::{fs::File, io, io::prelude::*}; # fn read_file(path: &str) -> io::Result { let mut file = File::open(path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) } ``` You can call that at any time, so you are in full control on when you call it. But here's the problem: the moment you call it, you transfer control to the called function until it returns a value - eventually. Note that this return value talks about the past. The past has a drawback: all decisions have been made. It has an advantage: the outcome is visible. We can unwrap the results of the program's past computation, and then decide what to do with it. But we wanted to abstract over *computation* and let someone else choose how to run it. That's fundamentally incompatible with looking at the results of previous computation all the time. So, let's find a type that *describes* a computation without running it. Let's look at the function again: ```rust,edition2018 # use std::{fs::File, io, io::prelude::*}; # fn read_file(path: &str) -> io::Result { let mut file = File::open(path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) } ``` Speaking in terms of time, we can only take action *before* calling the function or *after* the function returned. This is not desirable, as it takes from us the ability to do something *while* it runs. When working with parallel code, this would take from us the ability to start a parallel task while the first runs (because we gave away control). This is the moment where we could reach for [threads](https://en.wikipedia.org/wiki/Thread_). But threads are a very specific concurrency primitive and we said that we are searching for an abstraction. What we are searching for is something that represents ongoing work towards a result in the future. Whenever we say "something" in Rust, we almost always mean a trait. Let's start with an incomplete definition of the `Future` trait: ```rust,edition2018 # use std::{pin::Pin, task::{Context, Poll}}; # trait Future { type Output; fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll; } ``` Looking at it closely, we see the following: - It is generic over the `Output`. - It provides a function called `poll`, which allows us to check on the state of the current computation. - (Ignore `Pin` and `Context` for now, you don't need them for high-level understanding.) Every call to `poll()` can result in one of these two cases: 1. The computation is done, `poll` will return [`Poll::Ready`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Ready) 2. The computation has not finished executing, it will return [`Poll::Pending`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Pending) This allows us to externally check if a `Future` still has unfinished work, or is finally done and can give us the value. The most simple (but not efficient) way would be to just constantly poll futures in a loop. There are optimisations possible, and this is what a good runtime does for you. Note that calling `poll` again after case 1 happened may result in confusing behaviour. See the [futures-docs](https://doc.rust-lang.org/std/future/trait.Future.html) for details. ## Async While the `Future` trait has existed in Rust for a while, it was inconvenient to build and describe them. For this, Rust now has a special syntax: `async`. The example from above, implemented with `async-std`, would look like this: ```rust,edition2018 # extern crate async_std; # use async_std::{fs::File, io, io::prelude::*}; # async fn read_file(path: &str) -> io::Result { let mut file = File::open(path).await?; let mut contents = String::new(); file.read_to_string(&mut contents).await?; Ok(contents) } ``` Amazingly little difference, right? All we did is label the function `async` and insert 2 special commands: `.await`. This `async` function sets up a deferred computation. When this function is called, it will produce a `Future>` instead of immediately returning a `io::Result`. (Or, more precisely, generate a type for you that implements `Future>`.) ## What does `.await` do? The `.await` postfix does exactly what it says on the tin: the moment you use it, the code will wait until the requested action (e.g. opening a file or reading all data in it) is finished. The `.await?` is not special, it's just the application of the `?` operator to the result of `.await`. So, what is gained over the initial code example? We're getting futures and then immediately waiting for them? The `.await` points act as a marker. Here, the code will wait for a `Future` to produce its value. How will a future finish? You don't need to care! The marker allows the component (usually called the “runtime”) in charge of *executing* this piece of code to take care of all the other things it has to do while the computation finishes. It will come back to this point when the operation you are doing in the background is done. This is why this style of programming is also called *evented programming*. We are waiting for *things to happen* (e.g. a file to be opened) and then react (by starting to read). When executing 2 or more of these functions at the same time, our runtime system is then able to fill the wait time with handling *all the other events* currently going on. ## Conclusion Working from values, we searched for something that expresses *working towards a value available later*. From there, we talked about the concept of polling. A `Future` is any data type that does not represent a value, but the ability to *produce a value at some point in the future*. Implementations of this are very varied and detailed depending on use-case, but the interface is simple. Next, we will introduce you to `tasks`, which we will use to actually *run* Futures. [^1]: Two parties reading while it is guaranteed that no one is writing is always safe. [futures]: https://rust-lang.github.io/async-book/02_execution/02_future.html async-rs-async-std-57f61ae/docs/src/concepts/streams.md000066400000000000000000000000201476537407000231360ustar00rootroot00000000000000# TODO: Streams async-rs-async-std-57f61ae/docs/src/concepts/tasks.md000066400000000000000000000143621476537407000226230ustar00rootroot00000000000000# Tasks Now that we know what Futures are, we want to run them! In `async-std`, the [`task`][tasks] module is responsible for this. The simplest way is using the `block_on` function: ```rust,edition2018 # extern crate async_std; use async_std::{fs::File, io, prelude::*, task}; async fn read_file(path: &str) -> io::Result { let mut file = File::open(path).await?; let mut contents = String::new(); file.read_to_string(&mut contents).await?; Ok(contents) } fn main() { let reader_task = task::spawn(async { let result = read_file("data.csv").await; match result { Ok(s) => println!("{}", s), Err(e) => println!("Error reading file: {:?}", e) } }); println!("Started task!"); task::block_on(reader_task); println!("Stopped task!"); } ``` This asks the runtime baked into `async_std` to execute the code that reads a file. Let's go one by one, though, inside to outside. ```rust,edition2018 # extern crate async_std; # use async_std::{fs::File, io, prelude::*, task}; # # async fn read_file(path: &str) -> io::Result { # let mut file = File::open(path).await?; # let mut contents = String::new(); # file.read_to_string(&mut contents).await?; # Ok(contents) # } # async { let result = read_file("data.csv").await; match result { Ok(s) => println!("{}", s), Err(e) => println!("Error reading file: {:?}", e) } }; ``` This is an `async` *block*. Async blocks are necessary to call `async` functions, and will instruct the compiler to include all the relevant instructions to do so. In Rust, all blocks return a value and `async` blocks happen to return a value of the kind `Future`. But let's get to the interesting part: ```rust,edition2018 # extern crate async_std; # use async_std::task; task::spawn(async { }); ``` `spawn` takes a `Future` and starts running it on a `Task`. It returns a `JoinHandle`. Futures in Rust are sometimes called *cold* Futures. You need something that starts running them. To run a Future, there may be some additional bookkeeping required, e.g. whether it's running or finished, where it is being placed in memory and what the current state is. This bookkeeping part is abstracted away in a `Task`. A `Task` is similar to a `Thread`, with some minor differences: it will be scheduled by the program instead of the operating system kernel, and if it encounters a point where it needs to wait, the program itself is responsible for waking it up again. We'll talk a little bit about that later. An `async_std` task can also have a name and an ID, just like a thread. For now, it is enough to know that once you have `spawn`ed a task, it will continue running in the background. The `JoinHandle` is itself a future that will finish once the `Task` has run to conclusion. Much like with `threads` and the `join` function, we can now call `block_on` on the handle to *block* the program (or the calling thread, to be specific) and wait for it to finish. ## Tasks in `async_std` Tasks in `async_std` are one of the core abstractions. Much like Rust's `thread`s, they provide some practical functionality over the raw concept. `Tasks` have a relationship to the runtime, but they are in themselves separate. `async_std` tasks have a number of desirable properties: - They are allocated in one single allocation - All tasks have a *backchannel*, which allows them to propagate results and errors to the spawning task through the `JoinHandle` - They carry useful metadata for debugging - They support task local storage `async_std`s task API handles setup and teardown of a backing runtime for you and doesn't rely on a runtime being explicitly started. ## Blocking `Task`s are assumed to run _concurrently_, potentially by sharing a thread of execution. This means that operations blocking an _operating system thread_, such as `std::thread::sleep` or io function from Rust's `std` library will _stop execution of all tasks sharing this thread_. Other libraries (such as database drivers) have similar behaviour. Note that _blocking the current thread_ is not in and of itself bad behaviour, just something that does not mix well with the concurrent execution model of `async-std`. Essentially, never do this: ```rust,edition2018 # extern crate async_std; # use async_std::task; fn main() { task::block_on(async { // this is std::fs, which blocks std::fs::read_to_string("test_file"); }) } ``` If you want to mix operation kinds, consider putting such blocking operations on a separate `thread`. ## Errors and panics Tasks report errors through normal patterns: If they are fallible, their `Output` should be of kind `Result`. In case of `panic`, behaviour differs depending on whether there's a reasonable part that addresses the `panic`. If not, the program _aborts_. In practice, that means that `block_on` propagates panics to the blocking component: ```rust,edition2018,should_panic # extern crate async_std; # use async_std::task; fn main() { task::block_on(async { panic!("test"); }); } ``` ```text thread 'async-task-driver' panicked at 'test', examples/panic.rs:8:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. ``` While panicking a spawned task will abort: ```rust,edition2018,should_panic # extern crate async_std; # use async_std::task; # use std::time::Duration; task::spawn(async { panic!("test"); }); task::block_on(async { task::sleep(Duration::from_millis(10000)).await; }) ``` ```text thread 'async-task-driver' panicked at 'test', examples/panic.rs:8:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. Aborted (core dumped) ``` That might seem odd at first, but the other option would be to silently ignore panics in spawned tasks. The current behaviour can be changed by catching panics in the spawned task and reacting with custom behaviour. This gives users the choice of panic handling strategy. ## Conclusion `async_std` comes with a useful `Task` type that works with an API similar to `std::thread`. It covers error and panic behaviour in a structured and defined way. Tasks are separate concurrent units and sometimes they need to communicate. That's where `Stream`s come in. [tasks]: https://docs.rs/async-std/latest/async_std/task/index.html async-rs-async-std-57f61ae/docs/src/glossary.md000066400000000000000000000007621476537407000215220ustar00rootroot00000000000000# Glossary ### blocking "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. 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. async-rs-async-std-57f61ae/docs/src/images/000077500000000000000000000000001476537407000205755ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/src/images/async_1.svg000066400000000000000000000412141476537407000226550ustar00rootroot00000000000000 T T ! T T T T T async-rs-async-std-57f61ae/docs/src/images/async_2.svg000066400000000000000000000124721476537407000226620ustar00rootroot00000000000000 S ! T T async-rs-async-std-57f61ae/docs/src/images/horizontal_color.svg000066400000000000000000000202211476537407000247020ustar00rootroot00000000000000 image/svg+xml async-rs-async-std-57f61ae/docs/src/images/icon_color.svg000066400000000000000000000111771476537407000234530ustar00rootroot00000000000000 image/svg+xml async-rs-async-std-57f61ae/docs/src/images/vertical_color.svg000066400000000000000000000244001476537407000243250ustar00rootroot00000000000000 image/svg+xml async-rs-async-std-57f61ae/docs/src/introduction.md000066400000000000000000000010721476537407000223730ustar00rootroot00000000000000# Introduction ![async-std logo](./images/horizontal_color.svg) 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. 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. [async-book]: https://rust-lang.github.io/async-book/ async-rs-async-std-57f61ae/docs/src/overview/000077500000000000000000000000001476537407000211765ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/src/overview/async-std.md000066400000000000000000000014531476537407000234300ustar00rootroot00000000000000# Welcome to `async-std` `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. `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`. [organization]: https://github.com/async-rs async-rs-async-std-57f61ae/docs/src/overview/stability-guarantees.md000066400000000000000000000034371476537407000256670ustar00rootroot00000000000000# Stability and SemVer `async-std` follows https://semver.org/. In short: we are versioning our software as `MAJOR.MINOR.PATCH`. We increase the: * MAJOR version when there are incompatible API changes, * MINOR version when we introduce functionality in a backwards-compatible manner * PATCH version when we make backwards-compatible bug fixes We will provide migration documentation between major versions. ## Future expectations `async-std` uses its own implementations of the following concepts: * `Read` * `Write` * `Seek` * `BufRead` * `Stream` For integration with the ecosystem, all types implementing these traits also have an implementation of the corresponding interfaces in the `futures-rs` library. Please note that our SemVer guarantees don't extend to usage of those interfaces. We expect those to be conservatively updated and in lockstep. ## Minimum version policy The current tentative policy is that the minimum Rust version required to use this crate can be increased in minor version updates. For example, if `async-std` 1.0 requires Rust 1.37.0, then `async-std` 1.0.z for all values of z will also require Rust 1.37.0 or newer. However, `async-std` 1.y for y > 0 may require a newer minimum version of Rust. In general, this crate will be conservative with respect to the minimum supported version of Rust. With `async/await` being a new feature though, we will track changes in a measured pace initially. ## Security fixes Security fixes will be applied to _all_ minor branches of this library in all _supported_ major revisions. This policy might change in the future, in which case we give a notice at least _3 months_ ahead. ## Credits This policy is based on [BurntSushi's regex crate][regex-policy]. [regex-policy]: https://github.com/rust-lang/regex#minimum-rust-version-policy async-rs-async-std-57f61ae/docs/src/patterns.md000066400000000000000000000002241476537407000215100ustar00rootroot00000000000000# Patterns This section documents small, useful patterns. It is intended to be read at a glance, allowing you to get back when you have a problem.async-rs-async-std-57f61ae/docs/src/patterns/000077500000000000000000000000001476537407000211705ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/src/patterns/accept-loop.md000066400000000000000000000214321476537407000237220ustar00rootroot00000000000000# Production-Ready Accept Loop A production-ready accept loop needs the following things: 1. Handling errors 2. Limiting the number of simultanteous connections to avoid deny-of-service (DoS) attacks ## Handling errors There are two kinds of errors in an accept loop: 1. Per-connection errors. The system uses them to notify that there was a connection in the queue and it's dropped by the peer. Subsequent connections can be already queued so next connection must be accepted immediately. 2. Resource shortages. When these are encountered it doesn't make sense to accept the next socket immediately. But the listener stays active, so you server should try to accept socket later. Here is the example of a per-connection error (printed in normal and debug mode): ``` Error: Connection reset by peer (os error 104) Error: Os { code: 104, kind: ConnectionReset, message: "Connection reset by peer" } ``` And the following is the most common example of a resource shortage error: ``` Error: Too many open files (os error 24) Error: Os { code: 24, kind: Other, message: "Too many open files" } ``` ### Testing Application To test your application for these errors try the following (this works on unixes only). Lower limits and start the application: ``` $ ulimit -n 100 $ cargo run --example your_app Compiling your_app v0.1.0 (/work) Finished dev [unoptimized + debuginfo] target(s) in 5.47s Running `target/debug/examples/your_app` Server is listening on: http://127.0.0.1:1234 ``` Then in another console run the [`wrk`] benchmark tool: ``` $ wrk -c 1000 http://127.0.0.1:1234 Running 10s test @ http://localhost:8080/ 2 threads and 1000 connections $ telnet localhost 1234 Trying ::1... Connected to localhost. ``` Important is to check the following things: 1. The application doesn't crash on error (but may log errors, see below) 2. It's possible to connect to the application again once load is stopped (few seconds after `wrk`). This is what `telnet` does in example above, make sure it prints `Connected to `. 3. The `Too many open files` error is logged in the appropriate log. This requires to set "maximum number of simultaneous connections" parameter (see below) of your application to a value greater then `100` for this example. 4. Check CPU usage of the app while doing a test. It should not occupy 100% of a single CPU core (it's unlikely that you can exhaust CPU by 1000 connections in Rust, so this means error handling is not right). #### Testing non-HTTP applications If it's possible, use the appropriate benchmark tool and set the appropriate number of connections. For example `redis-benchmark` has a `-c` parameter for that, if you implement redis protocol. Alternatively, can still use `wrk`, just make sure that connection is not immediately closed. If it is, put a temporary timeout before handing the connection to the protocol handler, like this: ```rust,edition2018 # extern crate async_std; # use std::time::Duration; # use async_std::{ # net::{TcpListener, ToSocketAddrs}, # prelude::*, # }; # # type Result = std::result::Result>; # #async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { # let listener = TcpListener::bind(addr).await?; # let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { task::spawn(async { task::sleep(Duration::from_secs(10)).await; // 1 connection_loop(stream).await; }); } # Ok(()) # } ``` 1. Make sure the sleep coroutine is inside the spawned task, not in the loop. [`wrk`]: https://github.com/wg/wrk ### Handling Errors Manually Here is how basic accept loop could look like: ```rust,edition2018 # extern crate async_std; # use std::time::Duration; # use async_std::{ # net::{TcpListener, ToSocketAddrs}, # prelude::*, # }; # # type Result = std::result::Result>; # async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { let listener = TcpListener::bind(addr).await?; let mut incoming = listener.incoming(); while let Some(result) = incoming.next().await { let stream = match result { Err(ref e) if is_connection_error(e) => continue, // 1 Err(e) => { eprintln!("Error: {}. Pausing for 500ms.", e); // 3 task::sleep(Duration::from_millis(500)).await; // 2 continue; } Ok(s) => s, }; // body } Ok(()) } ``` 1. Ignore per-connection errors. 2. Sleep and continue on resource shortage. 3. It's important to log the message, because these errors commonly mean the misconfiguration of the system and are helpful for operations people running the application. Be sure to [test your application](#testing-application). ### External Crates The crate [`async-listen`] has a helper to achieve this task: ```rust,edition2018 # extern crate async_std; # extern crate async_listen; # use std::time::Duration; # use async_std::{ # net::{TcpListener, ToSocketAddrs}, # prelude::*, # }; # # type Result = std::result::Result>; # use async_listen::{ListenExt, error_hint}; async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { let listener = TcpListener::bind(addr).await?; let mut incoming = listener .incoming() .log_warnings(log_accept_error) // 1 .handle_errors(Duration::from_millis(500)); while let Some(socket) = incoming.next().await { // 2 // body } Ok(()) } fn log_accept_error(e: &io::Error) { eprintln!("Error: {}. Listener paused for 0.5s. {}", e, error_hint(e)) // 3 } ``` 1. Logs resource shortages (`async-listen` calls them warnings). If you use `log` crate or any other in your app this should go to the log. 2. Stream yields sockets without `Result` wrapper after `handle_errors` because all errors are already handled. 3. Together with the error we print a hint, which explains some errors for end users. For example, it recommends increasing open file limit and gives a link. [`async-listen`]: https://crates.io/crates/async-listen/ Be sure to [test your application](#testing-application). ## Connections Limit Even if you've applied everything described in [Handling Errors](#handling-errors) section, there is still a problem. Let's imagine you have a server that needs to open a file to process client request. At some point, you might encounter the following situation: 1. There are as many client connection as max file descriptors allowed for the application. 2. Listener gets `Too many open files` error so it sleeps. 3. Some client sends a request via the previously open connection. 4. Opening a file to serve request fails, because of the same `Too many open files` error, until some other client drops a connection. There are many more possible situations, this is just a small illustation that limiting number of connections is very useful. Generally, it's one of the ways to control resources used by a server and avoiding some kinds of deny of service (DoS) attacks. ### `async-listen` crate Limiting maximum number of simultaneous connections with [`async-listen`] looks like the following: ```rust,edition2018 # extern crate async_std; # extern crate async_listen; # use std::time::Duration; # use async_std::{ # net::{TcpListener, TcpStream, ToSocketAddrs}, # prelude::*, # }; # # type Result = std::result::Result>; # use async_listen::{ListenExt, Token, error_hint}; async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { let listener = TcpListener::bind(addr).await?; let mut incoming = listener .incoming() .log_warnings(log_accept_error) .handle_errors(Duration::from_millis(500)) // 1 .backpressure(100); while let Some((token, socket)) = incoming.next().await { // 2 task::spawn(async move { connection_loop(&token, stream).await; // 3 }); } Ok(()) } async fn connection_loop(_token: &Token, stream: TcpStream) { // 4 // ... } # fn log_accept_error(e: &io::Error) { # eprintln!("Error: {}. Listener paused for 0.5s. {}", e, error_hint(e)); # } ``` 1. We need to handle errors first, because [`backpressure`] helper expects stream of `TcpStream` rather than `Result`. 2. The token yielded by a new stream is what is counted by backpressure helper. I.e. if you drop a token, new connection can be established. 3. We give the connection loop a reference to token to bind token's lifetime to the lifetime of the connection. 4. The token itsellf in the function can be ignored, hence `_token` [`backpressure`]: https://docs.rs/async-listen/0.1.2/async_listen/trait.ListenExt.html#method.backpressure Be sure to [test this behavior](#testing-application). async-rs-async-std-57f61ae/docs/src/patterns/accepting-concurrent-requests.md000066400000000000000000000000251476537407000274750ustar00rootroot00000000000000# Accepting requests async-rs-async-std-57f61ae/docs/src/patterns/async-read-write.md000066400000000000000000000000231476537407000246630ustar00rootroot00000000000000# Async read/write async-rs-async-std-57f61ae/docs/src/patterns/background-tasks.md000066400000000000000000000000231476537407000247470ustar00rootroot00000000000000# Background Tasks async-rs-async-std-57f61ae/docs/src/patterns/fork-join.md000066400000000000000000000000141476537407000234030ustar00rootroot00000000000000# Fork/Join async-rs-async-std-57f61ae/docs/src/patterns/proper-shutdown.md000066400000000000000000000000221476537407000246640ustar00rootroot00000000000000# Proper Shutdown async-rs-async-std-57f61ae/docs/src/patterns/small-patterns.md000066400000000000000000000006641476537407000244660ustar00rootroot00000000000000# Small Patterns A collection of small, useful patterns. ## Splitting streams `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: ```rust,edition2018 # extern crate async_std; use async_std::{io, net::TcpStream}; async fn echo(stream: TcpStream) { let (reader, writer) = &mut (&stream, &stream); io::copy(reader, writer).await; } ``` async-rs-async-std-57f61ae/docs/src/patterns/testing.md000066400000000000000000000000121476537407000231600ustar00rootroot00000000000000# Testing async-rs-async-std-57f61ae/docs/src/security/000077500000000000000000000000001476537407000211775ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/src/security/index.md000066400000000000000000000010501476537407000226240ustar00rootroot00000000000000# Security Writing a highly performant async core library is a task involving some instances of unsafe code. We take great care in vetting all unsafe code included in `async-std` and do follow generally accepted practices. In the case that you find a security-related bug in our library, please get in touch with our [security contact][security-policy]. Patches improving the resilience of the library or the testing setup are happily accepted on our [github org][github]. [security-policy]: /security/policy [github]: https://github.com/async-rs async-rs-async-std-57f61ae/docs/src/security/policy.md000066400000000000000000000105751476537407000230300ustar00rootroot00000000000000# Policy Safety is one of the core principles of what we do, and to that end, we would like to ensure that async-std has a secure implementation. Thank you for taking the time to responsibly disclose any issues you find. All security bugs in async-std distribution should be reported by email to florian.gilcher@ferrous-systems.com. This list is delivered to a small security team. Your email will be acknowledged within 24 hours, and you’ll receive a more detailed response to your email within 48 hours indicating the next steps in handling your report. If you would like, you can encrypt your report using our public key. This key is also On MIT’s keyserver and reproduced below. Be sure to use a descriptive subject line to avoid having your report be missed. After the initial reply to your report, the security team will endeavor to keep you informed of the progress being made towards a fix and full announcement. As recommended by [RFPolicy][rf-policy], these updates will be sent at least every five days. In reality, this is more likely to be every 24-48 hours. If you have not received a reply to your email within 48 hours, or have not heard from the security team for the past five days, there are a few steps you can take (in order): * Post on our Community forums Please note that the discussion forums are public areas. When escalating in these venues, please do not discuss your issue. Simply say that you’re trying to get a hold of someone from the security team. [rf-policy]: https://en.wikipedia.org/wiki/RFPolicy ## Disclosure policy The async-std project has a 5 step disclosure process. * The security report is received and is assigned a primary handler. This person will coordinate the fix and release process. * The problem is confirmed and a list of all affected versions is determined. * Code is audited to find any potential similar problems. * Fixes are prepared for all releases which are still under maintenance. These fixes are not committed to the public repository but rather held locally pending the announcement. * On the embargo date, the changes are pushed to the public repository and new builds are deployed to crates.io. Within 6 hours, a copy of the advisory will be published on the the async.rs blog. This process can take some time, especially when coordination is required with maintainers of other projects. Every effort will be made to handle the bug in as timely a manner as possible, however it's important that we follow the release process above to ensure that the disclosure is handled in a consistent manner. ## Credits This policy is adapted from the [Rust project](https://www.rust-lang.org/policies/security) security policy. ## PGP Key ```text -----BEGIN PGP PUBLIC KEY BLOCK----- mQENBF1Wu/ABCADJaGt4HwSlqKB9BGHWYKZj/6mTMbmc29vsEOcCSQKo6myCf9zc sasWAttep4FAUDX+MJhVbBTSq9M1YVxp33Qh5AF0t9SnJZnbI+BZuGawcHDL01xE bE+8bcA2+szeTTUZCeWwsaoTd/2qmQKvpUCBQp7uBs/ITO/I2q7+xCGXaOHZwUKc H8SUBLd35nYFtjXAeejoZVkqG2qEjrc9bkZAwxFXi7Fw94QdkNLaCjNfKxZON/qP A3WOpyWPr3ERk5C5prjEAvrW8kdqpTRjdmzQjsr8UEXb5GGEOo93N4OLZVQ2mXt9 dfn++GOnOk7sTxvfiDH8Ru5o4zCtKgO+r5/LABEBAAG0UkZsb3JpYW4gR2lsY2hl ciAoU2VjdXJpdHkgY29udGFjdCBhc3luYy1zdGQpIDxmbG9yaWFuLmdpbGNoZXJA ZmVycm91cy1zeXN0ZW1zLmNvbT6JATgEEwECACIFAl1Wu/ACGwMGCwkIBwMCBhUI AgkKCwQWAgMBAh4BAheAAAoJEACXY97PwLtSc0AH/18yvrElVOkG0ADWX7l+JKHH nMQtYj0Auop8d6TuKBbpwtYhwELrQoITDMV7f2XEnchNsvYxAyBZhIISmXeJboE1 KzZD1O+4QPXRcXhj+QNsKQ680mrgZXgAI2Y4ptIW9Vyw3jiHu/ZVopvDAt4li+up 3fRJGPAvGu+tclpJmA+Xam23cDj89M7/wHHgKIyT59WgFwyCgibL+NHKwg2Unzou 9uyZQnq6hf62sQTWEZIAr9BQpKmluplNIJHDeECWzZoE9ucE2ZXsq5pq9qojsAMK yRdaFdpBcD/AxtrTKFeXGS7X7LqaljY/IFBEdJOqVNWpqSLjGWqjSLIEsc1AB0K5 AQ0EXVa78AEIAJMxBOEEW+2c3CcjFuUfcRsoBsFH3Vk+GwCbjIpNHq/eAvS1yy2L u10U5CcT5Xb6be3AeCYv00ZHVbEi6VwoauVCSX8qDjhVzQxvNLgQ1SduobjyF6t8 3M/wTija6NvMKszyw1l2oHepxSMLej1m49DyCDFNiZm5rjQcYnFT4J71syxViqHF v2fWCheTrHP3wfBAt5zyDet7IZd/EhYAK6xXEwr9nBPjfbaVexm2B8K6hOPNj0Bp OKm4rcOj7JYlcxrwhMvNnwEue7MqH1oXAsoaC1BW+qs4acp/hHpesweL6Rcg1pED OJUQd3UvRsqRK0EsorDu0oj5wt6Qp3ZEbPMAEQEAAYkBHwQYAQIACQUCXVa78AIb DAAKCRAAl2Pez8C7Uv8bB/9scRm2wvzHLbFtcEHaHvlKO1yYfSVqKqJzIKHc7pM2 +szM8JVRTxAbzK5Xih9SB5xlekixxO2UCJI5DkJ/ir/RCcg+/CAQ8iLm2UcYAgJD TocKiR5gjNAvUDI4tMrDLLdF+7+RCQGc7HBSxFiNBJVGAztGVh1+cQ0zaCX6Tt33 1EQtyRcPID0m6+ip5tCJN0dILC0YcwzXGrSgjB03JqItIyJEucdQz6UB84TIAGku JJl4tktgD9T7Rb5uzRhHCSbLy89DQVvCcKD4B94ffuDW3HO8n8utDusOiZuG4BUf WdFy6/gTLNiFbTzkq1BBJQMN1nBwGs1sn63RRgjumZ1N =dIcF -----END PGP PUBLIC KEY BLOCK----- ``` async-rs-async-std-57f61ae/docs/src/tutorial/000077500000000000000000000000001476537407000211735ustar00rootroot00000000000000async-rs-async-std-57f61ae/docs/src/tutorial/accept_loop.md000066400000000000000000000070671476537407000240170ustar00rootroot00000000000000## Writing an Accept Loop Let's implement the scaffold of the server: a loop that binds a TCP socket to an address and starts accepting connections. First of all, let's add required import boilerplate: ```rust,edition2018 # extern crate async_std; use async_std::{ prelude::*, // 1 task, // 2 net::{TcpListener, ToSocketAddrs}, // 3 }; type Result = std::result::Result>; // 4 ``` 1. `prelude` re-exports some traits required to work with futures and streams. 2. The `task` module roughly corresponds to the `std::thread` module, but tasks are much lighter weight. A single thread can run many tasks. 3. For the socket type, we use `TcpListener` from `async_std`, which is just like `std::net::TcpListener`, but is non-blocking and uses `async` API. 4. We will skip implementing comprehensive error handling in this example. To propagate the errors, we will use a boxed error trait object. Do you know that there's `From<&'_ str> for Box` implementation in stdlib, which allows you to use strings with `?` operator? Now we can write the server's accept loop: ```rust,edition2018 # extern crate async_std; # use async_std::{ # net::{TcpListener, ToSocketAddrs}, # prelude::*, # }; # # type Result = std::result::Result>; # async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { // 1 let listener = TcpListener::bind(addr).await?; // 2 let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { // 3 // TODO } Ok(()) } ``` 1. We mark the `accept_loop` function as `async`, which allows us to use `.await` syntax inside. 2. `TcpListener::bind` call returns a future, which we `.await` to extract the `Result`, and then `?` to get a `TcpListener`. Note how `.await` and `?` work nicely together. This is exactly how `std::net::TcpListener` works, but with `.await` added. Mirroring API of `std` is an explicit design goal of `async_std`. 3. Here, we would like to iterate incoming sockets, just how one would do in `std`: ```rust,edition2018,should_panic let listener: std::net::TcpListener = unimplemented!(); for stream in listener.incoming() { } ``` Unfortunately this doesn't quite work with `async` yet, because there's no support for `async` for-loops in the language yet. For this reason we have to implement the loop manually, by using `while let Some(item) = iter.next().await` pattern. Finally, let's add main: ```rust,edition2018 # extern crate async_std; # use async_std::{ # net::{TcpListener, ToSocketAddrs}, # prelude::*, # task, # }; # # type Result = std::result::Result>; # # async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { // 1 # let listener = TcpListener::bind(addr).await?; // 2 # let mut incoming = listener.incoming(); # while let Some(stream) = incoming.next().await { // 3 # // TODO # } # Ok(()) # } # // main fn run() -> Result<()> { let fut = accept_loop("127.0.0.1:8080"); task::block_on(fut) } ``` The crucial thing to realise that is in Rust, unlike other languages, calling an async function does **not** run any code. Async functions only construct futures, which are inert state machines. To start stepping through the future state-machine in an async function, you should use `.await`. In a non-async function, a way to execute a future is to hand it to the executor. In this case, we use `task::block_on` to execute a future on the current thread and block until it's done. async-rs-async-std-57f61ae/docs/src/tutorial/all_together.md000066400000000000000000000105111476537407000241640ustar00rootroot00000000000000## All Together At this point, we only need to start the broker to get a fully-functioning (in the happy case!) chat: ```rust,edition2018 # extern crate async_std; # extern crate futures; use async_std::{ io::BufReader, net::{TcpListener, TcpStream, ToSocketAddrs}, prelude::*, task, }; use futures::channel::mpsc; use futures::sink::SinkExt; use std::{ collections::hash_map::{HashMap, Entry}, sync::Arc, }; type Result = std::result::Result>; type Sender = mpsc::UnboundedSender; type Receiver = mpsc::UnboundedReceiver; // main fn run() -> Result<()> { task::block_on(accept_loop("127.0.0.1:8080")) } fn spawn_and_log_error(fut: F) -> task::JoinHandle<()> where F: Future> + Send + 'static, { task::spawn(async move { if let Err(e) = fut.await { eprintln!("{}", e) } }) } async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { let listener = TcpListener::bind(addr).await?; let (broker_sender, broker_receiver) = mpsc::unbounded(); // 1 let _broker_handle = task::spawn(broker_loop(broker_receiver)); let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { let stream = stream?; println!("Accepting from: {}", stream.peer_addr()?); spawn_and_log_error(connection_loop(broker_sender.clone(), stream)); } Ok(()) } async fn connection_loop(mut broker: Sender, stream: TcpStream) -> Result<()> { let stream = Arc::new(stream); // 2 let reader = BufReader::new(&*stream); let mut lines = reader.lines(); let name = match lines.next().await { None => Err("peer disconnected immediately")?, Some(line) => line?, }; broker.send(Event::NewPeer { name: name.clone(), stream: Arc::clone(&stream) }).await // 3 .unwrap(); while let Some(line) = lines.next().await { let line = line?; let (dest, msg) = match line.find(':') { None => continue, Some(idx) => (&line[..idx], line[idx + 1 ..].trim()), }; let dest: Vec = dest.split(',').map(|name| name.trim().to_string()).collect(); let msg: String = msg.to_string(); broker.send(Event::Message { // 4 from: name.clone(), to: dest, msg, }).await.unwrap(); } Ok(()) } async fn connection_writer_loop( mut messages: Receiver, stream: Arc, ) -> Result<()> { let mut stream = &*stream; while let Some(msg) = messages.next().await { stream.write_all(msg.as_bytes()).await?; } Ok(()) } #[derive(Debug)] enum Event { NewPeer { name: String, stream: Arc, }, Message { from: String, to: Vec, msg: String, }, } async fn broker_loop(mut events: Receiver) -> Result<()> { let mut peers: HashMap> = HashMap::new(); while let Some(event) = events.next().await { match event { Event::Message { from, to, msg } => { for addr in to { if let Some(peer) = peers.get_mut(&addr) { let msg = format!("from {}: {}\n", from, msg); peer.send(msg).await? } } } Event::NewPeer { name, stream} => { match peers.entry(name) { Entry::Occupied(..) => (), Entry::Vacant(entry) => { let (client_sender, client_receiver) = mpsc::unbounded(); entry.insert(client_sender); spawn_and_log_error(connection_writer_loop(client_receiver, stream)); } } } } } Ok(()) } ``` 1. Inside the `accept_loop`, we create the broker's channel and `task`. 2. Inside `connection_loop`, we need to wrap `TcpStream` into an `Arc`, to be able to share it with the `connection_writer_loop`. 3. On login, we notify the broker. Note that we `.unwrap` on send: broker should outlive all the clients and if that's not the case the broker probably panicked, so we can escalate the panic as well. 4. Similarly, we forward parsed messages to the broker, assuming that it is alive. async-rs-async-std-57f61ae/docs/src/tutorial/clean_shutdown.md000066400000000000000000000177131476537407000245430ustar00rootroot00000000000000## Clean Shutdown One of the problems of the current implementation is that it doesn't handle graceful shutdown. If we break from the accept loop for some reason, all in-flight tasks are just dropped on the floor. A more correct shutdown sequence would be: 1. Stop accepting new clients 2. Deliver all pending messages 3. Exit the process A clean shutdown in a channel based architecture is easy, although it can appear a magic trick at first. In Rust, receiver side of a channel is closed as soon as all senders are dropped. That is, as soon as producers exit and drop their senders, the rest of the system shuts down naturally. In `async_std` this translates to two rules: 1. Make sure that channels form an acyclic graph. 2. Take care to wait, in the correct order, until intermediate layers of the system process pending messages. In `a-chat`, we already have an unidirectional flow of messages: `reader -> broker -> writer`. However, we never wait for broker and writers, which might cause some messages to get dropped. Let's add waiting to the server: ```rust,edition2018 # extern crate async_std; # extern crate futures; # use async_std::{ # io::{self, BufReader}, # net::{TcpListener, TcpStream, ToSocketAddrs}, # prelude::*, # task, # }; # use futures::channel::mpsc; # use futures::sink::SinkExt; # use std::{ # collections::hash_map::{HashMap, Entry}, # sync::Arc, # }; # # type Result = std::result::Result>; # type Sender = mpsc::UnboundedSender; # type Receiver = mpsc::UnboundedReceiver; # # fn spawn_and_log_error(fut: F) -> task::JoinHandle<()> # where # F: Future> + Send + 'static, # { # task::spawn(async move { # if let Err(e) = fut.await { # eprintln!("{}", e) # } # }) # } # # # async fn connection_loop(mut broker: Sender, stream: TcpStream) -> Result<()> { # let stream = Arc::new(stream); // 2 # let reader = BufReader::new(&*stream); # let mut lines = reader.lines(); # # let name = match lines.next().await { # None => Err("peer disconnected immediately")?, # Some(line) => line?, # }; # broker.send(Event::NewPeer { name: name.clone(), stream: Arc::clone(&stream) }).await // 3 # .unwrap(); # # while let Some(line) = lines.next().await { # let line = line?; # let (dest, msg) = match line.find(':') { # None => continue, # Some(idx) => (&line[..idx], line[idx + 1 ..].trim()), # }; # let dest: Vec = dest.split(',').map(|name| name.trim().to_string()).collect(); # let msg: String = msg.trim().to_string(); # # broker.send(Event::Message { // 4 # from: name.clone(), # to: dest, # msg, # }).await.unwrap(); # } # Ok(()) # } # # async fn connection_writer_loop( # mut messages: Receiver, # stream: Arc, # ) -> Result<()> { # let mut stream = &*stream; # while let Some(msg) = messages.next().await { # stream.write_all(msg.as_bytes()).await?; # } # Ok(()) # } # # #[derive(Debug)] # enum Event { # NewPeer { # name: String, # stream: Arc, # }, # Message { # from: String, # to: Vec, # msg: String, # }, # } # # async fn broker_loop(mut events: Receiver) -> Result<()> { # let mut peers: HashMap> = HashMap::new(); # # while let Some(event) = events.next().await { # match event { # Event::Message { from, to, msg } => { # for addr in to { # if let Some(peer) = peers.get_mut(&addr) { # let msg = format!("from {}: {}\n", from, msg); # peer.send(msg).await? # } # } # } # Event::NewPeer { name, stream} => { # match peers.entry(name) { # Entry::Occupied(..) => (), # Entry::Vacant(entry) => { # let (client_sender, client_receiver) = mpsc::unbounded(); # entry.insert(client_sender); // 4 # spawn_and_log_error(connection_writer_loop(client_receiver, stream)); // 5 # } # } # } # } # } # Ok(()) # } # async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { let listener = TcpListener::bind(addr).await?; let (broker_sender, broker_receiver) = mpsc::unbounded(); let broker_handle = task::spawn(broker_loop(broker_receiver)); let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { let stream = stream?; println!("Accepting from: {}", stream.peer_addr()?); spawn_and_log_error(connection_loop(broker_sender.clone(), stream)); } drop(broker_sender); // 1 broker_handle.await?; // 5 Ok(()) } ``` And to the broker: ```rust,edition2018 # extern crate async_std; # extern crate futures; # use async_std::{ # io::{self, BufReader}, # net::{TcpListener, TcpStream, ToSocketAddrs}, # prelude::*, # task, # }; # use futures::channel::mpsc; # use futures::sink::SinkExt; # use std::{ # collections::hash_map::{HashMap, Entry}, # sync::Arc, # }; # # type Result = std::result::Result>; # type Sender = mpsc::UnboundedSender; # type Receiver = mpsc::UnboundedReceiver; # # async fn connection_writer_loop( # mut messages: Receiver, # stream: Arc, # ) -> Result<()> { # let mut stream = &*stream; # while let Some(msg) = messages.next().await { # stream.write_all(msg.as_bytes()).await?; # } # Ok(()) # } # # fn spawn_and_log_error(fut: F) -> task::JoinHandle<()> # where # F: Future> + Send + 'static, # { # task::spawn(async move { # if let Err(e) = fut.await { # eprintln!("{}", e) # } # }) # } # # #[derive(Debug)] # enum Event { # NewPeer { # name: String, # stream: Arc, # }, # Message { # from: String, # to: Vec, # msg: String, # }, # } # async fn broker_loop(mut events: Receiver) -> Result<()> { let mut writers = Vec::new(); let mut peers: HashMap> = HashMap::new(); while let Some(event) = events.next().await { // 2 match event { Event::Message { from, to, msg } => { for addr in to { if let Some(peer) = peers.get_mut(&addr) { let msg = format!("from {}: {}\n", from, msg); peer.send(msg).await? } } } Event::NewPeer { name, stream} => { match peers.entry(name) { Entry::Occupied(..) => (), Entry::Vacant(entry) => { let (client_sender, client_receiver) = mpsc::unbounded(); entry.insert(client_sender); let handle = spawn_and_log_error(connection_writer_loop(client_receiver, stream)); writers.push(handle); // 4 } } } } } drop(peers); // 3 for writer in writers { // 4 writer.await; } Ok(()) } ``` Notice what happens with all of the channels once we exit the accept loop: 1. First, we drop the main broker's sender. That way when the readers are done, there's no sender for the broker's channel, and the channel closes. 2. Next, the broker exits `while let Some(event) = events.next().await` loop. 3. It's crucial that, at this stage, we drop the `peers` map. This drops writer's senders. 4. Now we can join all of the writers. 5. Finally, we join the broker, which also guarantees that all the writes have terminated. async-rs-async-std-57f61ae/docs/src/tutorial/connecting_readers_and_writers.md000066400000000000000000000072061476537407000277570ustar00rootroot00000000000000 ## Connecting Readers and Writers So how do we make sure that messages read in `connection_loop` flow into the relevant `connection_writer_loop`? We should somehow maintain a `peers: HashMap>` map which allows a client to find destination channels. However, this map would be a bit of shared mutable state, so we'll have to wrap an `RwLock` over it and answer tough questions of what should happen if the client joins at the same moment as it receives a message. One trick to make reasoning about state simpler comes from the actor model. We can create a dedicated broker task which owns the `peers` map and communicates with other tasks using channels. By hiding `peers` inside such an "actor" task, we remove the need for mutexes and also make the serialization point explicit. The order of events "Bob sends message to Alice" and "Alice joins" is determined by the order of the corresponding events in the broker's event queue. ```rust,edition2018 # extern crate async_std; # extern crate futures; # use async_std::{ # net::TcpStream, # prelude::*, # task, # }; # use futures::channel::mpsc; # use futures::sink::SinkExt; # use std::sync::Arc; # # type Result = std::result::Result>; # type Sender = mpsc::UnboundedSender; # type Receiver = mpsc::UnboundedReceiver; # # async fn connection_writer_loop( # mut messages: Receiver, # stream: Arc, # ) -> Result<()> { # let mut stream = &*stream; # while let Some(msg) = messages.next().await { # stream.write_all(msg.as_bytes()).await?; # } # Ok(()) # } # # fn spawn_and_log_error(fut: F) -> task::JoinHandle<()> # where # F: Future> + Send + 'static, # { # task::spawn(async move { # if let Err(e) = fut.await { # eprintln!("{}", e) # } # }) # } # use std::collections::hash_map::{Entry, HashMap}; #[derive(Debug)] enum Event { // 1 NewPeer { name: String, stream: Arc, }, Message { from: String, to: Vec, msg: String, }, } async fn broker_loop(mut events: Receiver) -> Result<()> { let mut peers: HashMap> = HashMap::new(); // 2 while let Some(event) = events.next().await { match event { Event::Message { from, to, msg } => { // 3 for addr in to { if let Some(peer) = peers.get_mut(&addr) { let msg = format!("from {}: {}\n", from, msg); peer.send(msg).await? } } } Event::NewPeer { name, stream } => { match peers.entry(name) { Entry::Occupied(..) => (), Entry::Vacant(entry) => { let (client_sender, client_receiver) = mpsc::unbounded(); entry.insert(client_sender); // 4 spawn_and_log_error(connection_writer_loop(client_receiver, stream)); // 5 } } } } } Ok(()) } ``` 1. The broker task should handle two types of events: a message or an arrival of a new peer. 2. The internal state of the broker is a `HashMap`. Note how we don't need a `Mutex` here and can confidently say, at each iteration of the broker's loop, what is the current set of peers 3. To handle a message, we send it over a channel to each destination 4. To handle a new peer, we first register it in the peer's map ... 5. ... and then spawn a dedicated task to actually write the messages to the socket. async-rs-async-std-57f61ae/docs/src/tutorial/handling_disconnection.md000066400000000000000000000256061476537407000262310ustar00rootroot00000000000000## Handling Disconnections Currently, we only ever _add_ new peers to the map. This is clearly wrong: if a peer closes connection to the chat, we should not try to send any more messages to it. One subtlety with handling disconnection is that we can detect it either in the reader's task, or in the writer's task. The most obvious solution here is to just remove the peer from the `peers` map in both cases, but this would be wrong. If _both_ read and write fail, we'll remove the peer twice, but it can be the case that the peer reconnected between the two failures! To fix this, we will only remove the peer when the write side finishes. If the read side finishes we will notify the write side that it should stop as well. That is, we need to add an ability to signal shutdown for the writer task. One way to approach this is a `shutdown: Receiver<()>` channel. There's a more minimal solution however, which makes clever use of RAII. Closing a channel is a synchronization event, so we don't need to send a shutdown message, we can just drop the sender. This way, we statically guarantee that we issue shutdown exactly once, even if we early return via `?` or panic. First, let's add a shutdown channel to the `connection_loop`: ```rust,edition2018 # extern crate async_std; # extern crate futures; # use async_std::net::TcpStream; # use futures::channel::mpsc; # use futures::sink::SinkExt; # use std::sync::Arc; # # type Result = std::result::Result>; # type Sender = mpsc::UnboundedSender; # type Receiver = mpsc::UnboundedReceiver; # #[derive(Debug)] enum Void {} // 1 #[derive(Debug)] enum Event { NewPeer { name: String, stream: Arc, shutdown: Receiver, // 2 }, Message { from: String, to: Vec, msg: String, }, } async fn connection_loop(mut broker: Sender, stream: Arc) -> Result<()> { // ... # let name: String = unimplemented!(); let (_shutdown_sender, shutdown_receiver) = mpsc::unbounded::(); // 3 broker.send(Event::NewPeer { name: name.clone(), stream: Arc::clone(&stream), shutdown: shutdown_receiver, }).await.unwrap(); // ... # unimplemented!() } ``` 1. To enforce that no messages are sent along the shutdown channel, we use an uninhabited type. 2. We pass the shutdown channel to the writer task. 3. In the reader, we create a `_shutdown_sender` whose only purpose is to get dropped. In the `connection_writer_loop`, we now need to choose between shutdown and message channels. We use the `select` macro for this purpose: ```rust,edition2018 # extern crate async_std; # extern crate futures; # use async_std::{net::TcpStream, prelude::*}; # use futures::channel::mpsc; use futures::{select, FutureExt}; # use std::sync::Arc; # type Receiver = mpsc::UnboundedReceiver; # type Result = std::result::Result>; # type Sender = mpsc::UnboundedSender; # #[derive(Debug)] # enum Void {} // 1 async fn connection_writer_loop( messages: &mut Receiver, stream: Arc, shutdown: Receiver, // 1 ) -> Result<()> { let mut stream = &*stream; let mut messages = messages.fuse(); let mut shutdown = shutdown.fuse(); loop { // 2 select! { msg = messages.next().fuse() => match msg { // 3 Some(msg) => stream.write_all(msg.as_bytes()).await?, None => break, }, void = shutdown.next().fuse() => match void { Some(void) => match void {}, // 4 None => break, } } } Ok(()) } ``` 1. We add shutdown channel as an argument. 2. Because of `select`, we can't use a `while let` loop, so we desugar it further into a `loop`. 3. Function fuse() is used to turn any `Stream` into a `FusedStream`. This is used for fusing a stream such that poll_next will never again be called once it has finished. 4. In the shutdown case we use `match void {}` as a statically-checked `unreachable!()`. Another problem is that between the moment we detect disconnection in `connection_writer_loop` and the moment when we actually remove the peer from the `peers` map, new messages might be pushed into the peer's channel. To not lose these messages completely, we'll return the messages channel back to the broker. This also allows us to establish a useful invariant that the message channel strictly outlives the peer in the `peers` map, and makes the broker itself infallible. ## Final Code The final code looks like this: ```rust,edition2018 # extern crate async_std; # extern crate futures; use async_std::{ io::BufReader, net::{TcpListener, TcpStream, ToSocketAddrs}, prelude::*, task, }; use futures::channel::mpsc; use futures::sink::SinkExt; use futures::{select, FutureExt}; use std::{ collections::hash_map::{Entry, HashMap}, future::Future, sync::Arc, }; type Result = std::result::Result>; type Sender = mpsc::UnboundedSender; type Receiver = mpsc::UnboundedReceiver; #[derive(Debug)] enum Void {} // main fn run() -> Result<()> { task::block_on(accept_loop("127.0.0.1:8080")) } async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { let listener = TcpListener::bind(addr).await?; let (broker_sender, broker_receiver) = mpsc::unbounded(); let broker_handle = task::spawn(broker_loop(broker_receiver)); let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { let stream = stream?; println!("Accepting from: {}", stream.peer_addr()?); spawn_and_log_error(connection_loop(broker_sender.clone(), stream)); } drop(broker_sender); broker_handle.await; Ok(()) } async fn connection_loop(mut broker: Sender, stream: TcpStream) -> Result<()> { let stream = Arc::new(stream); let reader = BufReader::new(&*stream); let mut lines = reader.lines(); let name = match lines.next().await { None => Err("peer disconnected immediately")?, Some(line) => line?, }; let (_shutdown_sender, shutdown_receiver) = mpsc::unbounded::(); broker.send(Event::NewPeer { name: name.clone(), stream: Arc::clone(&stream), shutdown: shutdown_receiver, }).await.unwrap(); while let Some(line) = lines.next().await { let line = line?; let (dest, msg) = match line.find(':') { None => continue, Some(idx) => (&line[..idx], line[idx + 1 ..].trim()), }; let dest: Vec = dest.split(',').map(|name| name.trim().to_string()).collect(); let msg: String = msg.trim().to_string(); broker.send(Event::Message { from: name.clone(), to: dest, msg, }).await.unwrap(); } Ok(()) } async fn connection_writer_loop( messages: &mut Receiver, stream: Arc, shutdown: Receiver, ) -> Result<()> { let mut stream = &*stream; let mut messages = messages.fuse(); let mut shutdown = shutdown.fuse(); loop { select! { msg = messages.next().fuse() => match msg { Some(msg) => stream.write_all(msg.as_bytes()).await?, None => break, }, void = shutdown.next().fuse() => match void { Some(void) => match void {}, None => break, } } } Ok(()) } #[derive(Debug)] enum Event { NewPeer { name: String, stream: Arc, shutdown: Receiver, }, Message { from: String, to: Vec, msg: String, }, } async fn broker_loop(events: Receiver) { let (disconnect_sender, mut disconnect_receiver) = // 1 mpsc::unbounded::<(String, Receiver)>(); let mut peers: HashMap> = HashMap::new(); let mut events = events.fuse(); loop { let event = select! { event = events.next().fuse() => match event { None => break, // 2 Some(event) => event, }, disconnect = disconnect_receiver.next().fuse() => { let (name, _pending_messages) = disconnect.unwrap(); // 3 assert!(peers.remove(&name).is_some()); continue; }, }; match event { Event::Message { from, to, msg } => { for addr in to { if let Some(peer) = peers.get_mut(&addr) { let msg = format!("from {}: {}\n", from, msg); peer.send(msg).await .unwrap() // 6 } } } Event::NewPeer { name, stream, shutdown } => { match peers.entry(name.clone()) { Entry::Occupied(..) => (), Entry::Vacant(entry) => { let (client_sender, mut client_receiver) = mpsc::unbounded(); entry.insert(client_sender); let mut disconnect_sender = disconnect_sender.clone(); spawn_and_log_error(async move { let res = connection_writer_loop(&mut client_receiver, stream, shutdown).await; disconnect_sender.send((name, client_receiver)).await // 4 .unwrap(); res }); } } } } } drop(peers); // 5 drop(disconnect_sender); // 6 while let Some((_name, _pending_messages)) = disconnect_receiver.next().await { } } fn spawn_and_log_error(fut: F) -> task::JoinHandle<()> where F: Future> + Send + 'static, { task::spawn(async move { if let Err(e) = fut.await { eprintln!("{}", e) } }) } ``` 1. In the broker, we create a channel to reap disconnected peers and their undelivered messages. 2. The broker's main loop exits when the input events channel is exhausted (that is, when all readers exit). 3. Because broker itself holds a `disconnect_sender`, we know that the disconnections channel can't be fully drained in the main loop. 4. We send peer's name and pending messages to the disconnections channel in both the happy and the not-so-happy path. Again, we can safely unwrap because the broker outlives writers. 5. We drop `peers` map to close writers' messages channel and shut down the writers for sure. It is not strictly necessary in the current setup, where the broker waits for readers' shutdown anyway. However, if we add a server-initiated shutdown (for example, kbd:[ctrl+c] handling), this will be a way for the broker to shutdown the writers. 6. Finally, we close and drain the disconnections channel. async-rs-async-std-57f61ae/docs/src/tutorial/implementing_a_client.md000066400000000000000000000043651476537407000260530ustar00rootroot00000000000000## Implementing a client Since the protocol is line-based, implementing a client for the chat is straightforward: * Lines read from stdin should be sent over the socket. * Lines read from the socket should be echoed to stdout. Although async does not significantly affect client performance (as unlike the server, the client interacts solely with one user and only needs limited concurrency), async is still useful for managing concurrency! The client has to read from stdin and the socket *simultaneously*. Programming this with threads is cumbersome, especially when implementing a clean shutdown. With async, the `select!` macro is all that is needed. ```rust,edition2018 # extern crate async_std; # extern crate futures; use async_std::{ io::{stdin, BufReader}, net::{TcpStream, ToSocketAddrs}, prelude::*, task, }; use futures::{select, FutureExt}; type Result = std::result::Result>; // main fn run() -> Result<()> { task::block_on(try_run("127.0.0.1:8080")) } async fn try_run(addr: impl ToSocketAddrs) -> Result<()> { let stream = TcpStream::connect(addr).await?; let (reader, mut writer) = (&stream, &stream); // 1 let mut lines_from_server = BufReader::new(reader).lines().fuse(); // 2 let mut lines_from_stdin = BufReader::new(stdin()).lines().fuse(); // 2 loop { select! { // 3 line = lines_from_server.next().fuse() => match line { Some(line) => { let line = line?; println!("{}", line); }, None => break, }, line = lines_from_stdin.next().fuse() => match line { Some(line) => { let line = line?; writer.write_all(line.as_bytes()).await?; writer.write_all(b"\n").await?; } None => break, } } } Ok(()) } ``` 1. Here we split `TcpStream` into read and write halves: there's `impl AsyncRead for &'_ TcpStream`, just like the one in std. 2. We create a stream of lines for both the socket and stdin. 3. In the main select loop, we print the lines we receive from the server and send the lines we read from the console. async-rs-async-std-57f61ae/docs/src/tutorial/index.md000066400000000000000000000007461476537407000226330ustar00rootroot00000000000000# Tutorial: Writing a chat Nothing is simpler than creating a chat server, right? Not quite, chat servers expose you to all the fun of asynchronous programming: How will the server handle clients connecting concurrently? How will it handle them disconnecting? How will it distribute the messages? This tutorial explains how to write a chat server in `async-std`. You can also find the tutorial in [our repository](https://github.com/async-rs/async-std/blob/HEAD/examples/a-chat). async-rs-async-std-57f61ae/docs/src/tutorial/receiving_messages.md000066400000000000000000000112301476537407000253540ustar00rootroot00000000000000## Receiving messages Let's implement the receiving part of the protocol. We need to: 1. split incoming `TcpStream` on `\n` and decode bytes as utf-8 2. interpret the first line as a login 3. parse the rest of the lines as a `login: message` ```rust,edition2018 # extern crate async_std; # use async_std::{ # net::{TcpListener, ToSocketAddrs}, # prelude::*, # task, # }; # # type Result = std::result::Result>; # use async_std::{ io::BufReader, net::TcpStream, }; async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { let listener = TcpListener::bind(addr).await?; let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { let stream = stream?; println!("Accepting from: {}", stream.peer_addr()?); let _handle = task::spawn(connection_loop(stream)); // 1 } Ok(()) } async fn connection_loop(stream: TcpStream) -> Result<()> { let reader = BufReader::new(&stream); // 2 let mut lines = reader.lines(); let name = match lines.next().await { // 3 None => Err("peer disconnected immediately")?, Some(line) => line?, }; println!("name = {}", name); while let Some(line) = lines.next().await { // 4 let line = line?; let (dest, msg) = match line.find(':') { // 5 None => continue, Some(idx) => (&line[..idx], line[idx + 1 ..].trim()), }; let dest: Vec = dest.split(',').map(|name| name.trim().to_string()).collect(); let msg: String = msg.to_string(); } Ok(()) } ``` 1. We use `task::spawn` function to spawn an independent task for working with each client. That is, after accepting the client the `accept_loop` immediately starts waiting for the next one. This is the core benefit of event-driven architecture: we serve many clients concurrently, without spending many hardware threads. 2. Luckily, the "split byte stream into lines" functionality is already implemented. `.lines()` call returns a stream of `String`'s. 3. We get the first line -- login 4. And, once again, we implement a manual async for loop. 5. Finally, we parse each line into a list of destination logins and the message itself. ## Managing Errors One serious problem in the above solution is that, while we correctly propagate errors in the `connection_loop`, we just drop the error on the floor afterwards! That is, `task::spawn` does not return an error immediately (it can't, it needs to run the future to completion first), only after it is joined. We can "fix" it by waiting for the task to be joined, like this: ```rust,edition2018 # #![feature(async_closure)] # extern crate async_std; # use async_std::{ # io::BufReader, # net::{TcpListener, TcpStream, ToSocketAddrs}, # prelude::*, # task, # }; # # type Result = std::result::Result>; # # async fn connection_loop(stream: TcpStream) -> Result<()> { # let reader = BufReader::new(&stream); // 2 # let mut lines = reader.lines(); # # let name = match lines.next().await { // 3 # None => Err("peer disconnected immediately")?, # Some(line) => line?, # }; # println!("name = {}", name); # # while let Some(line) = lines.next().await { // 4 # let line = line?; # let (dest, msg) = match line.find(':') { // 5 # None => continue, # Some(idx) => (&line[..idx], line[idx + 1 ..].trim()), # }; # let dest: Vec = dest.split(',').map(|name| name.trim().to_string()).collect(); # let msg: String = msg.trim().to_string(); # } # Ok(()) # } # # async move |stream| { let handle = task::spawn(connection_loop(stream)); handle.await? # }; ``` The `.await` waits until the client finishes, and `?` propagates the result. There are two problems with this solution however! *First*, because we immediately await the client, we can only handle one client at a time, and that completely defeats the purpose of async! *Second*, if a client encounters an IO error, the whole server immediately exits. That is, a flaky internet connection of one peer brings down the whole chat room! A correct way to handle client errors in this case is log them, and continue serving other clients. So let's use a helper function for this: ```rust,edition2018 # extern crate async_std; # use async_std::{ # io, # prelude::*, # task, # }; fn spawn_and_log_error(fut: F) -> task::JoinHandle<()> where F: Future> + Send + 'static, { task::spawn(async move { if let Err(e) = fut.await { eprintln!("{}", e) } }) } ``` async-rs-async-std-57f61ae/docs/src/tutorial/sending_messages.md000066400000000000000000000037421476537407000250410ustar00rootroot00000000000000## Sending Messages Now it's time to implement the other half -- sending messages. A most obvious way to implement sending is to give each `connection_loop` access to the write half of `TcpStream` of each other clients. That way, a client can directly `.write_all` a message to recipients. However, this would be wrong: if Alice sends `bob: foo`, and Charley sends `bob: bar`, Bob might actually receive `fobaor`. Sending a message over a socket might require several syscalls, so two concurrent `.write_all`'s might interfere with each other! As a rule of thumb, only a single task should write to each `TcpStream`. So let's create a `connection_writer_loop` task which receives messages over a channel and writes them to the socket. This task would be the point of serialization of messages. if Alice and Charley send two messages to Bob at the same time, Bob will see the messages in the same order as they arrive in the channel. ```rust,edition2018 # extern crate async_std; # extern crate futures; # use async_std::{ # net::TcpStream, # prelude::*, # }; use futures::channel::mpsc; // 1 use futures::sink::SinkExt; use std::sync::Arc; # type Result = std::result::Result>; type Sender = mpsc::UnboundedSender; // 2 type Receiver = mpsc::UnboundedReceiver; async fn connection_writer_loop( mut messages: Receiver, stream: Arc, // 3 ) -> Result<()> { let mut stream = &*stream; while let Some(msg) = messages.next().await { stream.write_all(msg.as_bytes()).await?; } Ok(()) } ``` 1. We will use channels from the `futures` crate. 2. For simplicity, we will use `unbounded` channels, and won't be discussing backpressure in this tutorial. 3. As `connection_loop` and `connection_writer_loop` share the same `TcpStream`, we need to put it into an `Arc`. Note that because `client` only reads from the stream and `connection_writer_loop` only writes to the stream, we don't get a race here. async-rs-async-std-57f61ae/docs/src/tutorial/specification.md000066400000000000000000000021731476537407000243400ustar00rootroot00000000000000# Specification and Getting Started ## Specification The chat uses a simple text protocol over TCP. The protocol consists of utf-8 messages, separated by `\n`. The client connects to the server and sends login as a first line. After that, the client can send messages to other clients using the following syntax: ```text login1, login2, ... loginN: message ``` Each of the specified clients then receives a `from login: message` message. A possible session might look like this ```text On Alice's computer: | On Bob's computer: > alice | > bob > bob: hello < from alice: hello | > alice, bob: hi! < from bob: hi! < from bob: hi! | ``` The main challenge for the chat server is keeping track of many concurrent connections. The main challenge for the chat client is managing concurrent outgoing messages, incoming messages and user's typing. ## Getting Started Let's create a new Cargo project: ```bash $ cargo new a-chat $ cd a-chat ``` Add the following lines to `Cargo.toml`: ```toml [dependencies] futures = "0.3.0" async-std = "1" ``` async-rs-async-std-57f61ae/examples/000077500000000000000000000000001476537407000174275ustar00rootroot00000000000000async-rs-async-std-57f61ae/examples/README.md000066400000000000000000000071171476537407000207140ustar00rootroot00000000000000# Examples This directory contains example code that makes use of `async-std`, each of which can be run from the command line. ##### [Hello World][hello-world] Spawns a task that says hello. ``` cargo run --example hello-world ``` ##### [Line Count][line-count] Counts the number of lines in a file given as an argument. ```shell cargo run --example line-count -- ./Cargo.toml ``` ##### [List Dir][list-dir] Lists files in a directory given as an argument. ```shell cargo run --example list-dir -- . ``` ##### [Logging][logging] Prints the runtime's execution log on the standard output. ```shell cargo run --example logging ``` ##### [Print File][print-file] Prints a file given as an argument to stdout. ```shell cargo run --example print-file ./Cargo.toml ``` ##### [Socket Timeouts][socket-timeouts] Prints response of GET request made to TCP server with 5 second socket timeout ```shell cargo run --example socket-timeouts ``` ##### [Stdin Echo][stdin-echo] Echoes lines read on stdin to stdout. ```shell cargo run --example stdin-echo ``` ##### [Stdin Timeout][stdin-timeout] Reads a line from stdin, or exits with an error if nothing is read in 5 seconds. ```shell cargo run --example stdin-timeout ``` ##### [Surf Web][surf-web] Sends an HTTP request to the Rust website. ```shell cargo run --example surf-web ``` ##### [Task Local][task-local] Creates a task-local value. ```shell cargo run --example task-local ``` ##### [Task Name][task-name] Spawns a named task that prints its name. ```shell cargo run --example task-name ``` ##### [TCP Client][tcp-client] Connects to Localhost over TCP. First, start the echo server: ```shell cargo run --example tcp-echo ``` Then run the client: ```shell cargo run --example tcp-client ``` ##### [TCP Echo][tcp-echo] TCP echo server. Start the echo server: ```shell cargo run --example tcp-echo ``` Make requests by running the client example: ```shell cargo run --example tcp-client ``` ##### [UDP Client][udp-client] Connects to Localhost over UDP. First, start the echo server: ```shell cargo run --example udp-echo ``` Then run the client: ```shell cargo run --example udp-client ``` ##### [UDP Echo][udp-echo] UDP echo server. Start the echo server: ```shell cargo run --example udp-echo ``` Make requests by running the client example: ```shell cargo run --example udp-client ``` [hello-world]: https://github.com/async-rs/async-std/blob/HEAD/examples/hello-world.rs [line-count]: https://github.com/async-rs/async-std/blob/HEAD/examples/line-count.rs [list-dir]: https://github.com/async-rs/async-std/blob/HEAD/examples/list-dir.rs [logging]: https://github.com/async-rs/async-std/blob/HEAD/examples/logging.rs [print-file]: https://github.com/async-rs/async-std/blob/HEAD/examples/print-file.rs [socket-timeouts]: https://github.com/async-rs/async-std/blob/HEAD/examples/socket-timeouts.rs [stdin-echo]: https://github.com/async-rs/async-std/blob/HEAD/examples/stdin-echo.rs [stdin-timeout]: https://github.com/async-rs/async-std/blob/HEAD/examples/stdin-timeout.rs [surf-web]: https://github.com/async-rs/async-std/blob/HEAD/examples/surf-web.rs [task-local]: https://github.com/async-rs/async-std/blob/HEAD/examples/task-local.rs [task-name]: https://github.com/async-rs/async-std/blob/HEAD/examples/task-name.rs [tcp-client]: https://github.com/async-rs/async-std/blob/HEAD/examples/tcp-client.rs [tcp-echo]: https://github.com/async-rs/async-std/blob/HEAD/examples/tcp-echo.rs [udp-client]: https://github.com/async-rs/async-std/blob/HEAD/examples/udp-client.rs [udp-echo]: https://github.com/async-rs/async-std/blob/HEAD/examples/udp-echo.rs async-rs-async-std-57f61ae/examples/a-chat/000077500000000000000000000000001476537407000205645ustar00rootroot00000000000000async-rs-async-std-57f61ae/examples/a-chat/client.rs000066400000000000000000000024661476537407000224200ustar00rootroot00000000000000use futures::select; use futures::FutureExt; use async_std::{ io::{stdin, BufReader}, net::{TcpStream, ToSocketAddrs}, prelude::*, task, }; type Result = std::result::Result>; pub(crate) fn main() -> Result<()> { task::block_on(try_main("127.0.0.1:8080")) } async fn try_main(addr: impl ToSocketAddrs) -> Result<()> { let stream = TcpStream::connect(addr).await?; let (reader, mut writer) = (&stream, &stream); let reader = BufReader::new(reader); let mut lines_from_server = futures::StreamExt::fuse(reader.lines()); let stdin = BufReader::new(stdin()); let mut lines_from_stdin = futures::StreamExt::fuse(stdin.lines()); loop { select! { line = lines_from_server.next().fuse() => match line { Some(line) => { let line = line?; println!("{}", line); }, None => break, }, line = lines_from_stdin.next().fuse() => match line { Some(line) => { let line = line?; writer.write_all(line.as_bytes()).await?; writer.write_all(b"\n").await?; } None => break, } } } Ok(()) } async-rs-async-std-57f61ae/examples/a-chat/main.rs000066400000000000000000000006261476537407000220620ustar00rootroot00000000000000mod client; mod server; type Result = std::result::Result>; fn main() -> Result<()> { let mut args = std::env::args(); match (args.nth(1).as_ref().map(String::as_str), args.next()) { (Some("client"), None) => client::main(), (Some("server"), None) => server::main(), _ => Err("Usage: a-chat [client|server]".into()), } } async-rs-async-std-57f61ae/examples/a-chat/server.rs000066400000000000000000000125441476537407000224460ustar00rootroot00000000000000use std::{ collections::hash_map::{Entry, HashMap}, sync::Arc, }; use futures::{channel::mpsc, select, FutureExt, SinkExt}; use async_std::{ io::BufReader, net::{TcpListener, TcpStream, ToSocketAddrs}, prelude::*, task, }; type Result = std::result::Result>; type Sender = mpsc::UnboundedSender; type Receiver = mpsc::UnboundedReceiver; #[derive(Debug)] enum Void {} pub(crate) fn main() -> Result<()> { task::block_on(accept_loop("127.0.0.1:8080")) } async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> { let listener = TcpListener::bind(addr).await?; let (broker_sender, broker_receiver) = mpsc::unbounded(); let broker = task::spawn(broker_loop(broker_receiver)); let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { let stream = stream?; println!("Accepting from: {}", stream.peer_addr()?); spawn_and_log_error(connection_loop(broker_sender.clone(), stream)); } drop(broker_sender); broker.await; Ok(()) } async fn connection_loop(mut broker: Sender, stream: TcpStream) -> Result<()> { let stream = Arc::new(stream); let reader = BufReader::new(&*stream); let mut lines = reader.lines(); let name = match lines.next().await { None => return Err("peer disconnected immediately".into()), Some(line) => line?, }; let (_shutdown_sender, shutdown_receiver) = mpsc::unbounded::(); broker .send(Event::NewPeer { name: name.clone(), stream: Arc::clone(&stream), shutdown: shutdown_receiver, }) .await .unwrap(); while let Some(line) = lines.next().await { let line = line?; let (dest, msg) = match line.find(':') { None => continue, Some(idx) => (&line[..idx], line[idx + 1..].trim()), }; let dest: Vec = dest .split(',') .map(|name| name.trim().to_string()) .collect(); let msg: String = msg.trim().to_string(); broker .send(Event::Message { from: name.clone(), to: dest, msg, }) .await .unwrap(); } Ok(()) } async fn connection_writer_loop( messages: &mut Receiver, stream: Arc, mut shutdown: Receiver, ) -> Result<()> { let mut stream = &*stream; loop { select! { msg = messages.next().fuse() => match msg { Some(msg) => stream.write_all(msg.as_bytes()).await?, None => break, }, void = shutdown.next().fuse() => match void { #[allow(unreachable_patterns)] Some(void) => match void {}, None => break, } } } Ok(()) } #[derive(Debug)] enum Event { NewPeer { name: String, stream: Arc, shutdown: Receiver, }, Message { from: String, to: Vec, msg: String, }, } async fn broker_loop(mut events: Receiver) { let (disconnect_sender, mut disconnect_receiver) = mpsc::unbounded::<(String, Receiver)>(); let mut peers: HashMap> = HashMap::new(); loop { let event = select! { event = events.next().fuse() => match event { None => break, Some(event) => event, }, disconnect = disconnect_receiver.next().fuse() => { let (name, _pending_messages) = disconnect.unwrap(); assert!(peers.remove(&name).is_some()); continue; }, }; match event { Event::Message { from, to, msg } => { for addr in to { if let Some(peer) = peers.get_mut(&addr) { let msg = format!("from {}: {}\n", from, msg); peer.send(msg).await.unwrap(); } } } Event::NewPeer { name, stream, shutdown, } => match peers.entry(name.clone()) { Entry::Occupied(..) => (), Entry::Vacant(entry) => { let (client_sender, mut client_receiver) = mpsc::unbounded(); entry.insert(client_sender); let mut disconnect_sender = disconnect_sender.clone(); spawn_and_log_error(async move { let res = connection_writer_loop(&mut client_receiver, stream, shutdown).await; disconnect_sender .send((name, client_receiver)) .await .unwrap(); res }); } }, } } drop(peers); drop(disconnect_sender); while let Some((_name, _pending_messages)) = disconnect_receiver.next().await {} } fn spawn_and_log_error(fut: F) -> task::JoinHandle<()> where F: Future> + Send + 'static, { task::spawn(async move { if let Err(e) = fut.await { eprintln!("{}", e) } }) } async-rs-async-std-57f61ae/examples/hello-world.rs000066400000000000000000000002331476537407000222230ustar00rootroot00000000000000//! Spawns a task that says hello. use async_std::task; async fn say_hi() { println!("Hello, world!"); } fn main() { task::block_on(say_hi()) } async-rs-async-std-57f61ae/examples/line-count.rs000066400000000000000000000011711476537407000220520ustar00rootroot00000000000000//! Counts the number of lines in a file given as an argument. use std::env::args; use async_std::fs::File; use async_std::io::{self, BufReader}; use async_std::prelude::*; use async_std::task; fn main() -> io::Result<()> { let path = args().nth(1).expect("missing path argument"); task::block_on(async { let file = File::open(&path).await?; let mut lines = BufReader::new(file).lines(); let mut count = 0u64; while let Some(line) = lines.next().await { line?; count += 1; } println!("The file contains {} lines.", count); Ok(()) }) } async-rs-async-std-57f61ae/examples/list-dir.rs000066400000000000000000000010001476537407000215130ustar00rootroot00000000000000//! Lists files in a directory given as an argument. use std::env::args; use async_std::fs; use async_std::io; use async_std::prelude::*; use async_std::task; fn main() -> io::Result<()> { let path = args().nth(1).expect("missing path argument"); task::block_on(async { let mut dir = fs::read_dir(&path).await?; while let Some(res) = dir.next().await { let entry = res?; println!("{}", entry.file_name().to_string_lossy()); } Ok(()) }) } async-rs-async-std-57f61ae/examples/logging.rs000066400000000000000000000004531476537407000214250ustar00rootroot00000000000000//! Prints the runtime's execution log on the standard output. use async_std::task; fn main() { femme::with_level(log::LevelFilter::Trace); task::block_on(async { let handle = task::spawn(async { log::info!("Hello world!"); }); handle.await; }) } async-rs-async-std-57f61ae/examples/print-file.rs000066400000000000000000000015151476537407000220500ustar00rootroot00000000000000//! Prints a file given as an argument to stdout. use std::env::args; use async_std::fs::File; use async_std::io; use async_std::prelude::*; use async_std::task; const LEN: usize = 16 * 1024; // 16 Kb fn main() -> io::Result<()> { let path = args().nth(1).expect("missing path argument"); task::block_on(async { let mut file = File::open(&path).await?; let mut stdout = io::stdout(); let mut buf = vec![0u8; LEN]; loop { // Read a buffer from the file. let n = file.read(&mut buf).await?; // If this is the end of file, clean up and return. if n == 0 { stdout.flush().await?; return Ok(()); } // Write the buffer into stdout. stdout.write_all(&buf[..n]).await?; } }) } async-rs-async-std-57f61ae/examples/socket-timeouts.rs000066400000000000000000000013601476537407000231340ustar00rootroot00000000000000//! Prints response of GET request made to TCP server with 5 second socket timeout use std::time::Duration; use async_std::{io, net::TcpStream, prelude::*, task}; async fn get() -> io::Result> { let mut stream = TcpStream::connect("example.com:80").await?; stream .write_all(b"GET /index.html HTTP/1.0\r\n\r\n") .await?; let mut buf = vec![]; io::timeout(Duration::from_secs(5), async move { stream.read_to_end(&mut buf).await?; Ok(buf) }) .await } fn main() { task::block_on(async { let raw_response = get().await.expect("request"); let response = String::from_utf8(raw_response).expect("utf8 conversion"); println!("received: {}", response); }); } async-rs-async-std-57f61ae/examples/stdin-echo.rs000066400000000000000000000012561476537407000220360ustar00rootroot00000000000000//! Echoes lines read on stdin to stdout. use async_std::io; use async_std::prelude::*; use async_std::task; fn main() -> io::Result<()> { task::block_on(async { let stdin = io::stdin(); let mut stdout = io::stdout(); let mut line = String::new(); loop { // Read a line from stdin. let n = stdin.read_line(&mut line).await?; // If this is the end of stdin, return. if n == 0 { return Ok(()); } // Write the line to stdout. stdout.write_all(line.as_bytes()).await?; stdout.flush().await?; line.clear(); } }) } async-rs-async-std-57f61ae/examples/stdin-timeout.rs000066400000000000000000000010111476537407000225730ustar00rootroot00000000000000//! Reads a line from stdin, or exits with an error if nothing is read in 5 seconds. use std::time::Duration; use async_std::io; use async_std::task; fn main() -> io::Result<()> { // This async scope times out after 5 seconds. task::block_on(io::timeout(Duration::from_secs(5), async { let stdin = io::stdin(); // Read a line from the standard input and display it. let mut line = String::new(); stdin.read_line(&mut line).await?; dbg!(line); Ok(()) })) } async-rs-async-std-57f61ae/examples/surf-web.rs000066400000000000000000000007131476537407000215300ustar00rootroot00000000000000use async_std::task; fn main() -> Result<(), surf::Error> { task::block_on(async { let url = "https://www.rust-lang.org"; let mut response = surf::get(url).send().await?; let body = response.body_string().await?; dbg!(url); dbg!(response.status()); dbg!(response.version()); dbg!(response.header_names()); dbg!(response.header_values()); dbg!(body.len()); Ok(()) }) } async-rs-async-std-57f61ae/examples/task-local.rs000066400000000000000000000005351476537407000220320ustar00rootroot00000000000000//! Creates a task-local value. use std::cell::Cell; use async_std::prelude::*; use async_std::task; task_local! { static VAR: Cell = Cell::new(1); } fn main() { task::block_on(async { println!("var = {}", VAR.with(|v| v.get())); VAR.with(|v| v.set(2)); println!("var = {}", VAR.with(|v| v.get())); }) } async-rs-async-std-57f61ae/examples/task-name.rs000066400000000000000000000005321476537407000216550ustar00rootroot00000000000000//! Spawns a named task that prints its name. use async_std::task; async fn print_name() { println!("My name is {:?}", task::current().name()); } fn main() { task::block_on(async { task::Builder::new() .name("my-task".to_string()) .spawn(print_name()) .unwrap() .await; }) } async-rs-async-std-57f61ae/examples/tcp-client.rs000066400000000000000000000014071476537407000220410ustar00rootroot00000000000000//! TCP client. //! //! First start the echo server: //! //! ```sh //! $ cargo run --example tcp-echo //! ``` //! //! Then run the client: //! //! ```sh //! $ cargo run --example tcp-client //! ``` use async_std::io; use async_std::net::TcpStream; use async_std::prelude::*; use async_std::task; fn main() -> io::Result<()> { task::block_on(async { let mut stream = TcpStream::connect("127.0.0.1:8080").await?; println!("Connected to {}", &stream.peer_addr()?); let msg = "hello world"; println!("<- {}", msg); stream.write_all(msg.as_bytes()).await?; let mut buf = vec![0u8; 1024]; let n = stream.read(&mut buf).await?; println!("-> {}\n", String::from_utf8_lossy(&buf[..n])); Ok(()) }) } async-rs-async-std-57f61ae/examples/tcp-echo.rs000066400000000000000000000016151476537407000215020ustar00rootroot00000000000000//! TCP echo server. //! //! To send messages, do: //! //! ```sh //! $ nc localhost 8080 //! ``` use async_std::io; use async_std::net::{TcpListener, TcpStream}; use async_std::prelude::*; use async_std::task; async fn process(stream: TcpStream) -> io::Result<()> { println!("Accepted from: {}", stream.peer_addr()?); let mut reader = stream.clone(); let mut writer = stream; io::copy(&mut reader, &mut writer).await?; Ok(()) } fn main() -> io::Result<()> { task::block_on(async { let listener = TcpListener::bind("127.0.0.1:8080").await?; println!("Listening on {}", listener.local_addr()?); let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { let stream = stream?; task::spawn(async { process(stream).await.unwrap(); }); } Ok(()) }) } async-rs-async-std-57f61ae/examples/tcp-ipv4-and-6-echo.rs000066400000000000000000000023451476537407000232660ustar00rootroot00000000000000//! TCP echo server, accepting connections both on both ipv4 and ipv6 sockets. //! //! To send messages, do: //! //! ```sh //! $ nc 127.0.0.1 8080 //! $ nc ::1 8080 //! ``` use async_std::io; use async_std::net::{TcpListener, TcpStream}; use async_std::prelude::*; use async_std::task; async fn process(stream: TcpStream) -> io::Result<()> { println!("Accepted from: {}", stream.peer_addr()?); let mut reader = stream.clone(); let mut writer = stream; io::copy(&mut reader, &mut writer).await?; Ok(()) } fn main() -> io::Result<()> { task::block_on(async { let ipv4_listener = TcpListener::bind("127.0.0.1:8080").await?; println!("Listening on {}", ipv4_listener.local_addr()?); let ipv6_listener = TcpListener::bind("[::1]:8080").await?; println!("Listening on {}", ipv6_listener.local_addr()?); let ipv4_incoming = ipv4_listener.incoming(); let ipv6_incoming = ipv6_listener.incoming(); let mut incoming = ipv4_incoming.merge(ipv6_incoming); while let Some(stream) = incoming.next().await { let stream = stream?; task::spawn(async { process(stream).await.unwrap(); }); } Ok(()) }) } async-rs-async-std-57f61ae/examples/udp-client.rs000066400000000000000000000013771476537407000220510ustar00rootroot00000000000000//! UDP client. //! //! First start the echo server: //! //! ```sh //! $ cargo run --example udp-echo //! ``` //! //! Then run the client: //! //! ```sh //! $ cargo run --example udp-client //! ``` use async_std::io; use async_std::net::UdpSocket; use async_std::task; fn main() -> io::Result<()> { task::block_on(async { let socket = UdpSocket::bind("127.0.0.1:8081").await?; println!("Listening on {}", socket.local_addr()?); let msg = "hello world"; println!("<- {}", msg); socket.send_to(msg.as_bytes(), "127.0.0.1:8080").await?; let mut buf = vec![0u8; 1024]; let (n, _) = socket.recv_from(&mut buf).await?; println!("-> {}\n", String::from_utf8_lossy(&buf[..n])); Ok(()) }) } async-rs-async-std-57f61ae/examples/udp-echo.rs000066400000000000000000000011601476537407000214770ustar00rootroot00000000000000//! UDP echo server. //! //! To send messages, do: //! //! ```sh //! $ nc -u localhost 8080 //! ``` use async_std::io; use async_std::net::UdpSocket; use async_std::task; fn main() -> io::Result<()> { task::block_on(async { let socket = UdpSocket::bind("127.0.0.1:8080").await?; let mut buf = vec![0u8; 1024]; println!("Listening on {}", socket.local_addr()?); loop { let (n, peer) = socket.recv_from(&mut buf).await?; let sent = socket.send_to(&buf[..n], &peer).await?; println!("Sent {} out of {} bytes to {}", sent, n, peer); } }) } async-rs-async-std-57f61ae/src/000077500000000000000000000000001476537407000164005ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/channel.rs000066400000000000000000000003661476537407000203630ustar00rootroot00000000000000//! Channels //! //! Multi-producer, multi-consumer queues, used for message-based //! communication. Can provide a lightweight inter-task synchronisation //! mechanism, at the cost of some extra memory. #[doc(inline)] pub use async_channel::*; async-rs-async-std-57f61ae/src/collections/000077500000000000000000000000001476537407000207165ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/collections/binary_heap/000077500000000000000000000000001476537407000231775ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/collections/binary_heap/extend.rs000066400000000000000000000010351476537407000250330ustar00rootroot00000000000000use std::collections::BinaryHeap; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend for BinaryHeap { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); self.reserve(stream.size_hint().0); Box::pin(stream.for_each(move |item| self.push(item))) } } async-rs-async-std-57f61ae/src/collections/binary_heap/from_stream.rs000066400000000000000000000011221476537407000260570ustar00rootroot00000000000000use std::collections::BinaryHeap; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream for BinaryHeap { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = BinaryHeap::new(); stream::extend(&mut out, stream).await; out }) } } async-rs-async-std-57f61ae/src/collections/binary_heap/mod.rs000066400000000000000000000002171476537407000243240ustar00rootroot00000000000000//! The Rust priority queue implemented with a binary heap mod extend; mod from_stream; #[doc(inline)] pub use std::collections::BinaryHeap; async-rs-async-std-57f61ae/src/collections/btree_map/000077500000000000000000000000001476537407000226545ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/collections/btree_map/extend.rs000066400000000000000000000010011476537407000245010ustar00rootroot00000000000000use std::collections::BTreeMap; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend<(K, V)> for BTreeMap { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { Box::pin(stream.into_stream().for_each(move |(k, v)| { self.insert(k, v); })) } } async-rs-async-std-57f61ae/src/collections/btree_map/from_stream.rs000066400000000000000000000011431476537407000255370ustar00rootroot00000000000000use std::collections::BTreeMap; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream<(K, V)> for BTreeMap { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = BTreeMap::new(); stream::extend(&mut out, stream).await; out }) } } async-rs-async-std-57f61ae/src/collections/btree_map/mod.rs000066400000000000000000000001521476537407000237770ustar00rootroot00000000000000//! The Rust B-Tree Map mod extend; mod from_stream; #[doc(inline)] pub use std::collections::BTreeMap; async-rs-async-std-57f61ae/src/collections/btree_set/000077500000000000000000000000001476537407000226725ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/collections/btree_set/extend.rs000066400000000000000000000007511476537407000245320ustar00rootroot00000000000000use std::collections::BTreeSet; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend for BTreeSet { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { Box::pin(stream.into_stream().for_each(move |item| { self.insert(item); })) } } async-rs-async-std-57f61ae/src/collections/btree_set/from_stream.rs000066400000000000000000000011151476537407000255540ustar00rootroot00000000000000use std::collections::BTreeSet; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream for BTreeSet { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = BTreeSet::new(); stream::extend(&mut out, stream).await; out }) } } async-rs-async-std-57f61ae/src/collections/btree_set/mod.rs000066400000000000000000000001521476537407000240150ustar00rootroot00000000000000//! The Rust B-Tree Set mod extend; mod from_stream; #[doc(inline)] pub use std::collections::BTreeSet; async-rs-async-std-57f61ae/src/collections/hash_map/000077500000000000000000000000001476537407000224765ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/collections/hash_map/extend.rs000066400000000000000000000024051476537407000243340ustar00rootroot00000000000000use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend<(K, V)> for HashMap where K: Eq + Hash + Send, V: Send, H: BuildHasher + Default + Send, { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); // The following is adapted from the hashbrown source code: // https://github.com/rust-lang/hashbrown/blob/d1ad4fc3aae2ade446738eea512e50b9e863dd0c/src/map.rs#L2470-L2491 // // Keys may be already present or show multiple times in the stream. Reserve the entire // hint lower bound if the map is empty. Otherwise reserve half the hint (rounded up), so // the map will only resize twice in the worst case. let additional = if self.is_empty() { stream.size_hint().0 } else { (stream.size_hint().0 + 1) / 2 }; self.reserve(additional); Box::pin(stream.for_each(move |(k, v)| { self.insert(k, v); })) } } async-rs-async-std-57f61ae/src/collections/hash_map/from_stream.rs000066400000000000000000000013431476537407000253630ustar00rootroot00000000000000use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream<(K, V)> for HashMap where K: Eq + Hash + Send, H: BuildHasher + Default + Send, V: Send, { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = HashMap::with_hasher(Default::default()); stream::extend(&mut out, stream).await; out }) } } async-rs-async-std-57f61ae/src/collections/hash_map/mod.rs000066400000000000000000000002341476537407000236220ustar00rootroot00000000000000//! The Rust hash map, implemented with quadratic probing and SIMD lookup. mod extend; mod from_stream; #[doc(inline)] pub use std::collections::HashMap; async-rs-async-std-57f61ae/src/collections/hash_set/000077500000000000000000000000001476537407000225145ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/collections/hash_set/extend.rs000066400000000000000000000026471476537407000243620ustar00rootroot00000000000000use std::collections::HashSet; use std::hash::{BuildHasher, Hash}; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend for HashSet where T: Eq + Hash + Send, H: BuildHasher + Default + Send, { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { // The Extend impl for HashSet in the standard library delegates to the internal HashMap. // Thus, this impl is just a copy of the async Extend impl for HashMap in this crate. let stream = stream.into_stream(); // The following is adapted from the hashbrown source code: // https://github.com/rust-lang/hashbrown/blob/d1ad4fc3aae2ade446738eea512e50b9e863dd0c/src/map.rs#L2470-L2491 // // Keys may be already present or show multiple times in the stream. Reserve the entire // hint lower bound if the map is empty. Otherwise reserve half the hint (rounded up), so // the map will only resize twice in the worst case. let additional = if self.is_empty() { stream.size_hint().0 } else { (stream.size_hint().0 + 1) / 2 }; self.reserve(additional); Box::pin(stream.for_each(move |item| { self.insert(item); })) } } async-rs-async-std-57f61ae/src/collections/hash_set/from_stream.rs000066400000000000000000000013061476537407000254000ustar00rootroot00000000000000use std::collections::HashSet; use std::hash::{BuildHasher, Hash}; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream for HashSet where T: Eq + Hash + Send, H: BuildHasher + Default + Send, { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = HashSet::with_hasher(Default::default()); stream::extend(&mut out, stream).await; out }) } } async-rs-async-std-57f61ae/src/collections/hash_set/mod.rs000066400000000000000000000002341476537407000236400ustar00rootroot00000000000000//! The Rust hash set, implemented as a `HashMap` where the value is `()`. mod extend; mod from_stream; #[doc(inline)] pub use std::collections::HashSet; async-rs-async-std-57f61ae/src/collections/linked_list/000077500000000000000000000000001476537407000232175ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/collections/linked_list/extend.rs000066400000000000000000000007561476537407000250640ustar00rootroot00000000000000use std::collections::LinkedList; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend for LinkedList { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(stream.for_each(move |item| self.push_back(item))) } } async-rs-async-std-57f61ae/src/collections/linked_list/from_stream.rs000066400000000000000000000011151476537407000261010ustar00rootroot00000000000000use std::collections::LinkedList; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream for LinkedList { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = LinkedList::new(); stream::extend(&mut out, stream).await; out }) } } async-rs-async-std-57f61ae/src/collections/linked_list/mod.rs000066400000000000000000000002051476537407000243410ustar00rootroot00000000000000//! The Rust doubly-linked list with owned nodes mod extend; mod from_stream; #[doc(inline)] pub use std::collections::LinkedList; async-rs-async-std-57f61ae/src/collections/mod.rs000066400000000000000000000011551476537407000220450ustar00rootroot00000000000000//! The Rust standard collections //! //! This library provides efficient implementations of the most common general purpose programming //! data structures. pub mod binary_heap; pub mod btree_map; pub mod btree_set; pub mod hash_map; pub mod hash_set; pub mod linked_list; pub mod vec_deque; #[allow(unused)] pub use binary_heap::BinaryHeap; #[allow(unused)] pub use btree_map::BTreeMap; #[allow(unused)] pub use btree_set::BTreeSet; #[allow(unused)] pub use hash_map::HashMap; #[allow(unused)] pub use hash_set::HashSet; #[allow(unused)] pub use linked_list::LinkedList; #[allow(unused)] pub use vec_deque::VecDeque; async-rs-async-std-57f61ae/src/collections/vec_deque/000077500000000000000000000000001476537407000226565ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/collections/vec_deque/extend.rs000066400000000000000000000010301476537407000245050ustar00rootroot00000000000000use std::collections::VecDeque; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend for VecDeque { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); self.reserve(stream.size_hint().0); Box::pin(stream.for_each(move |item| self.push_back(item))) } } async-rs-async-std-57f61ae/src/collections/vec_deque/from_stream.rs000066400000000000000000000011071476537407000255410ustar00rootroot00000000000000use std::collections::VecDeque; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream for VecDeque { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = VecDeque::new(); stream::extend(&mut out, stream).await; out }) } } async-rs-async-std-57f61ae/src/collections/vec_deque/mod.rs000066400000000000000000000002341476537407000240020ustar00rootroot00000000000000//! The Rust double-ended queue, implemented with a growable ring buffer. mod extend; mod from_stream; #[doc(inline)] pub use std::collections::VecDeque; async-rs-async-std-57f61ae/src/fs/000077500000000000000000000000001476537407000170105ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/fs/canonicalize.rs000066400000000000000000000023001476537407000220100ustar00rootroot00000000000000use crate::io; use crate::path::{Path, PathBuf}; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Returns the canonical form of a path. /// /// The returned path is in absolute form with all intermediate components normalized and symbolic /// links resolved. /// /// This function is an async version of [`std::fs::canonicalize`]. /// /// [`std::fs::canonicalize`]: https://doc.rust-lang.org/std/fs/fn.canonicalize.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing file or directory. /// * A non-final component in `path` is not a directory. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let path = fs::canonicalize(".").await?; /// # /// # Ok(()) }) } /// ``` pub async fn canonicalize>(path: P) -> io::Result { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::canonicalize(&path) .map(Into::into) .context(|| format!("could not canonicalize `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/copy.rs000066400000000000000000000031371476537407000203340ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Copies the contents and permissions of a file to a new location. /// /// On success, the total number of bytes copied is returned and equals the length of the `to` file /// after this operation. /// /// The old contents of `to` will be overwritten. If `from` and `to` both point to the same file, /// then the file will likely get truncated as a result of this operation. /// /// If you're working with open [`File`]s and want to copy contents through those types, use the /// [`io::copy`] function. /// /// This function is an async version of [`std::fs::copy`]. /// /// [`File`]: struct.File.html /// [`io::copy`]: ../io/fn.copy.html /// [`std::fs::copy`]: https://doc.rust-lang.org/std/fs/fn.copy.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `from` does not point to an existing file. /// * The current process lacks permissions to read `from` or write `to`. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let num_bytes = fs::copy("a.txt", "b.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { let from = from.as_ref().to_owned(); let to = to.as_ref().to_owned(); spawn_blocking(move || { std::fs::copy(&from, &to) .context(|| format!("could not copy `{}` to `{}`", from.display(), to.display())) }) .await } async-rs-async-std-57f61ae/src/fs/create_dir.rs000066400000000000000000000024661476537407000214670ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Creates a new directory. /// /// Note that this function will only create the final directory in `path`. If you want to create /// all of its missing parent directories too, use the [`create_dir_all`] function instead. /// /// This function is an async version of [`std::fs::create_dir`]. /// /// [`create_dir_all`]: fn.create_dir_all.html /// [`std::fs::create_dir`]: https://doc.rust-lang.org/std/fs/fn.create_dir.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` already points to an existing file or directory. /// * A parent directory in `path` does not exist. /// * The current process lacks permissions to create the directory. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// fs::create_dir("./some/directory").await?; /// # /// # Ok(()) }) } /// ``` pub async fn create_dir>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::create_dir(&path) .context(|| format!("could not create directory `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/create_dir_all.rs000066400000000000000000000021611476537407000223070ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Creates a new directory and all of its parents if they are missing. /// /// This function is an async version of [`std::fs::create_dir_all`]. /// /// [`std::fs::create_dir_all`]: https://doc.rust-lang.org/std/fs/fn.create_dir_all.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` already points to an existing file or directory. /// * The current process lacks permissions to create the directory or its missing parents. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// fs::create_dir_all("./some/directory").await?; /// # /// # Ok(()) }) } /// ``` pub async fn create_dir_all>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::create_dir_all(&path) .context(|| format!("could not create directory path `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/dir_builder.rs000066400000000000000000000065731476537407000216550ustar00rootroot00000000000000use std::future::Future; use crate::io; use crate::path::Path; use crate::task::spawn_blocking; /// A builder for creating directories with configurable options. /// /// For Unix-specific options, import the [`os::unix::fs::DirBuilderExt`] trait. /// /// This type is an async version of [`std::fs::DirBuilder`]. /// /// [`os::unix::fs::DirBuilderExt`]: ../os/unix/fs/trait.DirBuilderExt.html /// [`std::fs::DirBuilder`]: https://doc.rust-lang.org/std/fs/struct.DirBuilder.html #[derive(Debug, Default)] pub struct DirBuilder { /// Set to `true` if non-existent parent directories should be created. recursive: bool, /// Unix mode for newly created directories. #[cfg(unix)] mode: Option, } impl DirBuilder { /// Creates a blank set of options. /// /// The [`recursive`] option is initially set to `false`. /// /// [`recursive`]: #method.recursive /// /// # Examples /// /// ``` /// use async_std::fs::DirBuilder; /// /// let builder = DirBuilder::new(); /// ``` pub fn new() -> DirBuilder { #[cfg(not(unix))] let builder = DirBuilder { recursive: false }; #[cfg(unix)] let builder = DirBuilder { recursive: false, mode: None, }; builder } /// Sets the option for recursive mode. /// /// When set to `true`, this option means all parent directories should be created recursively /// if they don't exist. Parents are created with the same permissions as the final directory. /// /// This option is initially set to `false`. /// /// # Examples /// /// ``` /// use async_std::fs::DirBuilder; /// /// let mut builder = DirBuilder::new(); /// builder.recursive(true); /// ``` pub fn recursive(&mut self, recursive: bool) -> &mut Self { self.recursive = recursive; self } /// Creates a directory with the configured options. /// /// It is considered an error if the directory already exists unless recursive mode is enabled. /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` already points to an existing file or directory. /// * The current process lacks permissions to create the directory or its missing parents. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::DirBuilder; /// /// DirBuilder::new() /// .recursive(true) /// .create("./some/directory") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn create>(&self, path: P) -> impl Future> { let mut builder = std::fs::DirBuilder::new(); builder.recursive(self.recursive); #[cfg(unix)] { if let Some(mode) = self.mode { std::os::unix::fs::DirBuilderExt::mode(&mut builder, mode); } } let path = path.as_ref().to_owned(); async move { spawn_blocking(move || builder.create(path)).await } } } cfg_unix! { use crate::os::unix::fs::DirBuilderExt; impl DirBuilderExt for DirBuilder { fn mode(&mut self, mode: u32) -> &mut Self { self.mode = Some(mode); self } } } async-rs-async-std-57f61ae/src/fs/dir_entry.rs000066400000000000000000000114271476537407000213620ustar00rootroot00000000000000use std::ffi::OsString; use std::fmt; use std::sync::Arc; use crate::fs::{FileType, Metadata}; use crate::io; use crate::path::PathBuf; use crate::task::spawn_blocking; /// An entry in a directory. /// /// A stream of entries in a directory is returned by [`read_dir`]. /// /// This type is an async version of [`std::fs::DirEntry`]. /// /// [`read_dir`]: fn.read_dir.html /// [`std::fs::DirEntry`]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html pub struct DirEntry(Arc); impl DirEntry { /// Creates an asynchronous `DirEntry` from a synchronous one. pub(crate) fn new(inner: std::fs::DirEntry) -> DirEntry { DirEntry(Arc::new(inner)) } /// Returns the full path to this entry. /// /// The full path is created by joining the original path passed to [`read_dir`] with the name /// of this entry. /// /// [`read_dir`]: fn.read_dir.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// use async_std::prelude::*; /// /// let mut dir = fs::read_dir(".").await?; /// /// while let Some(res) = dir.next().await { /// let entry = res?; /// println!("{:?}", entry.path()); /// } /// # /// # Ok(()) }) } /// ``` pub fn path(&self) -> PathBuf { self.0.path().into() } /// Reads the metadata for this entry. /// /// This function will traverse symbolic links to read the metadata. /// /// If you want to read metadata without following symbolic links, use [`symlink_metadata`] /// instead. /// /// [`symlink_metadata`]: fn.symlink_metadata.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * This entry does not point to an existing file or directory anymore. /// * The current process lacks permissions to read the metadata. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// use async_std::prelude::*; /// /// let mut dir = fs::read_dir(".").await?; /// /// while let Some(res) = dir.next().await { /// let entry = res?; /// println!("{:?}", entry.metadata().await?); /// } /// # /// # Ok(()) }) } /// ``` pub async fn metadata(&self) -> io::Result { let inner = self.0.clone(); spawn_blocking(move || inner.metadata()).await } /// Reads the file type for this entry. /// /// This function will not traverse symbolic links if this entry points at one. /// /// If you want to read metadata with following symbolic links, use [`metadata`] instead. /// /// [`metadata`]: #method.metadata /// /// # Errors /// /// An error will be returned in the following situations: /// /// * This entry does not point to an existing file or directory anymore. /// * The current process lacks permissions to read this entry's metadata. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// use async_std::prelude::*; /// /// let mut dir = fs::read_dir(".").await?; /// /// while let Some(res) = dir.next().await { /// let entry = res?; /// println!("{:?}", entry.file_type().await?); /// } /// # /// # Ok(()) }) } /// ``` pub async fn file_type(&self) -> io::Result { let inner = self.0.clone(); spawn_blocking(move || inner.file_type()).await } /// Returns the bare name of this entry without the leading path. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// use async_std::prelude::*; /// /// let mut dir = fs::read_dir(".").await?; /// /// while let Some(res) = dir.next().await { /// let entry = res?; /// println!("{}", entry.file_name().to_string_lossy()); /// } /// # /// # Ok(()) }) } /// ``` pub fn file_name(&self) -> OsString { self.0.file_name() } } impl fmt::Debug for DirEntry { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("DirEntry").field(&self.path()).finish() } } impl Clone for DirEntry { fn clone(&self) -> Self { DirEntry(self.0.clone()) } } cfg_unix! { use crate::os::unix::fs::DirEntryExt; impl DirEntryExt for DirEntry { fn ino(&self) -> u64 { self.0.ino() } } } async-rs-async-std-57f61ae/src/fs/file.rs000066400000000000000000001006351476537407000203020ustar00rootroot00000000000000use std::cell::UnsafeCell; use std::cmp; use std::fmt; use std::io::{Read as _, Seek as _, Write as _}; use std::ops::{Deref, DerefMut}; use std::pin::Pin; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use crate::fs::{Metadata, Permissions}; use crate::future; use crate::io::{self, Read, Seek, SeekFrom, Write}; use crate::path::Path; use crate::prelude::*; use crate::task::{spawn_blocking, Context, Poll, Waker}; use crate::utils::Context as _; const ARC_TRY_UNWRAP_EXPECT: &str = "cannot acquire ownership of the file handle after drop"; /// An open file on the filesystem. /// /// Depending on what options the file was opened with, this type can be used for reading and/or /// writing. /// /// Files are automatically closed when they get dropped and any errors detected on closing are /// ignored. Use the [`sync_all`] method before dropping a file if such errors need to be handled. /// /// This type is an async version of [`std::fs::File`]. /// /// [`sync_all`]: #method.sync_all /// [`std::fs::File`]: https://doc.rust-lang.org/std/fs/struct.File.html /// /// # Examples /// /// Create a new file and write some bytes to it: /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::prelude::*; /// /// let mut file = File::create("a.txt").await?; /// file.write_all(b"Hello, world!").await?; /// # /// # Ok(()) }) } /// ``` /// /// Read the contents of a file into a vector of bytes: /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::prelude::*; /// /// let mut file = File::open("a.txt").await?; /// let mut contents = Vec::new(); /// file.read_to_end(&mut contents).await?; /// # /// # Ok(()) }) } /// ``` #[derive(Clone)] pub struct File { /// A reference to the inner file. file: Arc, /// The state of the file protected by an async lock. lock: Lock, } impl File { /// Creates an async file handle. pub(crate) fn new(file: std::fs::File, is_flushed: bool) -> File { let file = Arc::new(file); File { file: file.clone(), lock: Lock::new(State { file, mode: Mode::Idle, cache: Vec::new(), is_flushed, last_read_err: None, last_write_err: None, }), } } /// Opens a file in read-only mode. /// /// See the [`OpenOptions::open`] function for more options. /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing file. /// * The current process lacks permissions to read the file. /// * Some other I/O error occurred. /// /// For more details, see the list of errors documented by [`OpenOptions::open`]. /// /// [`OpenOptions::open`]: struct.OpenOptions.html#method.open /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// /// let file = File::open("a.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn open>(path: P) -> io::Result { let path = path.as_ref().to_owned(); let file = spawn_blocking(move || { std::fs::File::open(&path).context(|| format!("could not open `{}`", path.display())) }) .await?; Ok(File::new(file, true)) } /// Opens a file in write-only mode. /// /// This function will create a file if it does not exist, and will truncate it if it does. /// /// See the [`OpenOptions::open`] function for more options. /// /// # Errors /// /// An error will be returned in the following situations: /// /// * The file's parent directory does not exist. /// * The current process lacks permissions to write to the file. /// * Some other I/O error occurred. /// /// For more details, see the list of errors documented by [`OpenOptions::open`]. /// /// [`OpenOptions::open`]: struct.OpenOptions.html#method.open /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// /// let file = File::create("a.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn create>(path: P) -> io::Result { let path = path.as_ref().to_owned(); let file = spawn_blocking(move || { std::fs::File::create(&path) }) .await?; Ok(File::new(file, true)) } /// Synchronizes OS-internal buffered contents and metadata to disk. /// /// This function will ensure that all in-memory data reaches the filesystem. /// /// This can be used to handle errors that would otherwise only be caught when the file is /// closed. When a file is dropped, errors in synchronizing this in-memory data are ignored. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::prelude::*; /// /// let mut file = File::create("a.txt").await?; /// file.write_all(b"Hello, world!").await?; /// file.sync_all().await?; /// # /// # Ok(()) }) } /// ``` pub async fn sync_all(&self) -> io::Result<()> { // Flush the write cache before calling `sync_all()`. let state = future::poll_fn(|cx| { let state = futures_core::ready!(self.lock.poll_lock(cx)); state.poll_flush(cx) }) .await?; spawn_blocking(move || state.file.sync_all()).await } /// Synchronizes OS-internal buffered contents to disk. /// /// This is similar to [`sync_all`], except that file metadata may not be synchronized. /// /// This is intended for use cases that must synchronize the contents of the file, but don't /// need the file metadata synchronized to disk. /// /// Note that some platforms may simply implement this in terms of [`sync_all`]. /// /// [`sync_all`]: #method.sync_all /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::prelude::*; /// /// let mut file = File::create("a.txt").await?; /// file.write_all(b"Hello, world!").await?; /// file.sync_data().await?; /// # /// # Ok(()) }) } /// ``` pub async fn sync_data(&self) -> io::Result<()> { // Flush the write cache before calling `sync_data()`. let state = future::poll_fn(|cx| { let state = futures_core::ready!(self.lock.poll_lock(cx)); state.poll_flush(cx) }) .await?; spawn_blocking(move || state.file.sync_data()).await } /// Truncates or extends the file. /// /// If `size` is less than the current file size, then the file will be truncated. If it is /// greater than the current file size, then the file will be extended to `size` and have all /// intermediate data filled with zeros. /// /// The file's cursor stays at the same position, even if the cursor ends up being past the end /// of the file after this operation. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// /// let file = File::create("a.txt").await?; /// file.set_len(10).await?; /// # /// # Ok(()) }) } /// ``` pub async fn set_len(&self, size: u64) -> io::Result<()> { // Invalidate the read cache and flush the write cache before calling `set_len()`. let state = future::poll_fn(|cx| { let state = futures_core::ready!(self.lock.poll_lock(cx)); let state = futures_core::ready!(state.poll_unread(cx))?; state.poll_flush(cx) }) .await?; spawn_blocking(move || state.file.set_len(size)).await } /// Reads the file's metadata. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// /// let file = File::open("a.txt").await?; /// let metadata = file.metadata().await?; /// # /// # Ok(()) }) } /// ``` pub async fn metadata(&self) -> io::Result { let file = self.file.clone(); spawn_blocking(move || file.metadata()).await } /// Changes the permissions on the file. /// /// # Errors /// /// An error will be returned in the following situations: /// /// * The current process lacks permissions to change attributes on the file. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// /// let file = File::create("a.txt").await?; /// /// let mut perms = file.metadata().await?.permissions(); /// perms.set_readonly(true); /// file.set_permissions(perms).await?; /// # /// # Ok(()) }) } /// ``` pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> { let file = self.file.clone(); spawn_blocking(move || file.set_permissions(perm)).await } } impl Drop for File { fn drop(&mut self) { // We need to flush the file on drop. Unfortunately, that is not possible to do in a // non-blocking fashion, but our only other option here is losing data remaining in the // write cache. Good task schedulers should be resilient to occasional blocking hiccups in // file destructors so we don't expect this to be a common problem in practice. let _ = futures_lite::future::block_on(self.flush()); } } impl fmt::Debug for File { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.file.fmt(f) } } impl Read for File { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { Pin::new(&mut &*self).poll_read(cx, buf) } } impl Read for &File { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { let state = futures_core::ready!(self.lock.poll_lock(cx)); state.poll_read(cx, buf) } } impl Write for File { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { Pin::new(&mut &*self).poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self).poll_flush(cx) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self).poll_close(cx) } } impl Write for &File { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { let state = futures_core::ready!(self.lock.poll_lock(cx)); state.poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let state = futures_core::ready!(self.lock.poll_lock(cx)); state.poll_flush(cx).map(|res| res.map(drop)) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let state = futures_core::ready!(self.lock.poll_lock(cx)); state.poll_close(cx) } } impl Seek for File { fn poll_seek( self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll> { Pin::new(&mut &*self).poll_seek(cx, pos) } } impl Seek for &File { fn poll_seek( self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll> { let state = futures_core::ready!(self.lock.poll_lock(cx)); state.poll_seek(cx, pos) } } impl From for File { fn from(file: std::fs::File) -> File { File::new(file, false) } } cfg_unix! { use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; impl File { fn into_std_file(self) -> std::fs::File { let file = self.file.clone(); drop(self); Arc::try_unwrap(file) .expect(ARC_TRY_UNWRAP_EXPECT) } } impl AsRawFd for File { fn as_raw_fd(&self) -> RawFd { self.file.as_raw_fd() } } impl FromRawFd for File { unsafe fn from_raw_fd(fd: RawFd) -> File { std::fs::File::from_raw_fd(fd).into() } } impl IntoRawFd for File { fn into_raw_fd(self) -> RawFd { self.into_std_file().into_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; impl AsFd for File { fn as_fd(&self) -> BorrowedFd<'_> { self.file.as_fd() } } impl From for File { fn from(fd: OwnedFd) -> Self { std::fs::File::from(fd).into() } } impl From for OwnedFd { fn from(val: File) -> OwnedFd { val.into_std_file().into() } } } } cfg_windows! { use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; impl AsRawHandle for File { fn as_raw_handle(&self) -> RawHandle { self.file.as_raw_handle() } } impl FromRawHandle for File { unsafe fn from_raw_handle(handle: RawHandle) -> File { std::fs::File::from_raw_handle(handle).into() } } impl IntoRawHandle for File { fn into_raw_handle(self) -> RawHandle { let file = self.file.clone(); drop(self); Arc::try_unwrap(file) .expect(ARC_TRY_UNWRAP_EXPECT) .into_raw_handle() } } cfg_io_safety! { use crate::os::windows::io::{AsHandle, BorrowedHandle, OwnedHandle}; impl AsHandle for File { fn as_handle(&self) -> BorrowedHandle<'_> { self.file.as_handle() } } impl From for File { fn from(handle: OwnedHandle) -> Self { std::fs::File::from(handle).into() } } impl From for OwnedHandle { fn from(val: File) -> OwnedHandle { let file = val.file.clone(); drop(val); Arc::try_unwrap(file) .expect(ARC_TRY_UNWRAP_EXPECT) .into() } } } } /// An async mutex with non-borrowing lock guards. struct Lock(Arc>); unsafe impl Send for Lock {} unsafe impl Sync for Lock {} impl Clone for Lock { #[inline] fn clone(&self) -> Self { Self(Arc::clone(&self.0)) } } /// The state of a lock. struct LockState { /// Set to `true` when locked. locked: AtomicBool, /// The inner value. value: UnsafeCell, /// A list of tasks interested in acquiring the lock. wakers: Mutex>, } impl Lock { /// Creates a new lock initialized with `value`. fn new(value: T) -> Lock { Lock(Arc::new(LockState { locked: AtomicBool::new(false), value: UnsafeCell::new(value), wakers: Mutex::new(Vec::new()), })) } /// Attempts to acquire the lock. fn poll_lock(&self, cx: &mut Context<'_>) -> Poll> { // Try acquiring the lock. if self.0.locked.swap(true, Ordering::Acquire) { // Lock the list of wakers. let mut list = self.0.wakers.lock().unwrap(); // Try acquiring the lock again. if self.0.locked.swap(true, Ordering::Acquire) { // If failed again, add the current task to the list and return. if list.iter().all(|w| !w.will_wake(cx.waker())) { list.push(cx.waker().clone()); } return Poll::Pending; } } // The lock was successfully acquired. Poll::Ready(LockGuard(Some(self.0.clone()))) } } /// A lock guard. /// /// When dropped, ownership of the inner value is returned back to the lock. /// The inner value is always Some, except when the lock is dropped, where we /// set it to None. See comment in drop(). struct LockGuard(Option>>); unsafe impl Send for LockGuard {} unsafe impl Sync for LockGuard {} impl LockGuard { /// Registers a task interested in acquiring the lock. /// /// When this lock guard gets dropped, all registered tasks will be woken up. fn register(&self, cx: &Context<'_>) { let mut list = self.0.as_ref().unwrap().wakers.lock().unwrap(); if list.iter().all(|w| !w.will_wake(cx.waker())) { list.push(cx.waker().clone()); } } } impl Drop for LockGuard { fn drop(&mut self) { // Set the Option to None and take its value so we can drop the Arc // before we wake up the tasks. let lock = self.0.take().unwrap(); // Prepare to wake up all registered tasks interested in acquiring the lock. let wakers: Vec<_> = lock.wakers.lock().unwrap().drain(..).collect(); // Release the lock. lock.locked.store(false, Ordering::Release); // Drop the Arc _before_ waking up the tasks, to avoid races. See // reproducer and discussion in https://github.com/async-rs/async-std/issues/1001. drop(lock); // Wake up all registered tasks interested in acquiring the lock. for w in wakers { w.wake(); } } } impl Deref for LockGuard { type Target = T; fn deref(&self) -> &T { // SAFETY: Safe because the lock is held when this method is called. And // the inner value is always Some since it is only set to None in // drop(). unsafe { &*self.0.as_ref().unwrap().value.get() } } } impl DerefMut for LockGuard { fn deref_mut(&mut self) -> &mut T { // SAFETY: Safe because the lock is held when this method is called. And // the inner value is always Some since it is only set to None in // drop(). unsafe { &mut *self.0.as_ref().unwrap().value.get() } } } /// Modes a file can be in. /// /// The file can either be in idle mode, reading mode, or writing mode. enum Mode { /// The cache is empty. Idle, /// The cache contains data read from the inner file. /// /// The `usize` represents how many bytes from the beginning of cache have been consumed. Reading(usize), /// The cache contains data that needs to be written to the inner file. Writing, } /// The current state of a file. /// /// The `File` struct protects this state behind a lock. /// /// Filesystem operations that get spawned as blocking tasks will acquire the lock, take ownership /// of the state and return it back once the operation completes. struct State { /// The inner file. file: Arc, /// The current mode (idle, reading, or writing). mode: Mode, /// The read/write cache. /// /// If in reading mode, the cache contains a chunk of data that has been read from the file. /// If in writing mode, the cache contains data that will eventually be written to the file. cache: Vec, /// Set to `true` if the file is flushed. /// /// When a file is flushed, the write cache and the inner file's buffer are empty. is_flushed: bool, /// The last read error that came from an async operation. last_read_err: Option, /// The last write error that came from an async operation. last_write_err: Option, } impl LockGuard { /// Seeks to a new position in the file. fn poll_seek(mut self, cx: &mut Context<'_>, pos: SeekFrom) -> Poll> { // If this operation doesn't move the cursor, then poll the current position inside the // file. This call should not block because it doesn't touch the actual file on disk. if pos == SeekFrom::Current(0) { // Poll the internal file cursor. let internal = (&*self.file).seek(SeekFrom::Current(0))?; // Factor in the difference caused by caching. let actual = match self.mode { Mode::Idle => internal, Mode::Reading(start) => internal - self.cache.len() as u64 + start as u64, Mode::Writing => internal + self.cache.len() as u64, }; return Poll::Ready(Ok(actual)); } // If the file is in reading mode and the cache will stay valid after seeking, then adjust // the current position in the read cache without invaliding it. if let Mode::Reading(start) = self.mode { if let SeekFrom::Current(diff) = pos { if let Some(new) = (start as i64).checked_add(diff) { if 0 <= new && new <= self.cache.len() as i64 { // Poll the internal file cursor. let internal = (&*self.file).seek(SeekFrom::Current(0))?; // Adjust the current position in the read cache. self.mode = Mode::Reading(new as usize); // Factor in the difference caused by caching. return Poll::Ready(Ok(internal - self.cache.len() as u64 + new as u64)); } } } } // Invalidate the read cache and flush the write cache before calling `seek()`. self = futures_core::ready!(self.poll_unread(cx))?; self = futures_core::ready!(self.poll_flush(cx))?; // Seek to the new position. This call should not block because it only changes the // internal offset into the file and doesn't touch the actual file on disk. Poll::Ready((&*self.file).seek(pos)) } /// Reads some bytes from the file into a buffer. fn poll_read(mut self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll> { // If an async operation has left a read error, return it now. if let Some(err) = self.last_read_err.take() { return Poll::Ready(Err(err)); } match self.mode { Mode::Idle => {} Mode::Reading(0) if self.cache.is_empty() => { // If the cache is empty in reading mode, the last operation didn't read any bytes, // which indicates that it reached the end of the file. In this case we need to // reset the mode to idle so that next time we try to read again, since the file // may grow after the first EOF. self.mode = Mode::Idle; return Poll::Ready(Ok(0)); } Mode::Reading(start) => { // How many bytes in the cache are available for reading. let available = self.cache.len() - start; if available > 0 { // Copy data from the cache into the buffer. let n = cmp::min(available, buf.len()); buf[..n].copy_from_slice(&self.cache[start..(start + n)]); // Move the read cursor forward. self.mode = Mode::Reading(start + n); return Poll::Ready(Ok(n)); } } Mode::Writing => { // If we're in writing mode, flush the write cache. self = futures_core::ready!(self.poll_flush(cx))?; } } // Make the cache as long as `buf`. if self.cache.len() < buf.len() { let diff = buf.len() - self.cache.len(); self.cache.reserve(diff); } unsafe { self.cache.set_len(buf.len()); } // Register current task's interest in the file lock. self.register(cx); // Start a read operation asynchronously. spawn_blocking(move || { // Read some data from the file into the cache. let res = { let State { file, cache, .. } = &mut *self; (&**file).read(cache) }; match res { Ok(n) => { // Update cache length and switch to reading mode, starting from index 0. unsafe { self.cache.set_len(n); } self.mode = Mode::Reading(0); } Err(err) => { // Save the error and switch to idle mode. self.cache.clear(); self.mode = Mode::Idle; self.last_read_err = Some(err); } } }); Poll::Pending } /// Invalidates the read cache. /// /// This method will also move the internal file's cursor backwards by the number of unconsumed /// bytes in the read cache. fn poll_unread(mut self, _: &mut Context<'_>) -> Poll> { match self.mode { Mode::Idle | Mode::Writing => Poll::Ready(Ok(self)), Mode::Reading(start) => { // The number of unconsumed bytes in the read cache. let n = self.cache.len() - start; if n > 0 { // Seek `n` bytes backwards. This call should not block because it only changes // the internal offset into the file and doesn't touch the actual file on disk. // // We ignore errors here because special files like `/dev/random` are not // seekable. let _ = (&*self.file).seek(SeekFrom::Current(-(n as i64))); } // Switch to idle mode. self.cache.clear(); self.mode = Mode::Idle; Poll::Ready(Ok(self)) } } } /// Writes some data from a buffer into the file. fn poll_write(mut self, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { // If an async operation has left a write error, return it now. if let Some(err) = self.last_write_err.take() { return Poll::Ready(Err(err)); } // If we're in reading mode, invalidate the read buffer. self = futures_core::ready!(self.poll_unread(cx))?; // If necessary, grow the cache to have as much capacity as `buf`. if self.cache.capacity() < buf.len() { let diff = buf.len() - self.cache.capacity(); self.cache.reserve(diff); } // How many bytes can be written into the cache before filling up. let available = self.cache.capacity() - self.cache.len(); // If there is space available in the cache or if the buffer is empty, we can write data // into the cache. if available > 0 || buf.is_empty() { let n = cmp::min(available, buf.len()); let start = self.cache.len(); // Copy data from the buffer into the cache. unsafe { self.cache.set_len(start + n); } self.cache[start..start + n].copy_from_slice(&buf[..n]); // Mark the file as not flushed and switch to writing mode. self.is_flushed = false; self.mode = Mode::Writing; Poll::Ready(Ok(n)) } else { // Drain the write cache because it's full. futures_core::ready!(self.poll_drain(cx))?; Poll::Pending } } /// Drains the write cache. fn poll_drain(mut self, cx: &mut Context<'_>) -> Poll> { // If an async operation has left a write error, return it now. if let Some(err) = self.last_write_err.take() { return Poll::Ready(Err(err)); } match self.mode { Mode::Idle | Mode::Reading(..) => Poll::Ready(Ok(self)), Mode::Writing => { // Register current task's interest in the file lock. self.register(cx); // Start a write operation asynchronously. spawn_blocking(move || { match (&*self.file).write_all(&self.cache) { Ok(_) => { // Switch to idle mode. self.cache.clear(); self.mode = Mode::Idle; } Err(err) => { // Save the error. self.last_write_err = Some(err); } }; }); Poll::Pending } } } /// Flushes the write cache into the file. fn poll_flush(mut self, cx: &mut Context<'_>) -> Poll> { // If the file is already in flushed state, return. if self.is_flushed { return Poll::Ready(Ok(self)); } // If there is data in the write cache, drain it. self = futures_core::ready!(self.poll_drain(cx))?; // Register current task's interest in the file lock. self.register(cx); // Start a flush operation asynchronously. spawn_blocking(move || { match (&*self.file).flush() { Ok(()) => { // Mark the file as flushed. self.is_flushed = true; } Err(err) => { // Save the error. self.last_write_err = Some(err); } } }); Poll::Pending } // This function does nothing because we're not sure about `AsyncWrite::poll_close()`'s exact // semantics nor whether it will stay in the `AsyncWrite` trait. fn poll_close(self, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } } #[cfg(test)] mod tests { use super::*; #[test] fn async_file_drop() { crate::task::block_on(async move { File::open(file!()).await.unwrap(); }); } #[test] fn async_file_clone() { crate::task::block_on(async move { let file = File::open(file!()).await.unwrap(); let mut clone = file.clone(); let len = crate::task::spawn_blocking(move || { let mut buf = Vec::new(); crate::task::block_on(async move { clone.read_to_end(&mut buf).await.unwrap(); drop(clone); buf.len() }) }).await; assert_eq!(len as u64, file.metadata().await.unwrap().len()); }); } #[test] fn async_file_create_error() { let file_name = Path::new("/tmp/does_not_exist/test"); let expect = std::fs::File::create(file_name).unwrap_err(); crate::task::block_on(async move { let actual = File::create(file_name).await.unwrap_err(); assert_eq!(format!("{}", expect), format!("{}", actual)); }) } #[test] fn file_eof_is_not_permanent() -> crate::io::Result<()> { let tempdir = tempfile::Builder::new() .prefix("async-std-file-eof-test") .tempdir()?; let path = tempdir.path().join("testfile"); crate::task::block_on(async { let mut file_w = File::create(&path).await?; let mut file_r = File::open(&path).await?; file_w.write_all(b"data").await?; file_w.flush().await?; let mut buf = [0u8; 4]; let mut len = file_r.read(&mut buf).await?; assert_eq!(len, 4); assert_eq!(&buf, b"data"); len = file_r.read(&mut buf).await?; assert_eq!(len, 0); file_w.write_all(b"more").await?; file_w.flush().await?; len = file_r.read(&mut buf).await?; assert_eq!(len, 4); assert_eq!(&buf, b"more"); len = file_r.read(&mut buf).await?; assert_eq!(len, 0); Ok(()) }) } } async-rs-async-std-57f61ae/src/fs/file_type.rs000066400000000000000000000053111476537407000213360ustar00rootroot00000000000000cfg_not_docs! { pub use std::fs::FileType; } cfg_docs! { /// The type of a file or directory. /// /// A file type is returned by [`Metadata::file_type`]. /// /// Note that file types are mutually exclusive, i.e. at most one of methods [`is_dir`], /// [`is_file`], and [`is_symlink`] can return `true`. /// /// This type is a re-export of [`std::fs::FileType`]. /// /// [`Metadata::file_type`]: struct.Metadata.html#method.file_type /// [`is_dir`]: #method.is_dir /// [`is_file`]: #method.is_file /// [`is_symlink`]: #method.is_symlink /// [`std::fs::FileType`]: https://doc.rust-lang.org/std/fs/struct.FileType.html #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType { _private: (), } impl FileType { /// Returns `true` if this file type represents a regular directory. /// /// If this file type represents a symbolic link, this method returns `false`. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let file_type = fs::metadata(".").await?.file_type(); /// println!("{:?}", file_type.is_dir()); /// # /// # Ok(()) }) } /// ``` pub fn is_dir(&self) -> bool { unreachable!("this impl only appears in the rendered docs") } /// Returns `true` if this file type represents a regular file. /// /// If this file type represents a symbolic link, this method returns `false`. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let file_type = fs::metadata("a.txt").await?.file_type(); /// println!("{:?}", file_type.is_file()); /// # /// # Ok(()) }) } /// ``` pub fn is_file(&self) -> bool { unreachable!("this impl only appears in the rendered docs") } /// Returns `true` if this file type represents a symbolic link. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let file_type = fs::metadata("a.txt").await?.file_type(); /// println!("{:?}", file_type.is_symlink()); /// # /// # Ok(()) }) } /// ``` pub fn is_symlink(&self) -> bool { unreachable!("this impl only appears in the rendered docs") } } } async-rs-async-std-57f61ae/src/fs/hard_link.rs000066400000000000000000000024221476537407000213110ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Creates a hard link on the filesystem. /// /// The `dst` path will be a link pointing to the `src` path. Note that operating systems often /// require these two paths to be located on the same filesystem. /// /// This function is an async version of [`std::fs::hard_link`]. /// /// [`std::fs::hard_link`]: https://doc.rust-lang.org/std/fs/fn.hard_link.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `src` does not point to an existing file. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// fs::hard_link("a.txt", "b.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn hard_link, Q: AsRef>(from: P, to: Q) -> io::Result<()> { let from = from.as_ref().to_owned(); let to = to.as_ref().to_owned(); spawn_blocking(move || { std::fs::hard_link(&from, &to).context(|| { format!( "could not create a hard link from `{}` to `{}`", from.display(), to.display() ) }) }) .await } async-rs-async-std-57f61ae/src/fs/metadata.rs000066400000000000000000000155121476537407000211420ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; /// Reads metadata for a path. /// /// This function will traverse symbolic links to read metadata for the target file or directory. /// If you want to read metadata without following symbolic links, use [`symlink_metadata`] /// instead. /// /// This function is an async version of [`std::fs::metadata`]. /// /// [`symlink_metadata`]: fn.symlink_metadata.html /// [`std::fs::metadata`]: https://doc.rust-lang.org/std/fs/fn.metadata.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing file or directory. /// * The current process lacks permissions to read metadata for the path. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let perm = fs::metadata("a.txt").await?.permissions(); /// # /// # Ok(()) }) } /// ``` pub async fn metadata>(path: P) -> io::Result { let path = path.as_ref().to_owned(); spawn_blocking(move || std::fs::metadata(path)).await } cfg_not_docs! { pub use std::fs::Metadata; } cfg_docs! { use std::time::SystemTime; use crate::fs::{FileType, Permissions}; /// Metadata for a file or directory. /// /// Metadata is returned by [`metadata`] and [`symlink_metadata`]. /// /// This type is a re-export of [`std::fs::Metadata`]. /// /// [`metadata`]: fn.metadata.html /// [`symlink_metadata`]: fn.symlink_metadata.html /// [`is_dir`]: #method.is_dir /// [`is_file`]: #method.is_file /// [`std::fs::Metadata`]: https://doc.rust-lang.org/std/fs/struct.Metadata.html #[derive(Clone, Debug)] pub struct Metadata { _private: (), } impl Metadata { /// Returns the file type from this metadata. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let metadata = fs::metadata("a.txt").await?; /// println!("{:?}", metadata.file_type()); /// # /// # Ok(()) }) } /// ``` pub fn file_type(&self) -> FileType { unreachable!("this impl only appears in the rendered docs") } /// Returns `true` if this metadata is for a regular directory. /// /// If this metadata is for a symbolic link, this method returns `false`. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let metadata = fs::metadata(".").await?; /// println!("{:?}", metadata.is_dir()); /// # /// # Ok(()) }) } /// ``` pub fn is_dir(&self) -> bool { unreachable!("this impl only appears in the rendered docs") } /// Returns `true` if this metadata is for a regular file. /// /// If this metadata is for a symbolic link, this method returns `false`. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let metadata = fs::metadata("a.txt").await?; /// println!("{:?}", metadata.is_file()); /// # /// # Ok(()) }) } /// ``` pub fn is_file(&self) -> bool { unreachable!("this impl only appears in the rendered docs") } /// Returns the file size in bytes. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let metadata = fs::metadata("a.txt").await?; /// println!("{}", metadata.len()); /// # /// # Ok(()) }) } /// ``` pub fn len(&self) -> u64 { unreachable!("this impl only appears in the rendered docs") } /// Returns the permissions from this metadata. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let metadata = fs::metadata("a.txt").await?; /// println!("{:?}", metadata.permissions()); /// # /// # Ok(()) }) } /// ``` pub fn permissions(&self) -> Permissions { unreachable!("this impl only appears in the rendered docs") } /// Returns the last modification time. /// /// # Errors /// /// This data may not be available on all platforms, in which case an error will be /// returned. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let metadata = fs::metadata("a.txt").await?; /// println!("{:?}", metadata.modified()); /// # /// # Ok(()) }) } /// ``` pub fn modified(&self) -> io::Result { unreachable!("this impl only appears in the rendered docs") } /// Returns the last access time. /// /// # Errors /// /// This data may not be available on all platforms, in which case an error will be /// returned. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let metadata = fs::metadata("a.txt").await?; /// println!("{:?}", metadata.accessed()); /// # /// # Ok(()) }) } /// ``` pub fn accessed(&self) -> io::Result { unreachable!("this impl only appears in the rendered docs") } /// Returns the creation time. /// /// # Errors /// /// This data may not be available on all platforms, in which case an error will be /// returned. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let metadata = fs::metadata("a.txt").await?; /// println!("{:?}", metadata.created()); /// # /// # Ok(()) }) } /// ``` pub fn created(&self) -> io::Result { unreachable!("this impl only appears in the rendered docs") } } } async-rs-async-std-57f61ae/src/fs/mod.rs000066400000000000000000000035611476537407000201420ustar00rootroot00000000000000//! Filesystem manipulation operations. //! //! This module is an async version of [`std::fs`]. //! //! [`os::unix::fs`]: ../os/unix/fs/index.html //! [`os::windows::fs`]: ../os/windows/fs/index.html //! [`std::fs`]: https://doc.rust-lang.org/std/fs/index.html //! //! # Platform-specific extensions //! //! * Unix: use the [`os::unix::fs`] module. //! * Windows: use the [`os::windows::fs`] module. //! //! # Examples //! //! Create a new file and write some bytes to it: //! //! ```no_run //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! use async_std::fs::File; //! use async_std::prelude::*; //! //! let mut file = File::create("a.txt").await?; //! file.write_all(b"Hello, world!").await?; //! # //! # Ok(()) }) } //! ``` pub use dir_builder::DirBuilder; pub use dir_entry::DirEntry; pub use file::File; pub use file_type::FileType; pub use metadata::Metadata; pub use open_options::OpenOptions; pub use permissions::Permissions; pub use read_dir::ReadDir; pub use canonicalize::canonicalize; pub use copy::copy; pub use create_dir::create_dir; pub use create_dir_all::create_dir_all; pub use hard_link::hard_link; pub use metadata::metadata; pub use read::read; pub use read_dir::read_dir; pub use read_link::read_link; pub use read_to_string::read_to_string; pub use remove_dir::remove_dir; pub use remove_dir_all::remove_dir_all; pub use remove_file::remove_file; pub use rename::rename; pub use set_permissions::set_permissions; pub use symlink_metadata::symlink_metadata; pub use write::write; mod canonicalize; mod copy; mod create_dir; mod create_dir_all; mod dir_builder; mod dir_entry; mod file; mod file_type; mod hard_link; mod metadata; mod open_options; mod permissions; mod read; mod read_dir; mod read_link; mod read_to_string; mod remove_dir; mod remove_dir_all; mod remove_file; mod rename; mod set_permissions; mod symlink_metadata; mod write; async-rs-async-std-57f61ae/src/fs/open_options.rs000066400000000000000000000213341476537407000220750ustar00rootroot00000000000000use std::future::Future; use crate::fs::File; use crate::io; use crate::path::Path; use crate::task::spawn_blocking; /// A builder for opening files with configurable options. /// /// Files can be opened in [`read`] and/or [`write`] mode. /// /// The [`append`] option opens files in a special writing mode that moves the file cursor to the /// end of file before every write operation. /// /// It is also possible to [`truncate`] the file right after opening, to [`create`] a file if it /// doesn't exist yet, or to always create a new file with [`create_new`]. /// /// This type is an async version of [`std::fs::OpenOptions`]. /// /// [`read`]: #method.read /// [`write`]: #method.write /// [`append`]: #method.append /// [`truncate`]: #method.truncate /// [`create`]: #method.create /// [`create_new`]: #method.create_new /// [`std::fs::OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html /// /// # Examples /// /// Open a file for reading: /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .read(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` /// /// Open a file for both reading and writing, and create it if it doesn't exist yet: /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .read(true) /// .write(true) /// .create(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` #[derive(Clone, Debug)] pub struct OpenOptions(std::fs::OpenOptions); impl OpenOptions { /// Creates a blank set of options. /// /// All options are initially set to `false`. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .read(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn new() -> OpenOptions { OpenOptions(std::fs::OpenOptions::new()) } /// Configures the option for read mode. /// /// When set to `true`, this option means the file will be readable after opening. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .read(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn read(&mut self, read: bool) -> &mut OpenOptions { self.0.read(read); self } /// Configures the option for write mode. /// /// When set to `true`, this option means the file will be writable after opening. /// /// If the file already exists, write calls on it will overwrite the previous contents without /// truncating it. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .write(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn write(&mut self, write: bool) -> &mut OpenOptions { self.0.write(write); self } /// Configures the option for append mode. /// /// When set to `true`, this option means the file will be writable after opening and the file /// cursor will be moved to the end of file before every write operation. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .append(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn append(&mut self, append: bool) -> &mut OpenOptions { self.0.append(append); self } /// Configures the option for truncating the previous file. /// /// When set to `true`, the file will be truncated to the length of 0 bytes. /// /// The file must be opened in [`write`] or [`append`] mode for truncation to work. /// /// [`write`]: #method.write /// [`append`]: #method.append /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .write(true) /// .truncate(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions { self.0.truncate(truncate); self } /// Configures the option for creating a new file if it doesn't exist. /// /// When set to `true`, this option means a new file will be created if it doesn't exist. /// /// The file must be opened in [`write`] or [`append`] mode for file creation to work. /// /// [`write`]: #method.write /// [`append`]: #method.append /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .write(true) /// .create(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn create(&mut self, create: bool) -> &mut OpenOptions { self.0.create(create); self } /// Configures the option for creating a new file or failing if it already exists. /// /// When set to `true`, this option means a new file will be created, or the open operation /// will fail if the file already exists. /// /// The file must be opened in [`write`] or [`append`] mode for file creation to work. /// /// [`write`]: #method.write /// [`append`]: #method.append /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .write(true) /// .create_new(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions { self.0.create_new(create_new); self } /// Opens a file with the configured options. /// /// # Errors /// /// An error will be returned in the following situations: /// /// * The file does not exist and neither [`create`] nor [`create_new`] were set. /// * The file's parent directory does not exist. /// * The current process lacks permissions to open the file in the configured mode. /// * The file already exists and [`create_new`] was set. /// * Invalid combination of options was used, like [`truncate`] was set but [`write`] wasn't, /// or none of [`read`], [`write`], and [`append`] modes was set. /// * An OS-level occurred, like too many files are open or the file name is too long. /// * Some other I/O error occurred. /// /// [`read`]: #method.read /// [`write`]: #method.write /// [`append`]: #method.append /// [`truncate`]: #method.truncate /// [`create`]: #method.create /// [`create_new`]: #method.create_new /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::OpenOptions; /// /// let file = OpenOptions::new() /// .read(true) /// .open("a.txt") /// .await?; /// # /// # Ok(()) }) } /// ``` pub fn open>(&self, path: P) -> impl Future> { let path = path.as_ref().to_owned(); let options = self.0.clone(); async move { let file = spawn_blocking(move || options.open(path)).await?; Ok(File::new(file, true)) } } } impl Default for OpenOptions { fn default() -> Self { Self::new() } } cfg_unix! { use crate::os::unix::fs::OpenOptionsExt; impl OpenOptionsExt for OpenOptions { fn mode(&mut self, mode: u32) -> &mut Self { self.0.mode(mode); self } fn custom_flags(&mut self, flags: i32) -> &mut Self { self.0.custom_flags(flags); self } } } async-rs-async-std-57f61ae/src/fs/permissions.rs000066400000000000000000000031551476537407000217350ustar00rootroot00000000000000cfg_not_docs! { pub use std::fs::Permissions; } cfg_docs! { /// A set of permissions on a file or directory. /// /// This type is a re-export of [`std::fs::Permissions`]. /// /// [`std::fs::Permissions`]: https://doc.rust-lang.org/std/fs/struct.Permissions.html #[derive(Clone, PartialEq, Eq, Debug)] pub struct Permissions { _private: (), } impl Permissions { /// Returns the read-only flag. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let perm = fs::metadata("a.txt").await?.permissions(); /// println!("{:?}", perm.readonly()); /// # /// # Ok(()) }) } /// ``` pub fn readonly(&self) -> bool { unreachable!("this impl only appears in the rendered docs") } /// Configures the read-only flag. /// /// [`fs::set_permissions`]: fn.set_permissions.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let mut perm = fs::metadata("a.txt").await?.permissions(); /// perm.set_readonly(true); /// fs::set_permissions("a.txt", perm).await?; /// # /// # Ok(()) }) } /// ``` pub fn set_readonly(&mut self, readonly: bool) { unreachable!("this impl only appears in the rendered docs") } } } async-rs-async-std-57f61ae/src/fs/read.rs000066400000000000000000000025031476537407000202710ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Reads the entire contents of a file as raw bytes. /// /// This is a convenience function for reading entire files. It pre-allocates a buffer based on the /// file size when available, so it is typically faster than manually opening a file and reading /// from it. /// /// If you want to read the contents as a string, use [`read_to_string`] instead. /// /// This function is an async version of [`std::fs::read`]. /// /// [`read_to_string`]: fn.read_to_string.html /// [`std::fs::read`]: https://doc.rust-lang.org/std/fs/fn.read.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing file. /// * The current process lacks permissions to read the file. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let contents = fs::read("a.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn read>(path: P) -> io::Result> { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::read(&path).context(|| format!("could not read file `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/read_dir.rs000066400000000000000000000067741476537407000211450ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use crate::fs::DirEntry; use crate::io; use crate::path::Path; use crate::stream::Stream; use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; use crate::utils::Context as _; /// Returns a stream of entries in a directory. /// /// The stream yields items of type [`io::Result`]`<`[`DirEntry`]`>`. Note that I/O errors can /// occur while reading from the stream. /// /// This function is an async version of [`std::fs::read_dir`]. /// /// [`io::Result`]: ../io/type.Result.html /// [`DirEntry`]: struct.DirEntry.html /// [`std::fs::read_dir`]: https://doc.rust-lang.org/std/fs/fn.read_dir.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing directory. /// * The current process lacks permissions to read the contents of the directory. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// use async_std::prelude::*; /// /// let mut entries = fs::read_dir(".").await?; /// /// while let Some(res) = entries.next().await { /// let entry = res?; /// println!("{}", entry.file_name().to_string_lossy()); /// } /// # /// # Ok(()) }) } /// ``` pub async fn read_dir>(path: P) -> io::Result { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::read_dir(&path) .context(|| format!("could not read directory `{}`", path.display())) }) .await .map(ReadDir::new) } /// A stream of entries in a directory. /// /// This stream is returned by [`read_dir`] and yields items of type /// [`io::Result`]`<`[`DirEntry`]`>`. Each [`DirEntry`] can then retrieve information like entry's /// path or metadata. /// /// This type is an async version of [`std::fs::ReadDir`]. /// /// [`read_dir`]: fn.read_dir.html /// [`io::Result`]: ../io/type.Result.html /// [`DirEntry`]: struct.DirEntry.html /// [`std::fs::ReadDir`]: https://doc.rust-lang.org/std/fs/struct.ReadDir.html #[derive(Debug)] pub struct ReadDir(State); /// The state of an asynchronous `ReadDir`. /// /// The `ReadDir` can be either idle or busy performing an asynchronous operation. #[derive(Debug)] enum State { Idle(Option), Busy(JoinHandle<(std::fs::ReadDir, Option>)>), } impl ReadDir { /// Creates an asynchronous `ReadDir` from a synchronous handle. pub(crate) fn new(inner: std::fs::ReadDir) -> ReadDir { ReadDir(State::Idle(Some(inner))) } } impl Stream for ReadDir { type Item = io::Result; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { loop { match &mut self.0 { State::Idle(opt) => { let mut inner = opt.take().unwrap(); // Start the operation asynchronously. self.0 = State::Busy(spawn_blocking(move || { let next = inner.next(); (inner, next) })); } // Poll the asynchronous operation the file is currently blocked on. State::Busy(task) => { let (inner, opt) = futures_core::ready!(Pin::new(task).poll(cx)); self.0 = State::Idle(Some(inner)); return Poll::Ready(opt.map(|res| res.map(DirEntry::new))); } } } } } async-rs-async-std-57f61ae/src/fs/read_link.rs000066400000000000000000000020001476537407000212760ustar00rootroot00000000000000use crate::io; use crate::path::{Path, PathBuf}; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Reads a symbolic link and returns the path it points to. /// /// This function is an async version of [`std::fs::read_link`]. /// /// [`std::fs::read_link`]: https://doc.rust-lang.org/std/fs/fn.read_link.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing link. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let path = fs::read_link("a.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn read_link>(path: P) -> io::Result { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::read_link(&path) .map(Into::into) .context(|| format!("could not read link `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/read_to_string.rs000066400000000000000000000026561476537407000223720ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Reads the entire contents of a file as a string. /// /// This is a convenience function for reading entire files. It pre-allocates a string based on the /// file size when available, so it is typically faster than manually opening a file and reading /// from it. /// /// If you want to read the contents as raw bytes, use [`read`] instead. /// /// This function is an async version of [`std::fs::read_to_string`]. /// /// [`read`]: fn.read.html /// [`std::fs::read_to_string`]: https://doc.rust-lang.org/std/fs/fn.read_to_string.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing file. /// * The current process lacks permissions to read the file. /// * The contents of the file cannot be read as a UTF-8 string. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let contents = fs::read_to_string("a.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn read_to_string>(path: P) -> io::Result { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::read_to_string(&path) .context(|| format!("could not read file `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/remove_dir.rs000066400000000000000000000020141476537407000215060ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Removes an empty directory. /// /// This function is an async version of [`std::fs::remove_dir`]. /// /// [`std::fs::remove_dir`]: https://doc.rust-lang.org/std/fs/fn.remove_dir.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` is not an existing and empty directory. /// * The current process lacks permissions to remove the directory. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// fs::remove_dir("./some/directory").await?; /// # /// # Ok(()) }) } /// ``` pub async fn remove_dir>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::remove_dir(&path) .context(|| format!("could not remove directory `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/remove_dir_all.rs000066400000000000000000000020651476537407000223440ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Removes a directory and all of its contents. /// /// This function is an async version of [`std::fs::remove_dir_all`]. /// /// [`std::fs::remove_dir_all`]: https://doc.rust-lang.org/std/fs/fn.remove_dir_all.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` is not an existing and empty directory. /// * The current process lacks permissions to remove the directory. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// fs::remove_dir_all("./some/directory").await?; /// # /// # Ok(()) }) } /// ``` pub async fn remove_dir_all>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::remove_dir_all(&path) .context(|| format!("could not remove directory `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/remove_file.rs000066400000000000000000000017551476537407000216620ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Removes a file. /// /// This function is an async version of [`std::fs::remove_file`]. /// /// [`std::fs::remove_file`]: https://doc.rust-lang.org/std/fs/fn.remove_file.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing file. /// * The current process lacks permissions to remove the file. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// fs::remove_file("a.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn remove_file>(path: P) -> io::Result<()> { let path = path.as_ref().to_owned(); spawn_blocking(move || { std::fs::remove_file(&path) .context(|| format!("could not remove file `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/fs/rename.rs000066400000000000000000000025171476537407000206320ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Renames a file or directory to a new location. /// /// If a file or directory already exists at the target location, it will be overwritten by this /// operation. /// /// This function is an async version of [`std::fs::rename`]. /// /// [`std::fs::rename`]: https://doc.rust-lang.org/std/fs/fn.rename.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `from` does not point to an existing file or directory. /// * `from` and `to` are on different filesystems. /// * The current process lacks permissions to do the rename operation. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// fs::rename("a.txt", "b.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> { let from = from.as_ref().to_owned(); let to = to.as_ref().to_owned(); spawn_blocking(move || { std::fs::rename(&from, &to).context(|| { format!( "could not rename `{}` to `{}`", from.display(), to.display() ) }) }) .await } async-rs-async-std-57f61ae/src/fs/set_permissions.rs000066400000000000000000000021371476537407000226070ustar00rootroot00000000000000use crate::fs::Permissions; use crate::io; use crate::path::Path; use crate::task::spawn_blocking; /// Changes the permissions of a file or directory. /// /// This function is an async version of [`std::fs::set_permissions`]. /// /// [`std::fs::set_permissions`]: https://doc.rust-lang.org/std/fs/fn.set_permissions.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing file or directory. /// * The current process lacks permissions to change attributes on the file or directory. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let mut perm = fs::metadata("a.txt").await?.permissions(); /// perm.set_readonly(true); /// fs::set_permissions("a.txt", perm).await?; /// # /// # Ok(()) }) } /// ``` pub async fn set_permissions>(path: P, perm: Permissions) -> io::Result<()> { let path = path.as_ref().to_owned(); spawn_blocking(move || std::fs::set_permissions(path, perm)).await } async-rs-async-std-57f61ae/src/fs/symlink_metadata.rs000066400000000000000000000022511476537407000227040ustar00rootroot00000000000000use crate::fs::Metadata; use crate::io; use crate::path::Path; use crate::task::spawn_blocking; /// Reads metadata for a path without following symbolic links. /// /// If you want to follow symbolic links before reading metadata of the target file or directory, /// use [`metadata`] instead. /// /// This function is an async version of [`std::fs::symlink_metadata`]. /// /// [`metadata`]: fn.metadata.html /// [`std::fs::symlink_metadata`]: https://doc.rust-lang.org/std/fs/fn.symlink_metadata.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * `path` does not point to an existing file or directory. /// * The current process lacks permissions to read metadata for the path. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// let perm = fs::symlink_metadata("a.txt").await?.permissions(); /// # /// # Ok(()) }) } /// ``` pub async fn symlink_metadata>(path: P) -> io::Result { let path = path.as_ref().to_owned(); spawn_blocking(move || std::fs::symlink_metadata(path)).await } async-rs-async-std-57f61ae/src/fs/write.rs000066400000000000000000000023241476537407000205110ustar00rootroot00000000000000use crate::io; use crate::path::Path; use crate::task::spawn_blocking; use crate::utils::Context as _; /// Writes a slice of bytes as the new contents of a file. /// /// This function will create a file if it does not exist, and will entirely replace its contents /// if it does. /// /// This function is an async version of [`std::fs::write`]. /// /// [`std::fs::write`]: https://doc.rust-lang.org/std/fs/fn.write.html /// /// # Errors /// /// An error will be returned in the following situations: /// /// * The file's parent directory does not exist. /// * The current process lacks permissions to write to the file. /// * Some other I/O error occurred. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// /// fs::write("a.txt", b"Hello world!").await?; /// # /// # Ok(()) }) } /// ``` pub async fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { let path = path.as_ref().to_owned(); let contents = contents.as_ref().to_owned(); spawn_blocking(move || { std::fs::write(&path, contents) .context(|| format!("could not write to file `{}`", path.display())) }) .await } async-rs-async-std-57f61ae/src/future/000077500000000000000000000000001476537407000177125ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/future/future/000077500000000000000000000000001476537407000212245ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/future/future/delay.rs000066400000000000000000000017531476537407000226760ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use std::time::Duration; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; use crate::utils::{timer_after, Timer}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct DelayFuture { #[pin] future: F, #[pin] delay: Timer, } } impl DelayFuture { pub fn new(future: F, dur: Duration) -> DelayFuture { let delay = timer_after(dur); DelayFuture { future, delay } } } impl Future for DelayFuture { type Output = F::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); match this.delay.poll(cx) { Poll::Pending => Poll::Pending, Poll::Ready(_) => match this.future.poll(cx) { Poll::Ready(v) => Poll::Ready(v), Poll::Pending => Poll::Pending, }, } } } async-rs-async-std-57f61ae/src/future/future/flatten.rs000066400000000000000000000031751476537407000232350ustar00rootroot00000000000000use pin_project_lite::pin_project; use std::future::Future; use std::pin::Pin; use crate::future::IntoFuture; use crate::task::{ready, Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct FlattenFuture { #[pin] state: State, } } pin_project! { #[project = StateProj] #[derive(Debug)] enum State { First { #[pin] fut1: Fut1, }, Second { #[pin] fut2: Fut2, }, Empty, } } impl FlattenFuture { pub(crate) fn new(fut1: Fut1) -> FlattenFuture { FlattenFuture { state: State::First { fut1 }, } } } impl Future for FlattenFuture::Future> where Fut1: Future, Fut1::Output: IntoFuture, { type Output = ::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut state = self.project().state; loop { match state.as_mut().project() { StateProj::First { fut1 } => { let fut2 = ready!(fut1.poll(cx)).into_future(); state.set(State::Second { fut2 }); } StateProj::Second { fut2 } => { let v = ready!(fut2.poll(cx)); state.set(State::Empty); return Poll::Ready(v); } StateProj::Empty => panic!("polled a completed future"), } } } } async-rs-async-std-57f61ae/src/future/future/join.rs000066400000000000000000000026101476537407000225300ustar00rootroot00000000000000use std::pin::Pin; use crate::future::MaybeDone; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; use std::future::Future; pin_project! { #[allow(missing_docs)] #[allow(missing_debug_implementations)] pub struct Join where L: Future, R: Future, { #[pin] left: MaybeDone, #[pin] right: MaybeDone, } } impl Join where L: Future, R: Future, { pub(crate) fn new(left: L, right: R) -> Self { Self { left: MaybeDone::new(left), right: MaybeDone::new(right), } } } impl Future for Join where L: Future, R: Future, { type Output = (L::Output, R::Output); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let mut left = this.left; let mut right = this.right; let is_left_ready = Future::poll(Pin::new(&mut left), cx).is_ready(); if is_left_ready && right.as_ref().output().is_some() { return Poll::Ready((left.take().unwrap(), right.take().unwrap())); } let is_right_ready = Future::poll(Pin::new(&mut right), cx).is_ready(); if is_right_ready && left.as_ref().output().is_some() { return Poll::Ready((left.take().unwrap(), right.take().unwrap())); } Poll::Pending } } async-rs-async-std-57f61ae/src/future/future/mod.rs000066400000000000000000000173241476537407000223600ustar00rootroot00000000000000cfg_unstable! { mod delay; mod flatten; mod race; mod try_race; mod join; mod try_join; use std::time::Duration; use delay::DelayFuture; use flatten::FlattenFuture; use crate::future::IntoFuture; use race::Race; use try_race::TryRace; use join::Join; use try_join::TryJoin; } cfg_unstable_default! { use crate::future::timeout::TimeoutFuture; } pub use core::future::Future as Future; #[doc = r#" Extension methods for [`Future`]. [`Future`]: ../future/trait.Future.html "#] #[cfg(any(feature = "std", feature = "docs"))] pub trait FutureExt: Future { /// Returns a Future that delays execution for a specified time. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// use async_std::prelude::*; /// use async_std::future; /// use std::time::Duration; /// /// let a = future::ready(1).delay(Duration::from_millis(2000)); /// dbg!(a.await); /// # }) /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn delay(self, dur: Duration) -> DelayFuture where Self: Sized, { DelayFuture::new(self, dur) } /// Flatten out the execution of this future when the result itself /// can be converted into another future. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// use async_std::prelude::*; /// /// let nested_future = async { async { 1 } }; /// let future = nested_future.flatten(); /// assert_eq!(future.await, 1); /// # }) /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn flatten( self, ) -> FlattenFuture::Future> where Self: Sized, ::Output: IntoFuture, { FlattenFuture::new(self) } #[doc = r#" Waits for one of two similarly-typed futures to complete. Awaits multiple futures simultaneously, returning the output of the first future that completes. This function will return a new future which awaits for either one of both futures to complete. If multiple futures are completed at the same time, resolution will occur in the order that they have been passed. Note that this function consumes all futures passed, and once a future is completed, all other futures are dropped. # Examples ``` # async_std::task::block_on(async { use async_std::prelude::*; use async_std::future; let a = future::pending(); let b = future::ready(1u8); let c = future::ready(2u8); let f = a.race(b).race(c); assert_eq!(f.await, 1u8); # }); ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn race( self, other: F, ) -> Race where Self: std::future::Future + Sized, F: std::future::Future::Output>, { Race::new(self, other) } #[doc = r#" Waits for one of two similarly-typed fallible futures to complete. Awaits multiple futures simultaneously, returning all results once complete. `try_race` is similar to [`race`], but keeps going if a future resolved to an error until all futures have been resolved. In which case an error is returned. The ordering of which value is yielded when two futures resolve simultaneously is intentionally left unspecified. [`race`]: #method.race # Examples ``` # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::future; use std::io::{Error, ErrorKind}; let a = future::pending::>(); let b = future::ready(Err(Error::from(ErrorKind::Other))); let c = future::ready(Ok(1u8)); let f = a.try_race(b).try_race(c); assert_eq!(f.await?, 1u8); # # Ok(()) }) } ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn try_race( self, other: F ) -> TryRace where Self: std::future::Future> + Sized, F: std::future::Future::Output>, { TryRace::new(self, other) } #[doc = r#" Waits for two similarly-typed futures to complete. Awaits multiple futures simultaneously, returning the output of the futures once both complete. This function returns a new future which polls both futures concurrently. # Examples ``` # async_std::task::block_on(async { use async_std::prelude::*; use async_std::future; let a = future::ready(1u8); let b = future::ready(2u16); let f = a.join(b); assert_eq!(f.await, (1u8, 2u16)); # }); ``` "#] #[cfg(any(feature = "unstable", feature = "docs"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn join( self, other: F ) -> Join where Self: std::future::Future + Sized, F: std::future::Future, { Join::new(self, other) } #[doc = r#" Waits for two similarly-typed fallible futures to complete. Awaits multiple futures simultaneously, returning all results once complete. `try_join` is similar to [`join`], but returns an error immediately if a future resolves to an error. [`join`]: #method.join # Examples ``` # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::future; let a = future::ready(Err::("Error")); let b = future::ready(Ok(1u8)); let f = a.try_join(b); assert_eq!(f.await, Err("Error")); let a = future::ready(Ok::(1u8)); let b = future::ready(Ok::(2u16)); let f = a.try_join(b); assert_eq!(f.await, Ok((1u8, 2u16))); # # Ok(()) }) } ``` "#] #[cfg(any(feature = "unstable", feature = "docs"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn try_join( self, other: F ) -> TryJoin where Self: std::future::Future> + Sized, F: std::future::Future>, { TryJoin::new(self, other) } #[doc = r#" Waits for both the future and a timeout, if the timeout completes before the future, it returns a TimeoutError. # Example ``` # async_std::task::block_on(async { # use std::time::Duration; use async_std::prelude::*; use async_std::future; let fut = future::ready(0); let dur = Duration::from_millis(100); let res = fut.timeout(dur).await; assert!(res.is_ok()); let fut = future::pending::<()>(); let dur = Duration::from_millis(100); let res = fut.timeout(dur).await; assert!(res.is_err()) # # }); ``` "#] #[cfg(any(all(feature = "default", feature = "unstable"), feature = "docs"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn timeout(self, dur: Duration) -> TimeoutFuture where Self: Sized { TimeoutFuture::new(self, dur) } } #[cfg(any(feature = "std", feature = "docs"))] impl FutureExt for T {} async-rs-async-std-57f61ae/src/future/future/race.rs000066400000000000000000000023431476537407000225060ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use crate::future::MaybeDone; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; pin_project! { #[allow(missing_docs)] #[allow(missing_debug_implementations)] pub struct Race where L: Future, R: Future { #[pin] left: MaybeDone, #[pin] right: MaybeDone, } } impl Race where L: Future, R: Future, { pub(crate) fn new(left: L, right: R) -> Self { Self { left: MaybeDone::new(left), right: MaybeDone::new(right), } } } impl Future for Race where L: Future, R: Future, { type Output = L::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let mut left = this.left; if Future::poll(Pin::new(&mut left), cx).is_ready() { return Poll::Ready(left.take().unwrap()); } let mut right = this.right; if Future::poll(Pin::new(&mut right), cx).is_ready() { return Poll::Ready(right.take().unwrap()); } Poll::Pending } } async-rs-async-std-57f61ae/src/future/future/try_join.rs000066400000000000000000000036011476537407000234270ustar00rootroot00000000000000use std::pin::Pin; use crate::future::MaybeDone; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; use std::future::Future; pin_project! { #[allow(missing_docs)] #[allow(missing_debug_implementations)] pub struct TryJoin where L: Future, R: Future, { #[pin] left: MaybeDone, #[pin] right: MaybeDone, } } impl TryJoin where L: Future, R: Future, { pub(crate) fn new(left: L, right: R) -> Self { Self { left: MaybeDone::new(left), right: MaybeDone::new(right), } } } impl Future for TryJoin where L: Future>, R: Future>, { type Output = Result<(A, B), E>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let mut left = this.left; let mut right = this.right; if Future::poll(Pin::new(&mut left), cx).is_ready() { if left.as_ref().output().unwrap().is_err() { return Poll::Ready(Err(left.take().unwrap().err().unwrap())); } else if right.as_ref().output().is_some() { return Poll::Ready(Ok(( left.take().unwrap().ok().unwrap(), right.take().unwrap().ok().unwrap(), ))); } } if Future::poll(Pin::new(&mut right), cx).is_ready() { if right.as_ref().output().unwrap().is_err() { return Poll::Ready(Err(right.take().unwrap().err().unwrap())); } else if left.as_ref().output().is_some() { return Poll::Ready(Ok(( left.take().unwrap().ok().unwrap(), right.take().unwrap().ok().unwrap(), ))); } } Poll::Pending } } async-rs-async-std-57f61ae/src/future/future/try_race.rs000066400000000000000000000033471476537407000234110ustar00rootroot00000000000000use std::pin::Pin; use crate::future::MaybeDone; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; use std::future::Future; pin_project! { #[allow(missing_docs)] #[allow(missing_debug_implementations)] pub struct TryRace where L: Future, R: Future { #[pin] left: MaybeDone, #[pin] right: MaybeDone, } } impl TryRace where L: Future, R: Future, { pub(crate) fn new(left: L, right: R) -> Self { Self { left: MaybeDone::new(left), right: MaybeDone::new(right), } } } impl Future for TryRace where L: Future>, R: Future, { type Output = L::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let mut left_errored = false; // Check if the left future is ready & successful. Continue if not. let mut left = this.left; if Future::poll(Pin::new(&mut left), cx).is_ready() { if left.as_ref().output().unwrap().is_ok() { return Poll::Ready(left.take().unwrap()); } else { left_errored = true; } } // Check if the right future is ready & successful. Return err if left // future also resolved to err. Continue if not. let mut right = this.right; let is_ready = Future::poll(Pin::new(&mut right), cx).is_ready(); if is_ready && (right.as_ref().output().unwrap().is_ok() || left_errored) { return Poll::Ready(right.take().unwrap()); } Poll::Pending } } async-rs-async-std-57f61ae/src/future/into_future.rs000066400000000000000000000022111476537407000226170ustar00rootroot00000000000000use std::future::Future; /// Convert a type into a `Future`. /// /// # Examples /// /// ``` /// use async_std::future::{Future, IntoFuture}; /// use async_std::io; /// use async_std::pin::Pin; /// /// struct Client; /// /// impl Client { /// pub async fn send(self) -> io::Result<()> { /// // Send a request /// Ok(()) /// } /// } /// /// impl IntoFuture for Client { /// type Output = io::Result<()>; /// /// type Future = Pin>>; /// /// fn into_future(self) -> Self::Future { /// Box::pin(async { /// self.send().await /// }) /// } /// } /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait IntoFuture { /// The type of value produced on completion. type Output; /// Which kind of future are we turning this into? type Future: Future; /// Create a future from a value fn into_future(self) -> Self::Future; } impl IntoFuture for T { type Output = T::Output; type Future = T; fn into_future(self) -> Self::Future { self } } async-rs-async-std-57f61ae/src/future/maybe_done.rs000066400000000000000000000046721476537407000223730ustar00rootroot00000000000000//! A type that wraps a future to keep track of its completion status. //! //! This implementation was taken from the original `macro_rules` `join/try_join` //! macros in the `futures-preview` crate. use std::future::Future; use std::mem; use std::pin::Pin; use std::task::{Context, Poll}; use futures_core::ready; /// A future that may have completed. #[derive(Debug)] pub(crate) enum MaybeDone { /// A not-yet-completed future Future(Fut), /// The output of the completed future Done(Fut::Output), /// The empty variant after the result of a [`MaybeDone`] has been /// taken using the [`take`](MaybeDone::take) method. Gone, } impl MaybeDone { /// Create a new instance of `MaybeDone`. pub(crate) fn new(future: Fut) -> MaybeDone { Self::Future(future) } /// Returns an [`Option`] containing a reference to the output of the future. /// The output of this method will be [`Some`] if and only if the inner /// future has been completed and [`take`](MaybeDone::take) /// has not yet been called. #[inline] pub(crate) fn output(self: Pin<&Self>) -> Option<&Fut::Output> { let this = self.get_ref(); match this { MaybeDone::Done(res) => Some(res), _ => None, } } /// Attempt to take the output of a `MaybeDone` without driving it /// towards completion. #[inline] pub(crate) fn take(self: Pin<&mut Self>) -> Option { unsafe { let this = self.get_unchecked_mut(); match this { MaybeDone::Done(_) => {} MaybeDone::Future(_) | MaybeDone::Gone => return None, }; if let MaybeDone::Done(output) = mem::replace(this, MaybeDone::Gone) { Some(output) } else { unreachable!() } } } } impl Future for MaybeDone { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let res = unsafe { match Pin::as_mut(&mut self).get_unchecked_mut() { MaybeDone::Future(a) => ready!(Pin::new_unchecked(a).poll(cx)), MaybeDone::Done(_) => return Poll::Ready(()), MaybeDone::Gone => panic!("MaybeDone polled after value taken"), } }; self.set(MaybeDone::Done(res)); Poll::Ready(()) } } async-rs-async-std-57f61ae/src/future/mod.rs000066400000000000000000000057101476537407000210420ustar00rootroot00000000000000//! Asynchronous values. //! //! ## Base Futures Concurrency //! //! Often it's desirable to await multiple futures as if it was a single //! future. The `join` family of operations converts multiple futures into a //! single future that returns all of their outputs. The `race` family of //! operations converts multiple future into a single future that returns the //! first output. //! //! For operating on futures the following functions can be used: //! //! | Name | Return signature | When does it return? | //! | --- | --- | --- | //! | [`Future::join`] | `(T1, T2)` | Wait for all to complete //! | [`Future::race`] | `T` | Return on first value //! //! ## Fallible Futures Concurrency //! //! For operating on futures that return `Result` additional `try_` variants of //! the functions mentioned before can be used. These functions are aware of `Result`, //! and will behave slightly differently from their base variants. //! //! In the case of `try_join`, if any of the futures returns `Err` all //! futures are dropped and an error is returned. This is referred to as //! "short-circuiting". //! //! In the case of `try_race`, instead of returning the first future that //! completes it returns the first future that _successfully_ completes. This //! means `try_race` will keep going until any one of the futures returns //! `Ok`, or _all_ futures have returned `Err`. //! //! However sometimes it can be useful to use the base variants of the functions //! even on futures that return `Result`. Here is an overview of operations that //! work on `Result`, and their respective semantics: //! //! | Name | Return signature | When does it return? | //! | --- | --- | --- | //! | [`Future::join`] | `(Result, Result)` | Wait for all to complete //! | [`Future::try_join`] | `Result<(T1, T2), E>` | Return on first `Err`, wait for all to complete //! | [`Future::race`] | `Result` | Return on first value //! | [`Future::try_race`] | `Result` | Return on first `Ok`, reject on last Err //! //! [`Future::join`]: trait.Future.html#method.join //! [`Future::try_join`]: trait.Future.html#method.try_join //! [`Future::race`]: trait.Future.html#method.race //! [`Future::try_race`]: trait.Future.html#method.try_race cfg_alloc! { pub use future::Future; pub(crate) mod future; } cfg_std! { pub use pending::pending; pub use poll_fn::poll_fn; pub use ready::ready; mod pending; mod poll_fn; mod ready; } #[cfg(any(feature = "unstable", feature = "default"))] pub use timeout::{timeout, TimeoutError}; #[cfg(any(feature = "unstable", feature = "default"))] mod timeout; cfg_unstable! { pub use into_future::IntoFuture; pub(crate) use maybe_done::MaybeDone; mod into_future; mod maybe_done; } async-rs-async-std-57f61ae/src/future/pending.rs000066400000000000000000000014441476537407000217070ustar00rootroot00000000000000use std::future::Future; use std::marker::PhantomData; use std::pin::Pin; use crate::task::{Context, Poll}; /// Never resolves to a value. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use std::time::Duration; /// /// use async_std::future; /// use async_std::io; /// /// let dur = Duration::from_secs(1); /// let fut = future::pending(); /// /// let res: io::Result<()> = io::timeout(dur, fut).await; /// assert!(res.is_err()); /// # /// # }) /// ``` pub async fn pending() -> T { let fut = Pending { _marker: PhantomData, }; fut.await } struct Pending { _marker: PhantomData, } impl Future for Pending { type Output = T; fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { Poll::Pending } } async-rs-async-std-57f61ae/src/future/poll_fn.rs000066400000000000000000000017401476537407000217130ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::task::{Context, Poll}; /// Creates a new future wrapping around a function returning [`Poll`]. /// /// Polling the returned future delegates to the wrapped function. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::future; /// use async_std::task::{Context, Poll}; /// /// fn poll_greeting(_: &mut Context<'_>) -> Poll { /// Poll::Ready("hello world".to_string()) /// } /// /// assert_eq!(future::poll_fn(poll_greeting).await, "hello world"); /// # /// # }) /// ``` pub async fn poll_fn(f: F) -> T where F: FnMut(&mut Context<'_>) -> Poll, { let fut = PollFn { f }; fut.await } struct PollFn { f: F, } impl Unpin for PollFn {} impl Future for PollFn where F: FnMut(&mut Context<'_>) -> Poll, { type Output = T; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { (&mut self.f)(cx) } } async-rs-async-std-57f61ae/src/future/ready.rs000066400000000000000000000006471476537407000213730ustar00rootroot00000000000000/// Resolves to the provided value. /// /// This function is an async version of [`std::convert::identity`]. /// /// [`std::convert::identity`]: https://doc.rust-lang.org/std/convert/fn.identity.html /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::future; /// /// assert_eq!(future::ready(10).await, 10); /// # /// # }) /// ``` pub async fn ready(val: T) -> T { val } async-rs-async-std-57f61ae/src/future/timeout.rs000066400000000000000000000041221476537407000217450ustar00rootroot00000000000000use std::error::Error; use std::fmt; use std::future::Future; use std::pin::Pin; use std::time::Duration; use pin_project_lite::pin_project; use crate::task::{Context, Poll}; use crate::utils::{timer_after, Timer}; /// Awaits a future or times out after a duration of time. /// /// If you want to await an I/O future consider using /// [`io::timeout`](../io/fn.timeout.html) instead. /// /// # Examples /// /// ``` /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use std::time::Duration; /// /// use async_std::future; /// /// let never = future::pending::<()>(); /// let dur = Duration::from_millis(5); /// assert!(future::timeout(dur, never).await.is_err()); /// # /// # Ok(()) }) } /// ``` pub async fn timeout(dur: Duration, f: F) -> Result where F: Future, { TimeoutFuture::new(f, dur).await } pin_project! { /// A future that times out after a duration of time. pub struct TimeoutFuture { #[pin] future: F, #[pin] delay: Timer, } } impl TimeoutFuture { #[allow(dead_code)] pub(super) fn new(future: F, dur: Duration) -> TimeoutFuture { TimeoutFuture { future, delay: timer_after(dur), } } } impl Future for TimeoutFuture { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); match this.future.poll(cx) { Poll::Ready(v) => Poll::Ready(Ok(v)), Poll::Pending => match this.delay.poll(cx) { Poll::Ready(_) => Poll::Ready(Err(TimeoutError { _private: () })), Poll::Pending => Poll::Pending, }, } } } /// An error returned when a future times out. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct TimeoutError { _private: (), } impl Error for TimeoutError {} impl fmt::Display for TimeoutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "future has timed out".fmt(f) } } async-rs-async-std-57f61ae/src/io/000077500000000000000000000000001476537407000170075ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/io/buf_read/000077500000000000000000000000001476537407000205565ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/io/buf_read/lines.rs000066400000000000000000000044131476537407000222400ustar00rootroot00000000000000use std::mem; use std::pin::Pin; use std::str; use pin_project_lite::pin_project; use super::read_until_internal; use crate::io::{self, BufRead}; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream of lines in a byte stream. /// /// This stream is created by the [`lines`] method on types that implement [`BufRead`]. /// /// This type is an async version of [`std::io::Lines`]. /// /// [`lines`]: trait.BufRead.html#method.lines /// [`BufRead`]: trait.BufRead.html /// [`std::io::Lines`]: https://doc.rust-lang.org/std/io/struct.Lines.html #[derive(Debug)] pub struct Lines { #[pin] pub(crate) reader: R, pub(crate) buf: String, pub(crate) bytes: Vec, pub(crate) read: usize, } } impl Stream for Lines { type Item = io::Result; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let n = futures_core::ready!(read_line_internal( this.reader, cx, this.buf, this.bytes, this.read ))?; if n == 0 && this.buf.is_empty() { return Poll::Ready(None); } if this.buf.ends_with('\n') { this.buf.pop(); if this.buf.ends_with('\r') { this.buf.pop(); } } Poll::Ready(Some(Ok(mem::replace(this.buf, String::new())))) } } pub fn read_line_internal( reader: Pin<&mut R>, cx: &mut Context<'_>, buf: &mut String, bytes: &mut Vec, read: &mut usize, ) -> Poll> { let ret = futures_core::ready!(read_until_internal(reader, cx, b'\n', bytes, read)); if str::from_utf8(&bytes).is_err() { Poll::Ready(ret.and_then(|_| { Err(io::Error::new( io::ErrorKind::InvalidData, "stream did not contain valid UTF-8", )) })) } else { debug_assert!(buf.is_empty()); debug_assert_eq!(*read, 0); // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. mem::swap(unsafe { buf.as_mut_vec() }, bytes); Poll::Ready(ret) } } async-rs-async-std-57f61ae/src/io/buf_read/mod.rs000066400000000000000000000165151476537407000217130ustar00rootroot00000000000000mod lines; mod read_line; mod read_until; mod split; pub use lines::Lines; pub use split::Split; use read_line::ReadLineFuture; use read_until::ReadUntilFuture; use std::mem; use std::pin::Pin; use crate::io; use crate::task::{Context, Poll}; pub use futures_io::AsyncBufRead as BufRead; #[doc = r#" Extension methods for [`BufRead`]. [`BufRead`]: ../trait.BufRead.html "#] pub trait BufReadExt: BufRead { #[doc = r#" Reads all bytes into `buf` until the delimiter `byte` or EOF is reached. This function will read bytes from the underlying stream until the delimiter or EOF is found. Once found, all bytes up to, and including, the delimiter (if found) will be appended to `buf`. If successful, this function will return the total number of bytes read. # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::io::BufReader; use async_std::prelude::*; let mut file = BufReader::new(File::open("a.txt").await?); let mut buf = Vec::with_capacity(1024); let n = file.read_until(b'\n', &mut buf).await?; # # Ok(()) }) } ``` Multiple successful calls to `read_until` append all bytes up to and including to `buf`: ``` # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::io::BufReader; use async_std::prelude::*; let from: &[u8] = b"append\nexample\n"; let mut reader = BufReader::new(from); let mut buf = vec![]; let mut size = reader.read_until(b'\n', &mut buf).await?; assert_eq!(size, 7); assert_eq!(buf, b"append\n"); size += reader.read_until(b'\n', &mut buf).await?; assert_eq!(size, from.len()); assert_eq!(buf, from); # # Ok(()) }) } ``` "#] fn read_until<'a>( &'a mut self, byte: u8, buf: &'a mut Vec, ) -> ReadUntilFuture<'a, Self> where Self: Unpin, { ReadUntilFuture { reader: self, byte, buf, read: 0, } } #[doc = r#" Reads all bytes and appends them into `buf` until a newline (the 0xA byte) is reached. This function will read bytes from the underlying stream until the newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes up to, and including, the delimiter (if found) will be appended to `buf`. If successful, this function will return the total number of bytes read. If this function returns `Ok(0)`, the stream has reached EOF. # Errors This function has the same error semantics as [`read_until`] and will also return an error if the read bytes are not valid UTF-8. If an I/O error is encountered then `buf` may contain some bytes already read in the event that all data read so far was valid UTF-8. [`read_until`]: #method.read_until # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::io::BufReader; use async_std::prelude::*; let mut file = BufReader::new(File::open("a.txt").await?); let mut buf = String::new(); file.read_line(&mut buf).await?; # # Ok(()) }) } ``` "#] fn read_line<'a>( &'a mut self, buf: &'a mut String, ) -> ReadLineFuture<'a, Self> where Self: Unpin, { ReadLineFuture { reader: self, bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) }, buf, read: 0, } } #[doc = r#" Returns a stream over the lines of this byte stream. The stream returned from this function will yield instances of [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. [`io::Result`]: type.Result.html [`String`]: https://doc.rust-lang.org/std/string/struct.String.html # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::io::BufReader; use async_std::prelude::*; let file = File::open("a.txt").await?; let mut lines = BufReader::new(file).lines(); let mut count = 0; while let Some(line) = lines.next().await { line?; count += 1; } # # Ok(()) }) } ``` "#] fn lines(self) -> Lines where Self: Unpin + Sized, { Lines { reader: self, buf: String::new(), bytes: Vec::new(), read: 0, } } #[doc = r#" Returns a stream over the contents of this reader split on the byte `byte`. The stream returned from this function will return instances of [`io::Result`]`<`[`Vec`]`>`. Each vector returned will *not* have the delimiter byte at the end. This function will yield errors whenever [`read_until`] would have also yielded an error. [`io::Result`]: type.Result.html [`Vec`]: ../vec/struct.Vec.html [`read_until`]: #method.read_until # Examples [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In this example, we use [`Cursor`] to iterate over all hyphen delimited segments in a byte slice [`Cursor`]: struct.Cursor.html ``` # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::io; let cursor = io::Cursor::new(b"lorem-ipsum-dolor"); let mut split_iter = cursor.split(b'-').map(|l| l.unwrap()); assert_eq!(split_iter.next().await, Some(b"lorem".to_vec())); assert_eq!(split_iter.next().await, Some(b"ipsum".to_vec())); assert_eq!(split_iter.next().await, Some(b"dolor".to_vec())); assert_eq!(split_iter.next().await, None); # # Ok(()) }) } ``` "#] fn split(self, byte: u8) -> Split where Self: Sized, { Split { reader: self, buf: Vec::new(), delim: byte, read: 0, } } } impl BufReadExt for T {} pub(crate) fn read_until_internal( mut reader: Pin<&mut R>, cx: &mut Context<'_>, byte: u8, buf: &mut Vec, read: &mut usize, ) -> Poll> { loop { let (done, used) = { let available = futures_core::ready!(reader.as_mut().poll_fill_buf(cx))?; if let Some(i) = memchr::memchr(byte, available) { buf.extend_from_slice(&available[..=i]); (true, i + 1) } else { buf.extend_from_slice(available); (false, available.len()) } }; reader.as_mut().consume(used); *read += used; if done || used == 0 { return Poll::Ready(Ok(mem::replace(read, 0))); } } } async-rs-async-std-57f61ae/src/io/buf_read/read_line.rs000066400000000000000000000027401476537407000230510ustar00rootroot00000000000000use std::mem; use std::pin::Pin; use std::str; use std::future::Future; use super::read_until_internal; use crate::io::{self, BufRead}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct ReadLineFuture<'a, T: Unpin + ?Sized> { pub(crate) reader: &'a mut T, pub(crate) buf: &'a mut String, pub(crate) bytes: Vec, pub(crate) read: usize, } impl Future for ReadLineFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { reader, buf, bytes, read, } = &mut *self; let reader = Pin::new(reader); let ret = futures_core::ready!(read_until_internal(reader, cx, b'\n', bytes, read)); if str::from_utf8(&bytes).is_err() { Poll::Ready(ret.and_then(|_| { Err(io::Error::new( io::ErrorKind::InvalidData, "stream did not contain valid UTF-8", )) })) } else { #[allow(clippy::debug_assert_with_mut_call)] { debug_assert!(buf.is_empty()); debug_assert_eq!(*read, 0); } // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. mem::swap(unsafe { buf.as_mut_vec() }, bytes); Poll::Ready(ret) } } } async-rs-async-std-57f61ae/src/io/buf_read/read_until.rs000066400000000000000000000013721476537407000232550ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use super::read_until_internal; use crate::io::{self, BufRead}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct ReadUntilFuture<'a, T: Unpin + ?Sized> { pub(crate) reader: &'a mut T, pub(crate) byte: u8, pub(crate) buf: &'a mut Vec, pub(crate) read: usize, } impl Future for ReadUntilFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { reader, byte, buf, read, } = &mut *self; read_until_internal(Pin::new(reader), cx, *byte, buf, read) } } async-rs-async-std-57f61ae/src/io/buf_read/split.rs000066400000000000000000000027171476537407000222660ustar00rootroot00000000000000use std::mem; use std::pin::Pin; use pin_project_lite::pin_project; use super::read_until_internal; use crate::io::{self, BufRead}; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream over the contents of an instance of [`BufRead`] split on a particular byte. /// /// This stream is created by the [`split`] method on types that implement [`BufRead`]. /// /// This type is an async version of [`std::io::Split`]. /// /// [`split`]: trait.BufRead.html#method.lines /// [`BufRead`]: trait.BufRead.html /// [`std::io::Split`]: https://doc.rust-lang.org/std/io/struct.Split.html #[derive(Debug)] pub struct Split { #[pin] pub(crate) reader: R, pub(crate) buf: Vec, pub(crate) read: usize, pub(crate) delim: u8, } } impl Stream for Split { type Item = io::Result>; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let n = futures_core::ready!(read_until_internal( this.reader, cx, *this.delim, this.buf, this.read ))?; if n == 0 && this.buf.is_empty() { return Poll::Ready(None); } if this.buf[this.buf.len() - 1] == *this.delim { this.buf.pop(); } Poll::Ready(Some(Ok(mem::replace(this.buf, vec![])))) } } async-rs-async-std-57f61ae/src/io/buf_reader.rs000066400000000000000000000261031476537407000214550ustar00rootroot00000000000000use std::io::{IoSliceMut, Read as _}; use std::pin::Pin; use std::{cmp, fmt}; use pin_project_lite::pin_project; use crate::io::{self, BufRead, Read, Seek, SeekFrom, DEFAULT_BUF_SIZE}; use crate::task::{Context, Poll}; pin_project! { /// Adds buffering to any reader. /// /// It can be excessively inefficient to work directly with a [`Read`] instance. A `BufReader` /// performs large, infrequent reads on the underlying [`Read`] and maintains an in-memory buffer /// of the incoming byte stream. /// /// `BufReader` can improve the speed of programs that make *small* and *repeated* read calls to /// the same file or network socket. It does not help when reading very large amounts at once, or /// reading just one or a few times. It also provides no advantage when reading from a source that /// is already in memory, like a `Vec`. /// /// When the `BufReader` is dropped, the contents of its buffer will be discarded. Creating /// multiple instances of a `BufReader` on the same stream can cause data loss. /// /// This type is an async version of [`std::io::BufReader`]. /// /// [`Read`]: trait.Read.html /// [`std::io::BufReader`]: https://doc.rust-lang.org/std/io/struct.BufReader.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::io::BufReader; /// use async_std::prelude::*; /// /// let mut file = BufReader::new(File::open("a.txt").await?); /// /// let mut line = String::new(); /// file.read_line(&mut line).await?; /// # /// # Ok(()) }) } /// ``` pub struct BufReader { #[pin] inner: R, buf: Box<[u8]>, pos: usize, cap: usize, } } impl BufReader { /// Creates a buffered reader with default buffer capacity. /// /// The default capacity is currently 8 KB, but may change in the future. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::io::BufReader; /// /// let f = BufReader::new(File::open("a.txt").await?); /// # /// # Ok(()) }) } /// ``` pub fn new(inner: R) -> BufReader { BufReader::with_capacity(DEFAULT_BUF_SIZE, inner) } /// Creates a new buffered reader with the specified capacity. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::io::BufReader; /// /// let f = BufReader::with_capacity(1024, File::open("a.txt").await?); /// # /// # Ok(()) }) } /// ``` pub fn with_capacity(capacity: usize, inner: R) -> BufReader { BufReader { inner, buf: vec![0; capacity].into_boxed_slice(), pos: 0, cap: 0, } } } impl BufReader { /// Gets a reference to the underlying reader. /// /// It is inadvisable to directly read from the underlying reader. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::io::BufReader; /// /// let f = BufReader::new(File::open("a.txt").await?); /// let inner = f.get_ref(); /// # /// # Ok(()) }) } /// ``` pub fn get_ref(&self) -> &R { &self.inner } /// Gets a mutable reference to the underlying reader. /// /// It is inadvisable to directly read from the underlying reader. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::io::BufReader; /// /// let mut file = BufReader::new(File::open("a.txt").await?); /// let inner = file.get_mut(); /// # /// # Ok(()) }) } /// ``` pub fn get_mut(&mut self) -> &mut R { &mut self.inner } /// Gets a pinned mutable reference to the underlying reader. /// /// It is inadvisable to directly read from the underlying reader. fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut R> { self.project().inner } /// Returns a reference to the internal buffer. /// /// This function will not attempt to fill the buffer if it is empty. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::io::BufReader; /// /// let f = BufReader::new(File::open("a.txt").await?); /// let buffer = f.buffer(); /// # /// # Ok(()) }) } /// ``` pub fn buffer(&self) -> &[u8] { &self.buf[self.pos..self.cap] } /// Unwraps the buffered reader, returning the underlying reader. /// /// Note that any leftover data in the internal buffer is lost. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs::File; /// use async_std::io::BufReader; /// /// let f = BufReader::new(File::open("a.txt").await?); /// let inner = f.into_inner(); /// # /// # Ok(()) }) } /// ``` pub fn into_inner(self) -> R { self.inner } /// Invalidates all data in the internal buffer. #[inline] fn discard_buffer(self: Pin<&mut Self>) { let this = self.project(); *this.pos = 0; *this.cap = 0; } } impl Read for BufReader { fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. if self.pos == self.cap && buf.len() >= self.buf.len() { let res = futures_core::ready!(self.as_mut().get_pin_mut().poll_read(cx, buf)); self.discard_buffer(); return Poll::Ready(res); } let mut rem = futures_core::ready!(self.as_mut().poll_fill_buf(cx))?; let nread = rem.read(buf)?; self.consume(nread); Poll::Ready(Ok(nread)) } fn poll_read_vectored( mut self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>], ) -> Poll> { let total_len = bufs.iter().map(|b| b.len()).sum::(); if self.pos == self.cap && total_len >= self.buf.len() { let res = futures_core::ready!(self.as_mut().get_pin_mut().poll_read_vectored(cx, bufs)); self.discard_buffer(); return Poll::Ready(res); } let mut rem = futures_core::ready!(self.as_mut().poll_fill_buf(cx))?; let nread = rem.read_vectored(bufs)?; self.consume(nread); Poll::Ready(Ok(nread)) } } impl BufRead for BufReader { fn poll_fill_buf<'a>( self: Pin<&'a mut Self>, cx: &mut Context<'_>, ) -> Poll> { let mut this = self.project(); // If we've reached the end of our internal buffer then we need to fetch // some more data from the underlying reader. // Branch using `>=` instead of the more correct `==` // to tell the compiler that the pos..cap slice is always valid. if *this.pos >= *this.cap { debug_assert!(*this.pos == *this.cap); *this.cap = futures_core::ready!(this.inner.as_mut().poll_read(cx, this.buf))?; *this.pos = 0; } Poll::Ready(Ok(&this.buf[*this.pos..*this.cap])) } fn consume(self: Pin<&mut Self>, amt: usize) { let this = self.project(); *this.pos = cmp::min(*this.pos + amt, *this.cap); } } impl fmt::Debug for BufReader { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("BufReader") .field("reader", &self.inner) .field( "buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()), ) .finish() } } impl Seek for BufReader { /// Seeks to an offset, in bytes, in the underlying reader. /// /// The position used for seeking with `SeekFrom::Current(_)` is the position the underlying /// reader would be at if the `BufReader` had no internal buffer. /// /// Seeking always discards the internal buffer, even if the seek position would otherwise fall /// within it. This guarantees that calling `.into_inner()` immediately after a seek yields the /// underlying reader at the same position. /// /// See [`Seek`] for more details. /// /// Note: In the edge case where you're seeking with `SeekFrom::Current(n)` where `n` minus the /// internal buffer length overflows an `i64`, two seeks will be performed instead of one. If /// the second seek returns `Err`, the underlying reader will be left at the same position it /// would have if you called `seek` with `SeekFrom::Current(0)`. /// /// [`Seek`]: trait.Seek.html fn poll_seek( mut self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll> { let result: u64; if let SeekFrom::Current(n) = pos { let remainder = (self.cap - self.pos) as i64; // it should be safe to assume that remainder fits within an i64 as the alternative // means we managed to allocate 8 exbibytes and that's absurd. // But it's not out of the realm of possibility for some weird underlying reader to // support seeking by i64::min_value() so we need to handle underflow when subtracting // remainder. if let Some(offset) = n.checked_sub(remainder) { result = futures_core::ready!( self.as_mut() .get_pin_mut() .poll_seek(cx, SeekFrom::Current(offset)) )?; } else { // seek backwards by our remainder, and then by the offset futures_core::ready!( self.as_mut() .get_pin_mut() .poll_seek(cx, SeekFrom::Current(-remainder)) )?; self.as_mut().discard_buffer(); result = futures_core::ready!( self.as_mut() .get_pin_mut() .poll_seek(cx, SeekFrom::Current(n)) )?; } } else { // Seeking with Start/End doesn't care about our buffer length. result = futures_core::ready!(self.as_mut().get_pin_mut().poll_seek(cx, pos))?; } self.discard_buffer(); Poll::Ready(Ok(result)) } } async-rs-async-std-57f61ae/src/io/buf_writer.rs000066400000000000000000000264231476537407000215340ustar00rootroot00000000000000use std::fmt; use std::pin::Pin; use pin_project_lite::pin_project; use crate::io::write::WriteExt; use crate::io::{self, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE}; use crate::task::{Context, Poll, ready}; pin_project! { /// Wraps a writer and buffers its output. /// /// It can be excessively inefficient to work directly with something that /// implements [`Write`]. For example, every call to /// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// /// `BufWriter` can improve the speed of programs that make *small* and /// *repeated* write calls to the same file or network socket. It does not /// help when writing very large amounts at once, or writing just one or a few /// times. It also provides no advantage when writing to a destination that is /// in memory, like a `Vec`. /// /// Unlike the `BufWriter` type in `std`, this type does not write out the /// contents of its buffer when it is dropped. Therefore, it is absolutely /// critical that users explicitly flush the buffer before dropping a /// `BufWriter`. /// /// This type is an async version of [`std::io::BufWriter`]. /// /// [`std::io::BufWriter`]: https://doc.rust-lang.org/std/io/struct.BufWriter.html /// /// # Examples /// /// Let's write the numbers one through ten to a [`TcpStream`]: /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::net::TcpStream; /// use async_std::prelude::*; /// /// let mut stream = TcpStream::connect("127.0.0.1:34254").await?; /// /// for i in 0..10 { /// let arr = [i+1]; /// stream.write(&arr).await?; /// } /// # /// # Ok(()) }) } /// ``` /// /// Because we're not buffering, we write each one in turn, incurring the /// overhead of a system call per byte written. We can fix this with a /// `BufWriter`: /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::io::BufWriter; /// use async_std::net::TcpStream; /// use async_std::prelude::*; /// /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").await?); /// /// for i in 0..10 { /// let arr = [i+1]; /// stream.write(&arr).await?; /// }; /// /// stream.flush().await?; /// # /// # Ok(()) }) } /// ``` /// /// By wrapping the stream with a `BufWriter`, these ten writes are all grouped /// together by the buffer, and will all be written out in one system call when /// `stream.flush()` completes. (As mentioned above, dropping a `BufWriter` /// does not flush its buffers, so a `flush` call is essential.) /// /// [`Write`]: trait.Write.html /// [`TcpStream::write`]: ../net/struct.TcpStream.html#method.write /// [`TcpStream`]: ../net/struct.TcpStream.html /// [`flush`]: trait.Write.html#tymethod.flush pub struct BufWriter { #[pin] inner: W, buf: Vec, written: usize, } } /// An error returned by `into_inner` which combines an error that /// happened while writing out the buffer, and the buffered writer object /// which may be used to recover from the condition. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::io::BufWriter; /// use async_std::net::TcpStream; /// /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34251").await?); /// /// // unwrap the TcpStream and flush the buffer /// let stream = match buf_writer.into_inner().await { /// Ok(s) => s, /// Err(e) => { /// // Here, e is an IntoInnerError /// panic!("An error occurred"); /// } /// }; /// # /// # Ok(()) }) } ///``` #[derive(Debug)] pub struct IntoInnerError(W, #[allow(dead_code)] crate::io::Error); impl BufWriter { /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, /// but may change in the future. /// /// # Examples /// /// ```no_run /// # #![allow(unused_mut)] /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::io::BufWriter; /// use async_std::net::TcpStream; /// /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").await?); /// # /// # Ok(()) }) } /// ``` pub fn new(inner: W) -> BufWriter { BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } /// Creates a new `BufWriter` with the specified buffer capacity. /// /// # Examples /// /// Creating a buffer with a buffer of a hundred bytes. /// /// ```no_run /// # #![allow(unused_mut)] /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::io::BufWriter; /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:34254").await?; /// let mut buffer = BufWriter::with_capacity(100, stream); /// # /// # Ok(()) }) } /// ``` pub fn with_capacity(capacity: usize, inner: W) -> BufWriter { BufWriter { inner, buf: Vec::with_capacity(capacity), written: 0, } } /// Gets a reference to the underlying writer. /// /// # Examples /// /// ```no_run /// # #![allow(unused_mut)] /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::io::BufWriter; /// use async_std::net::TcpStream; /// /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").await?); /// /// // We can use reference just like buffer /// let reference = buffer.get_ref(); /// # /// # Ok(()) }) } /// ``` pub fn get_ref(&self) -> &W { &self.inner } /// Gets a mutable reference to the underlying writer. /// /// It is inadvisable to directly write to the underlying writer. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::io::BufWriter; /// use async_std::net::TcpStream; /// /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").await?); /// /// // We can use reference just like buffer /// let reference = buffer.get_mut(); /// # /// # Ok(()) }) } /// ``` pub fn get_mut(&mut self) -> &mut W { &mut self.inner } /// Gets a pinned mutable reference to the underlying writer. /// /// It is inadvisable to directly write to the underlying writer. fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut W> { self.project().inner } /// Consumes BufWriter, returning the underlying writer /// /// This method will not write leftover data, it will be lost. /// For method that will attempt to write before returning the writer see [`poll_into_inner`] /// /// [`poll_into_inner`]: #method.poll_into_inner /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::io::BufWriter; /// use async_std::net::TcpStream; /// /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34251").await?); /// /// // unwrap the TcpStream and flush the buffer /// let stream = buf_writer.into_inner().await.unwrap(); /// # /// # Ok(()) }) } /// ``` pub async fn into_inner(mut self) -> Result>> where Self: Unpin, { match self.flush().await { Err(e) => Err(IntoInnerError(self, e)), Ok(()) => Ok(self.inner), } } /// Returns a reference to the internally buffered data. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// use async_std::io::BufWriter; /// use async_std::net::TcpStream; /// /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34251").await?); /// /// // See how many bytes are currently buffered /// let bytes_buffered = buf_writer.buffer().len(); /// # /// # Ok(()) }) } /// ``` pub fn buffer(&self) -> &[u8] { &self.buf } /// Poll buffer flushing until completion /// /// This is used in types that wrap around BufWrite, one such example: [`LineWriter`] /// /// [`LineWriter`]: struct.LineWriter.html fn poll_flush_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); let len = this.buf.len(); let mut ret = Ok(()); while *this.written < len { match this .inner .as_mut() .poll_write(cx, &this.buf[*this.written..]) { Poll::Ready(Ok(0)) => { ret = Err(io::Error::new( io::ErrorKind::WriteZero, "Failed to write buffered data", )); break; } Poll::Ready(Ok(n)) => *this.written += n, Poll::Ready(Err(ref e)) if e.kind() == io::ErrorKind::Interrupted => {} Poll::Ready(Err(e)) => { ret = Err(e); break; } Poll::Pending => return Poll::Pending, } } if *this.written > 0 { this.buf.drain(..*this.written); } *this.written = 0; Poll::Ready(ret) } } impl Write for BufWriter { fn poll_write( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { if self.buf.len() + buf.len() > self.buf.capacity() { ready!(self.as_mut().poll_flush_buf(cx))?; } if buf.len() >= self.buf.capacity() { self.get_pin_mut().poll_write(cx, buf) } else { Pin::new(&mut *self.project().buf).poll_write(cx, buf) } } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { ready!(self.as_mut().poll_flush_buf(cx))?; self.get_pin_mut().poll_flush(cx) } fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { ready!(self.as_mut().poll_flush_buf(cx))?; self.get_pin_mut().poll_close(cx) } } impl fmt::Debug for BufWriter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("BufWriter") .field("writer", &self.inner) .field("buf", &self.buf) .finish() } } impl Seek for BufWriter { /// Seek to the offset, in bytes, in the underlying writer. /// /// Seeking always writes out the internal buffer before seeking. fn poll_seek( mut self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll> { ready!(self.as_mut().poll_flush_buf(cx))?; self.get_pin_mut().poll_seek(cx, pos) } } async-rs-async-std-57f61ae/src/io/copy.rs000066400000000000000000000140131476537407000203260ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use pin_project_lite::pin_project; use crate::io::{self, BufRead, BufReader, Read, Write}; use crate::task::{Context, Poll}; use crate::utils::Context as _; // Note: There are two otherwise-identical implementations of this // function because unstable has removed the `?Sized` bound for the // reader and writer and accepts `R` and `W` instead of `&mut R` and // `&mut W`. If making a change to either of the implementations, // ensure that you copy it into the other. /// Copies the entire contents of a reader into a writer. /// /// This function will continuously read data from `reader` and then /// write it into `writer` in a streaming fashion until `reader` /// returns EOF. /// /// On success, the total number of bytes that were copied from /// `reader` to `writer` is returned. /// /// If you’re wanting to copy the contents of one file to another and you’re /// working with filesystem paths, see the [`fs::copy`] function. /// /// This function is an async version of [`std::io::copy`]. /// /// [`std::io::copy`]: https://doc.rust-lang.org/std/io/fn.copy.html /// [`fs::copy`]: ../fs/fn.copy.html /// /// # Errors /// /// This function will return an error immediately if any call to `read` or /// `write` returns an error. All instances of `ErrorKind::Interrupted` are /// handled by this function and the underlying operation is retried. /// /// # Examples /// /// ``` /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// /// let mut reader: &[u8] = b"hello"; /// let mut writer = io::stdout(); /// /// io::copy(&mut reader, &mut writer).await?; /// # /// # Ok(()) }) } /// ``` #[cfg(any(feature = "docs", not(feature = "unstable")))] pub async fn copy(reader: &mut R, writer: &mut W) -> io::Result where R: Read + Unpin + ?Sized, W: Write + Unpin + ?Sized, { pin_project! { struct CopyFuture { #[pin] reader: R, #[pin] writer: W, amt: u64, reader_eof: bool } } impl Future for CopyFuture where R: BufRead, W: Write + Unpin, { type Output = io::Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { if *this.reader_eof { futures_core::ready!(this.writer.as_mut().poll_flush(cx))?; return Poll::Ready(Ok(*this.amt)); } let buffer = futures_core::ready!(this.reader.as_mut().poll_fill_buf(cx))?; if buffer.is_empty() { *this.reader_eof = true; continue; } let i = futures_core::ready!(this.writer.as_mut().poll_write(cx, buffer))?; if i == 0 { return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); } *this.amt += i as u64; this.reader.as_mut().consume(i); } } } let future = CopyFuture { reader: BufReader::new(reader), writer, reader_eof: false, amt: 0, }; future.await.context(|| String::from("io::copy failed")) } /// Copies the entire contents of a reader into a writer. /// /// This function will continuously read data from `reader` and then /// write it into `writer` in a streaming fashion until `reader` /// returns EOF. /// /// On success, the total number of bytes that were copied from /// `reader` to `writer` is returned. /// /// If you’re wanting to copy the contents of one file to another and you’re /// working with filesystem paths, see the [`fs::copy`] function. /// /// This function is an async version of [`std::io::copy`]. /// /// [`std::io::copy`]: https://doc.rust-lang.org/std/io/fn.copy.html /// [`fs::copy`]: ../fs/fn.copy.html /// /// # Errors /// /// This function will return an error immediately if any call to `read` or /// `write` returns an error. All instances of `ErrorKind::Interrupted` are /// handled by this function and the underlying operation is retried. /// /// # Examples /// /// ``` /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// /// let mut reader: &[u8] = b"hello"; /// let mut writer = io::stdout(); /// /// io::copy(&mut reader, &mut writer).await?; /// # /// # Ok(()) }) } /// ``` #[cfg(all(feature = "unstable", not(feature = "docs")))] pub async fn copy(reader: R, writer: W) -> io::Result where R: Read + Unpin, W: Write + Unpin, { pin_project! { struct CopyFuture { #[pin] reader: R, #[pin] writer: W, amt: u64, reader_eof: bool } } impl Future for CopyFuture where R: BufRead, W: Write + Unpin, { type Output = io::Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { if *this.reader_eof { futures_core::ready!(this.writer.as_mut().poll_flush(cx))?; return Poll::Ready(Ok(*this.amt)); } let buffer = futures_core::ready!(this.reader.as_mut().poll_fill_buf(cx))?; if buffer.is_empty() { *this.reader_eof = true; continue; } let i = futures_core::ready!(this.writer.as_mut().poll_write(cx, buffer))?; if i == 0 { return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); } *this.amt += i as u64; this.reader.as_mut().consume(i); } } } let future = CopyFuture { reader: BufReader::new(reader), writer, reader_eof: false, amt: 0, }; future.await.context(|| String::from("io::copy failed")) } async-rs-async-std-57f61ae/src/io/cursor.rs000066400000000000000000000161541476537407000207010ustar00rootroot00000000000000use std::pin::Pin; use crate::io::{self, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::task::{Context, Poll}; /// A `Cursor` wraps an in-memory buffer and provides it with a /// [`Seek`] implementation. /// /// `Cursor`s are used with in-memory buffers, anything implementing /// `AsRef<[u8]>`, to allow them to implement [`Read`] and/or [`Write`], /// allowing these buffers to be used anywhere you might use a reader or writer /// that does actual I/O. /// /// The standard library implements some I/O traits on various types which /// are commonly used as a buffer, like `Cursor<`[`Vec`]`>` and /// `Cursor<`[`&[u8]`][bytes]`>`. /// /// [`Seek`]: trait.Seek.html /// [`Read`]: trait.Read.html /// [`Write`]: trait.Write.html /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html /// [bytes]: https://doc.rust-lang.org/std/primitive.slice.html /// [`File`]: struct.File.html #[derive(Clone, Debug, Default)] pub struct Cursor { inner: std::io::Cursor, } impl Cursor { /// Creates a new cursor wrapping the provided underlying in-memory buffer. /// /// Cursor initial position is `0` even if underlying buffer (e.g., `Vec`) /// is not empty. So writing to cursor starts with overwriting `Vec` /// content, not with appending to it. /// /// # Examples /// /// ``` /// use async_std::io::Cursor; /// /// let buff = Cursor::new(Vec::new()); /// # fn force_inference(_: &Cursor>) {} /// # force_inference(&buff); /// ``` pub fn new(inner: T) -> Cursor { Cursor { inner: std::io::Cursor::new(inner), } } /// Consumes this cursor, returning the underlying value. /// /// # Examples /// /// ``` /// use async_std::io::Cursor; /// /// let buff = Cursor::new(Vec::new()); /// # fn force_inference(_: &Cursor>) {} /// # force_inference(&buff); /// /// let vec = buff.into_inner(); /// ``` pub fn into_inner(self) -> T { self.inner.into_inner() } /// Gets a reference to the underlying value in this cursor. /// /// # Examples /// /// ``` /// use async_std::io::Cursor; /// /// let buff = Cursor::new(Vec::new()); /// # fn force_inference(_: &Cursor>) {} /// # force_inference(&buff); /// /// let reference = buff.get_ref(); /// ``` pub fn get_ref(&self) -> &T { self.inner.get_ref() } /// Gets a mutable reference to the underlying value in this cursor. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying value as it may corrupt this cursor's position. /// /// # Examples /// /// ``` /// use async_std::io::Cursor; /// /// let mut buff = Cursor::new(Vec::new()); /// # fn force_inference(_: &Cursor>) {} /// # force_inference(&buff); /// /// let reference = buff.get_mut(); /// ``` pub fn get_mut(&mut self) -> &mut T { self.inner.get_mut() } /// Returns the current position of this cursor. /// /// # Examples /// /// ``` /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io::Cursor; /// use async_std::io::prelude::*; /// use async_std::io::SeekFrom; /// /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); /// /// assert_eq!(buff.position(), 0); /// /// buff.seek(SeekFrom::Current(2)).await?; /// assert_eq!(buff.position(), 2); /// /// buff.seek(SeekFrom::Current(-1)).await?; /// assert_eq!(buff.position(), 1); /// # /// # Ok(()) }) } /// ``` pub fn position(&self) -> u64 { self.inner.position() } /// Sets the position of this cursor. /// /// # Examples /// /// ``` /// use async_std::io::Cursor; /// /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); /// /// assert_eq!(buff.position(), 0); /// /// buff.set_position(2); /// assert_eq!(buff.position(), 2); /// /// buff.set_position(4); /// assert_eq!(buff.position(), 4); /// ``` pub fn set_position(&mut self, pos: u64) { self.inner.set_position(pos) } } impl Seek for Cursor where T: AsRef<[u8]> + Unpin, { fn poll_seek( mut self: Pin<&mut Self>, _: &mut Context<'_>, pos: SeekFrom, ) -> Poll> { Poll::Ready(std::io::Seek::seek(&mut self.inner, pos)) } } impl Read for Cursor where T: AsRef<[u8]> + Unpin, { fn poll_read( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { Poll::Ready(std::io::Read::read(&mut self.inner, buf)) } fn poll_read_vectored( mut self: Pin<&mut Self>, _: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>], ) -> Poll> { Poll::Ready(std::io::Read::read_vectored(&mut self.inner, bufs)) } } impl BufRead for Cursor where T: AsRef<[u8]> + Unpin, { fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(std::io::BufRead::fill_buf(&mut self.get_mut().inner)) } fn consume(mut self: Pin<&mut Self>, amt: usize) { std::io::BufRead::consume(&mut self.inner, amt) } } impl Write for Cursor<&mut [u8]> { fn poll_write( mut self: Pin<&mut Self>, _: &mut Context<'_>, buf: &[u8], ) -> Poll> { Poll::Ready(std::io::Write::write(&mut self.inner, buf)) } fn poll_write_vectored( mut self: Pin<&mut Self>, _: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll> { Poll::Ready(std::io::Write::write_vectored(&mut self.inner, bufs)) } fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(std::io::Write::flush(&mut self.inner)) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.poll_flush(cx) } } impl Write for Cursor<&mut Vec> { fn poll_write( mut self: Pin<&mut Self>, _: &mut Context<'_>, buf: &[u8], ) -> Poll> { Poll::Ready(std::io::Write::write(&mut self.inner, buf)) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.poll_flush(cx) } fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(std::io::Write::flush(&mut self.inner)) } } impl Write for Cursor> { fn poll_write( mut self: Pin<&mut Self>, _: &mut Context<'_>, buf: &[u8], ) -> Poll> { Poll::Ready(std::io::Write::write(&mut self.inner, buf)) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.poll_flush(cx) } fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(std::io::Write::flush(&mut self.inner)) } } async-rs-async-std-57f61ae/src/io/empty.rs000066400000000000000000000025151476537407000205160ustar00rootroot00000000000000use std::fmt; use std::pin::Pin; use crate::io::{self, BufRead, Read}; use crate::task::{Context, Poll}; /// Creates a reader that contains no data. /// /// # Examples /// /// ```rust /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// use async_std::prelude::*; /// /// let mut buf = Vec::new(); /// let mut reader = io::empty(); /// reader.read_to_end(&mut buf).await?; /// /// assert!(buf.is_empty()); /// # /// # Ok(()) }) } /// ``` pub fn empty() -> Empty { Empty { _private: () } } /// A reader that contains no data. /// /// This reader is created by the [`empty`] function. See its /// documentation for more. /// /// [`empty`]: fn.empty.html pub struct Empty { _private: (), } impl fmt::Debug for Empty { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Empty { .. }") } } impl Read for Empty { #[inline] fn poll_read( self: Pin<&mut Self>, _: &mut Context<'_>, _: &mut [u8], ) -> Poll> { Poll::Ready(Ok(0)) } } impl BufRead for Empty { #[inline] fn poll_fill_buf<'a>( self: Pin<&'a mut Self>, _: &mut Context<'_>, ) -> Poll> { Poll::Ready(Ok(&[])) } #[inline] fn consume(self: Pin<&mut Self>, _: usize) {} } async-rs-async-std-57f61ae/src/io/mod.rs000066400000000000000000000235611476537407000201430ustar00rootroot00000000000000//! Traits, helpers, and type definitions for core I/O functionality. //! //! The `async_std::io` module contains a number of common things you'll need //! when doing input and output. The most core part of this module is //! the [`Read`] and [`Write`] traits, which provide the //! most general interface for reading and writing input and output. //! //! This module is an async version of [`std::io`]. //! //! [`std::io`]: https://doc.rust-lang.org/std/io/index.html //! //! # Read and Write //! //! Because they are traits, [`Read`] and [`Write`] are implemented by a number //! of other types, and you can implement them for your types too. As such, //! you'll see a few different types of I/O throughout the documentation in //! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec`]s. For //! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on //! [`File`]s: //! //! ```no_run //! use async_std::fs::File; //! use async_std::prelude::*; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! let mut f = File::open("foo.txt").await?; //! let mut buffer = [0; 10]; //! //! // read up to 10 bytes //! let n = f.read(&mut buffer).await?; //! //! println!("The bytes: {:?}", &buffer[..n]); //! # //! # Ok(()) }) } //! ``` //! //! [`Read`] and [`Write`] are so important, implementors of the two traits have a //! nickname: readers and writers. So you'll sometimes see 'a reader' instead //! of 'a type that implements the [`Read`] trait'. Much easier! //! //! ## Seek and BufRead //! //! Beyond that, there are two important traits that are provided: [`Seek`] //! and [`BufRead`]. Both of these build on top of a reader to control //! how the reading happens. [`Seek`] lets you control where the next byte is //! coming from: //! //! ```no_run //! use async_std::fs::File; //! use async_std::io::SeekFrom; //! use async_std::prelude::*; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! let mut f = File::open("foo.txt").await?; //! let mut buffer = [0; 10]; //! //! // skip to the last 10 bytes of the file //! f.seek(SeekFrom::End(-10)).await?; //! //! // read up to 10 bytes //! let n = f.read(&mut buffer).await?; //! //! println!("The bytes: {:?}", &buffer[..n]); //! # //! # Ok(()) }) } //! ``` //! //! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but //! to show it off, we'll need to talk about buffers in general. Keep reading! //! //! ## BufReader and BufWriter //! //! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be //! making near-constant calls to the operating system. To help with this, //! `std::io` comes with two structs, [`BufReader`] and [`BufWriter`], which wrap //! readers and writers. The wrapper uses a buffer, reducing the number of //! calls and providing nicer methods for accessing exactly what you want. //! //! For example, [`BufReader`] works with the [`BufRead`] trait to add extra //! methods to any reader: //! //! ```no_run //! use async_std::fs::File; //! use async_std::io::BufReader; //! use async_std::prelude::*; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! let f = File::open("foo.txt").await?; //! let mut reader = BufReader::new(f); //! let mut buffer = String::new(); //! //! // read a line into buffer //! reader.read_line(&mut buffer).await?; //! //! println!("{}", buffer); //! # //! # Ok(()) }) } //! ``` //! //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call //! to [`write`][`Write::write`]: //! //! ```no_run //! use async_std::fs::File; //! use async_std::io::prelude::*; //! use async_std::io::BufWriter; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! let f = File::create("foo.txt").await?; //! { //! let mut writer = BufWriter::new(f); //! //! // write a byte to the buffer //! writer.write(&[42]).await?; //! } // the buffer is flushed once writer goes out of scope //! // //! # //! # Ok(()) }) } //! ``` //! //! ## Standard input and output //! //! A very common source of input is standard input: //! //! ```no_run //! use async_std::io; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! let mut input = String::new(); //! //! io::stdin().read_line(&mut input).await?; //! //! println!("You typed: {}", input.trim()); //! # //! # Ok(()) }) } //! ``` //! //! Note that you cannot use the [`?` operator] in functions that do not return //! a [`Result`][`Result`]. Instead, you can call [`.unwrap()`] //! or `match` on the return value to catch any possible errors: //! //! ```no_run //! use async_std::io; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! let mut input = String::new(); //! //! io::stdin().read_line(&mut input).await.unwrap(); //! # //! # Ok(()) }) } //! ``` //! //! And a very common source of output is standard output: //! //! ```no_run //! use async_std::io; //! use async_std::io::prelude::*; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! io::stdout().write(&[42]).await?; //! # //! # Ok(()) }) } //! ``` //! //! Of course, using [`io::stdout`] directly is less common than something like //! [`println!`]. //! //! ## Iterator types //! //! A large number of the structures provided by `std::io` are for various //! ways of iterating over I/O. For example, [`Lines`] is used to split over //! lines: //! //! ```no_run //! use async_std::fs::File; //! use async_std::io::BufReader; //! use async_std::prelude::*; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! let f = File::open("foo.txt").await?; //! let reader = BufReader::new(f); //! //! let mut lines = reader.lines(); //! while let Some(line) = lines.next().await { //! println!("{}", line?); //! } //! # //! # Ok(()) }) } //! ``` //! //! ## Functions //! //! There are a number of [functions][functions-list] that offer access to various //! features. For example, we can use three of these functions to copy everything //! from standard input to standard output: //! //! ```no_run //! use async_std::io; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! io::copy(&mut io::stdin(), &mut io::stdout()).await?; //! # //! # Ok(()) }) } //! ``` //! //! [functions-list]: #functions-1 //! //! ## io::Result //! //! Last, but certainly not least, is [`io::Result`]. This type is used //! as the return type of many `std::io` functions that can cause an error, and //! can be returned from your own functions as well. Many of the examples in this //! module use the [`?` operator]: //! //! ``` //! #![allow(dead_code)] //! use async_std::io; //! //! async fn read_input() -> io::Result<()> { //! let mut input = String::new(); //! //! io::stdin().read_line(&mut input).await?; //! //! println!("You typed: {}", input.trim()); //! //! Ok(()) //! } //! ``` //! //! The return type of `read_input`, [`io::Result<()>`][`io::Result`], is a very //! common type for functions which don't have a 'real' return value, but do want to //! return errors if they happen. In this case, the only purpose of this function is //! to read the line and print it, so we use `()`. //! //! ## Platform-specific behavior //! //! Many I/O functions throughout the standard library are documented to indicate //! what various library or syscalls they are delegated to. This is done to help //! applications both understand what's happening under the hood as well as investigate //! any possibly unclear semantics. Note, however, that this is informative, not a binding //! contract. The implementation of many of these functions are subject to change over //! time and may call fewer or more syscalls/library functions. //! //! [`Read`]: trait.Read.html //! [`Write`]: trait.Write.html //! [`Seek`]: trait.Seek.html //! [`BufRead`]: trait.BufRead.html //! [`File`]: ../fs/struct.File.html //! [`TcpStream`]: ../net/struct.TcpStream.html //! [`Vec`]: ../vec/struct.Vec.html //! [`BufReader`]: struct.BufReader.html //! [`BufWriter`]: struct.BufWriter.html //! [`Write::write`]: trait.Write.html#tymethod.write //! [`io::stdout`]: fn.stdout.html //! [`println!`]: ../macro.println.html //! [`Lines`]: struct.Lines.html //! [`io::Result`]: type.Result.html //! [`?` operator]: https://doc.rust-lang.org/stable/book/appendix-02-operators.html //! [`Read::read`]: trait.Read.html#tymethod.read //! [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html //! [`.unwrap()`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap const DEFAULT_BUF_SIZE: usize = 8 * 1024; cfg_std! { #[doc(inline)] pub use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Result, SeekFrom}; pub use buf_read::*; pub use buf_reader::BufReader; pub use buf_writer::{BufWriter, IntoInnerError}; pub use copy::copy; pub use cursor::Cursor; pub use empty::{empty, Empty}; pub use read::*; pub use repeat::{repeat, Repeat}; pub use seek::*; pub use sink::{sink, Sink}; pub use write::*; pub mod prelude; pub(crate) mod buf_read; pub(crate) mod read; pub(crate) mod seek; pub(crate) mod write; pub(crate) mod utils; mod buf_reader; mod buf_writer; mod copy; mod cursor; mod empty; mod repeat; mod sink; } cfg_default! { // For use in the print macros. #[doc(hidden)] #[cfg(not(target_os = "unknown"))] pub use stdio::{_eprint, _print}; #[cfg(not(target_os = "unknown"))] pub use stderr::{stderr, Stderr}; #[cfg(not(target_os = "unknown"))] pub use stdin::{stdin, Stdin}; #[cfg(not(target_os = "unknown"))] pub use stdout::{stdout, Stdout}; pub use timeout::timeout; mod timeout; #[cfg(not(target_os = "unknown"))] mod stderr; #[cfg(not(target_os = "unknown"))] mod stdin; #[cfg(not(target_os = "unknown"))] mod stdio; #[cfg(not(target_os = "unknown"))] mod stdout; } async-rs-async-std-57f61ae/src/io/prelude.rs000066400000000000000000000012031476537407000210110ustar00rootroot00000000000000//! The async I/O prelude. //! //! The purpose of this module is to alleviate imports of many common I/O traits //! by adding a glob import to the top of I/O heavy modules: //! //! ``` //! # #![allow(unused_imports)] //! use async_std::io::prelude::*; //! ``` #[doc(no_inline)] pub use crate::io::BufRead; #[doc(no_inline)] pub use crate::io::Read; #[doc(no_inline)] pub use crate::io::Seek; #[doc(no_inline)] pub use crate::io::Write; #[doc(inline)] pub use crate::io::buf_read::BufReadExt; #[doc(inline)] pub use crate::io::read::ReadExt; #[doc(inline)] pub use crate::io::seek::SeekExt; #[doc(inline)] pub use crate::io::write::WriteExt; async-rs-async-std-57f61ae/src/io/read/000077500000000000000000000000001476537407000177225ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/io/read/bytes.rs000066400000000000000000000032561476537407000214240ustar00rootroot00000000000000use std::pin::Pin; use crate::io::{self, Read}; use crate::stream::stream::Stream; use crate::task::{Context, Poll}; /// A stream over `u8` values of a reader. /// /// This struct is generally created by calling [`bytes`] on a reader. /// Please see the documentation of [`bytes`] for more details. /// /// [`bytes`]: trait.Read.html#method.bytes #[derive(Debug)] pub struct Bytes { pub(crate) inner: T, } impl Stream for Bytes { type Item = io::Result; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut byte = 0; let rd = Pin::new(&mut self.inner); match futures_core::ready!(rd.poll_read(cx, std::slice::from_mut(&mut byte))) { Ok(0) => Poll::Ready(None), Ok(..) => Poll::Ready(Some(Ok(byte))), Err(ref e) if e.kind() == io::ErrorKind::Interrupted => Poll::Pending, Err(e) => Poll::Ready(Some(Err(e))), } } } #[cfg(all(test, feature = "default", not(target_arch = "wasm32")))] mod tests { use crate::io; use crate::prelude::*; use crate::task; #[test] fn test_bytes_basics() -> std::io::Result<()> { task::block_on(async move { let raw: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8]; let source: io::Cursor> = io::Cursor::new(raw.clone()); let mut s = source.bytes(); // TODO(@dignifiedquire): Use collect, once it is stable. let mut result = Vec::new(); while let Some(byte) = s.next().await { result.push(byte?); } assert_eq!(result, raw); Ok(()) }) } } async-rs-async-std-57f61ae/src/io/read/chain.rs000066400000000000000000000127161476537407000213610ustar00rootroot00000000000000use std::fmt; use std::pin::Pin; use pin_project_lite::pin_project; use crate::io::{self, BufRead, IoSliceMut, Read}; use crate::task::{Context, Poll}; pin_project! { /// Adaptor to chain together two readers. /// /// This struct is generally created by calling [`chain`] on a reader. /// Please see the documentation of [`chain`] for more details. /// /// [`chain`]: trait.Read.html#method.chain pub struct Chain { #[pin] pub(crate) first: T, #[pin] pub(crate) second: U, pub(crate) done_first: bool, } } impl Chain { /// Consumes the `Chain`, returning the wrapped readers. /// /// # Examples /// /// ```no_run /// # fn main() -> async_std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::fs::File; /// /// let foo_file = File::open("foo.txt").await?; /// let bar_file = File::open("bar.txt").await?; /// /// let chain = foo_file.chain(bar_file); /// let (foo_file, bar_file) = chain.into_inner(); /// # /// # Ok(()) }) } /// ``` pub fn into_inner(self) -> (T, U) { (self.first, self.second) } /// Gets references to the underlying readers in this `Chain`. /// /// # Examples /// /// ```no_run /// # fn main() -> async_std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::fs::File; /// /// let foo_file = File::open("foo.txt").await?; /// let bar_file = File::open("bar.txt").await?; /// /// let chain = foo_file.chain(bar_file); /// let (foo_file, bar_file) = chain.get_ref(); /// # /// # Ok(()) }) } /// ``` pub fn get_ref(&self) -> (&T, &U) { (&self.first, &self.second) } /// Gets mutable references to the underlying readers in this `Chain`. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying readers as doing so may corrupt the internal state of this /// `Chain`. /// /// # Examples /// /// ```no_run /// # fn main() -> async_std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::fs::File; /// /// let foo_file = File::open("foo.txt").await?; /// let bar_file = File::open("bar.txt").await?; /// /// let mut chain = foo_file.chain(bar_file); /// let (foo_file, bar_file) = chain.get_mut(); /// # /// # Ok(()) }) } /// ``` pub fn get_mut(&mut self) -> (&mut T, &mut U) { (&mut self.first, &mut self.second) } } impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Chain") .field("t", &self.first) .field("u", &self.second) .finish() } } impl Read for Chain { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { let this = self.project(); if !*this.done_first { match futures_core::ready!(this.first.poll_read(cx, buf)) { Ok(0) if !buf.is_empty() => *this.done_first = true, Ok(n) => return Poll::Ready(Ok(n)), Err(err) => return Poll::Ready(Err(err)), } } this.second.poll_read(cx, buf) } fn poll_read_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>], ) -> Poll> { let this = self.project(); if !*this.done_first { match futures_core::ready!(this.first.poll_read_vectored(cx, bufs)) { Ok(0) if !bufs.is_empty() => *this.done_first = true, Ok(n) => return Poll::Ready(Ok(n)), Err(err) => return Poll::Ready(Err(err)), } } this.second.poll_read_vectored(cx, bufs) } } impl BufRead for Chain { fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); if !*this.done_first { match futures_core::ready!(this.first.poll_fill_buf(cx)) { Ok(buf) if buf.is_empty() => { *this.done_first = true; } Ok(buf) => return Poll::Ready(Ok(buf)), Err(err) => return Poll::Ready(Err(err)), } } this.second.poll_fill_buf(cx) } fn consume(self: Pin<&mut Self>, amt: usize) { let this = self.project(); if !*this.done_first { this.first.consume(amt) } else { this.second.consume(amt) } } } #[cfg(all(test, feature = "default", not(target_arch = "wasm32")))] mod tests { use crate::io; use crate::prelude::*; use crate::task; #[test] fn test_chain_basics() -> std::io::Result<()> { let source1: io::Cursor> = io::Cursor::new(vec![0, 1, 2]); let source2: io::Cursor> = io::Cursor::new(vec![3, 4, 5]); task::block_on(async move { let mut buffer = Vec::new(); let mut source = source1.chain(source2); assert_eq!(6, source.read_to_end(&mut buffer).await?); assert_eq!(buffer, vec![0, 1, 2, 3, 4, 5]); Ok(()) }) } } async-rs-async-std-57f61ae/src/io/read/mod.rs000066400000000000000000000267071476537407000210630ustar00rootroot00000000000000mod bytes; mod chain; mod read; mod read_exact; mod read_to_end; mod read_to_string; mod read_vectored; mod take; use read::ReadFuture; use read_exact::ReadExactFuture; use read_to_end::{read_to_end_internal, ReadToEndFuture}; use read_to_string::ReadToStringFuture; use read_vectored::ReadVectoredFuture; use std::mem; use crate::io::IoSliceMut; pub use bytes::Bytes; pub use chain::Chain; pub use take::Take; pub use futures_io::AsyncRead as Read; #[doc = r#" Extension methods for [`Read`]. [`Read`]: ../trait.Read.html "#] pub trait ReadExt: Read { #[doc = r#" Reads some bytes from the byte stream. Returns the number of bytes read from the start of the buffer. If the return value is `Ok(n)`, then it must be guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates that the buffer has been filled in with `n` bytes of data. If `n` is `0`, then it can indicate one of two scenarios: 1. This reader has reached its "end of file" and will likely no longer be able to produce bytes. Note that this does not mean that the reader will always no longer be able to produce bytes. 2. The buffer specified was 0 bytes in length. # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::prelude::*; let mut file = File::open("a.txt").await?; let mut buf = vec![0; 1024]; let n = file.read(&mut buf).await?; # # Ok(()) }) } ``` "#] fn read<'a>( &'a mut self, buf: &'a mut [u8], ) -> ReadFuture<'a, Self> where Self: Unpin { ReadFuture { reader: self, buf } } #[doc = r#" Like [`read`], except that it reads into a slice of buffers. Data is copied to fill each buffer in order, with the final buffer written to possibly being only partially filled. This method must behave as a single call to [`read`] with the buffers concatenated would. The default implementation calls [`read`] with either the first nonempty buffer provided, or an empty one if none exists. [`read`]: #tymethod.read "#] fn read_vectored<'a>( &'a mut self, bufs: &'a mut [IoSliceMut<'a>], ) -> ReadVectoredFuture<'a, Self> where Self: Unpin, { ReadVectoredFuture { reader: self, bufs } } #[doc = r#" Reads all bytes from the byte stream. All bytes read from this stream will be appended to the specified buffer `buf`. This function will continuously call [`read`] to append more data to `buf` until [`read`] returns either `Ok(0)` or an error. If successful, this function will return the total number of bytes read. [`read`]: #tymethod.read # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::prelude::*; let mut file = File::open("a.txt").await?; let mut buf = Vec::new(); file.read_to_end(&mut buf).await?; # # Ok(()) }) } ``` "#] fn read_to_end<'a>( &'a mut self, buf: &'a mut Vec, ) -> ReadToEndFuture<'a, Self> where Self: Unpin, { let start_len = buf.len(); ReadToEndFuture { reader: self, buf, start_len, } } #[doc = r#" Reads all bytes from the byte stream and appends them into a string. If successful, this function will return the number of bytes read. If the data in this stream is not valid UTF-8 then an error will be returned and `buf` will be left unmodified. # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::prelude::*; let mut file = File::open("a.txt").await?; let mut buf = String::new(); file.read_to_string(&mut buf).await?; # # Ok(()) }) } ``` "#] fn read_to_string<'a>( &'a mut self, buf: &'a mut String, ) -> ReadToStringFuture<'a, Self> where Self: Unpin, { let start_len = buf.len(); ReadToStringFuture { reader: self, bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) }, buf, start_len, } } #[doc = r#" Reads the exact number of bytes required to fill `buf`. This function reads as many bytes as necessary to completely fill the specified buffer `buf`. No guarantees are provided about the contents of `buf` when this function is called, implementations cannot rely on any property of the contents of `buf` being true. It is recommended that implementations only write data to `buf` instead of reading its contents. If this function encounters an "end of file" before completely filling the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. The contents of `buf` are unspecified in this case. If any other read error is encountered then this function immediately returns. The contents of `buf` are unspecified in this case. If this function returns an error, it is unspecified how many bytes it has read, but it will never read more than would be necessary to completely fill the buffer. [`ErrorKind::UnexpectedEof`]: enum.ErrorKind.html#variant.UnexpectedEof # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::prelude::*; let mut file = File::open("a.txt").await?; let mut buf = vec![0; 10]; file.read_exact(&mut buf).await?; # # Ok(()) }) } ``` "#] fn read_exact<'a>( &'a mut self, buf: &'a mut [u8], ) -> ReadExactFuture<'a, Self> where Self: Unpin, { ReadExactFuture { reader: self, buf } } #[doc = r#" Creates an adaptor which will read at most `limit` bytes from it. This function returns a new instance of `Read` which will read at most `limit` bytes, after which it will always return EOF ([`Ok(0)`]). Any read errors will not count towards the number of bytes read and future calls to [`read`] may succeed. # Examples [`File`]s implement `Read`: [`File`]: ../fs/struct.File.html [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok [`read`]: tymethod.read ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::io::prelude::*; use async_std::fs::File; let f = File::open("foo.txt").await?; let mut buffer = [0; 5]; // read at most five bytes let mut handle = f.take(5); handle.read(&mut buffer).await?; # # Ok(()) }) } ``` "#] fn take(self, limit: u64) -> Take where Self: Sized, { Take { inner: self, limit } } #[doc = r#" Creates a "by reference" adaptor for this instance of `Read`. The returned adaptor also implements `Read` and will simply borrow this current reader. # Examples [`File`][file]s implement `Read`: [file]: ../fs/struct.File.html ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::fs::File; let mut f = File::open("foo.txt").await?; let mut buffer = Vec::new(); let mut other_buffer = Vec::new(); { let reference = f.by_ref(); // read at most 5 bytes reference.take(5).read_to_end(&mut buffer).await?; } // drop our &mut reference so we can use f again // original file still usable, read the rest f.read_to_end(&mut other_buffer).await?; # # Ok(()) }) } ``` "#] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } #[doc = r#" Transforms this `Read` instance to a `Stream` over its bytes. The returned type implements `Stream` where the `Item` is `Result`. The yielded item is `Ok` if a byte was successfully read and `Err` otherwise. EOF is mapped to returning `None` from this iterator. # Examples [`File`][file]s implement `Read`: [file]: ../fs/struct.File.html ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::fs::File; let f = File::open("foo.txt").await?; let mut s = f.bytes(); while let Some(byte) = s.next().await { println!("{}", byte.unwrap()); } # # Ok(()) }) } ``` "#] fn bytes(self) -> Bytes where Self: Sized { Bytes { inner: self } } #[doc = r#" Creates an adaptor which will chain this stream with another. The returned `Read` instance will first read all bytes from this object until EOF is encountered. Afterwards the output is equivalent to the output of `next`. # Examples [`File`][file]s implement `Read`: [file]: ../fs/struct.File.html ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::fs::File; let f1 = File::open("foo.txt").await?; let f2 = File::open("bar.txt").await?; let mut handle = f1.chain(f2); let mut buffer = String::new(); // read the value into a String. We could use any Read method here, // this is just one example. handle.read_to_string(&mut buffer).await?; # # Ok(()) }) } ``` "#] fn chain(self, next: R) -> Chain where Self: Sized { Chain { first: self, second: next, done_first: false } } } impl ReadExt for T {} /// Initializes a buffer if necessary. /// /// Currently, a buffer is always initialized because `read_initializer` /// feature is not stable. #[inline] unsafe fn initialize(_reader: &R, buf: &mut [u8]) { std::ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) } #[cfg(all(test, not(target_os = "unknown")))] mod tests { use crate::io; use crate::prelude::*; #[test] fn test_read_by_ref() { crate::task::block_on(async { let mut f = io::Cursor::new(vec![0u8, 1, 2, 3, 4, 5, 6, 7, 8]); let mut buffer = Vec::new(); let mut other_buffer = Vec::new(); { let reference = f.by_ref(); // read at most 5 bytes assert_eq!(reference.take(5).read_to_end(&mut buffer).await.unwrap(), 5); assert_eq!(&buffer, &[0, 1, 2, 3, 4]) } // drop our &mut reference so we can use f again // original file still usable, read the rest assert_eq!(f.read_to_end(&mut other_buffer).await.unwrap(), 4); assert_eq!(&other_buffer, &[5, 6, 7, 8]); }); } } async-rs-async-std-57f61ae/src/io/read/read.rs000066400000000000000000000010651476537407000212050ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::io::{self, Read}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct ReadFuture<'a, T: Unpin + ?Sized> { pub(crate) reader: &'a mut T, pub(crate) buf: &'a mut [u8], } impl Future for ReadFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { reader, buf } = &mut *self; Pin::new(reader).poll_read(cx, buf) } } async-rs-async-std-57f61ae/src/io/read/read_exact.rs000066400000000000000000000016221476537407000223700ustar00rootroot00000000000000use std::mem; use std::pin::Pin; use std::future::Future; use crate::io::{self, Read}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct ReadExactFuture<'a, T: Unpin + ?Sized> { pub(crate) reader: &'a mut T, pub(crate) buf: &'a mut [u8], } impl Future for ReadExactFuture<'_, T> { type Output = io::Result<()>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { reader, buf } = &mut *self; while !buf.is_empty() { let n = futures_core::ready!(Pin::new(&mut *reader).poll_read(cx, buf))?; let (_, rest) = mem::replace(buf, &mut []).split_at_mut(n); *buf = rest; if n == 0 { return Poll::Ready(Err(io::ErrorKind::UnexpectedEof.into())); } } Poll::Ready(Ok(())) } } async-rs-async-std-57f61ae/src/io/read/read_to_end.rs000066400000000000000000000045301476537407000225350ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::io::{self, Read}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct ReadToEndFuture<'a, T: Unpin + ?Sized> { pub(crate) reader: &'a mut T, pub(crate) buf: &'a mut Vec, pub(crate) start_len: usize, } impl Future for ReadToEndFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { reader, buf, start_len, } = &mut *self; read_to_end_internal(Pin::new(reader), cx, buf, *start_len) } } // This uses an adaptive system to extend the vector when it fills. We want to // avoid paying to allocate and zero a huge chunk of memory if the reader only // has 4 bytes while still making large reads if the reader does have a ton // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every // time is 4,500 times (!) slower than this if the reader has a very small // amount of data to return. // // Because we're extending the buffer with uninitialized data for trusted // readers, we need to make sure to truncate that if any of this panics. pub fn read_to_end_internal( mut rd: Pin<&mut R>, cx: &mut Context<'_>, buf: &mut Vec, start_len: usize, ) -> Poll> { struct Guard<'a> { buf: &'a mut Vec, len: usize, } impl Drop for Guard<'_> { fn drop(&mut self) { unsafe { self.buf.set_len(self.len); } } } let mut g = Guard { len: buf.len(), buf, }; let ret; loop { if g.len == g.buf.len() { unsafe { g.buf.reserve(32); let capacity = g.buf.capacity(); g.buf.set_len(capacity); super::initialize(&rd, &mut g.buf[g.len..]); } } match futures_core::ready!(rd.as_mut().poll_read(cx, &mut g.buf[g.len..])) { Ok(0) => { ret = Poll::Ready(Ok(g.len - start_len)); break; } Ok(n) => g.len += n, Err(e) => { ret = Poll::Ready(Err(e)); break; } } } ret } async-rs-async-std-57f61ae/src/io/read/read_to_string.rs000066400000000000000000000027011476537407000232730ustar00rootroot00000000000000use std::mem; use std::pin::Pin; use std::str; use std::future::Future; use super::read_to_end_internal; use crate::io::{self, Read}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct ReadToStringFuture<'a, T: Unpin + ?Sized> { pub(crate) reader: &'a mut T, pub(crate) buf: &'a mut String, pub(crate) bytes: Vec, pub(crate) start_len: usize, } impl Future for ReadToStringFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { reader, buf, bytes, start_len, } = &mut *self; let reader = Pin::new(reader); let ret = futures_core::ready!(read_to_end_internal(reader, cx, bytes, *start_len)); if str::from_utf8(&bytes).is_err() { Poll::Ready(ret.and_then(|_| { Err(io::Error::new( io::ErrorKind::InvalidData, "stream did not contain valid UTF-8", )) })) } else { #[allow(clippy::debug_assert_with_mut_call)] { debug_assert!(buf.is_empty()); } // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. mem::swap(unsafe { buf.as_mut_vec() }, bytes); Poll::Ready(ret) } } } async-rs-async-std-57f61ae/src/io/read/read_vectored.rs000066400000000000000000000011511476537407000230740ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::io::{self, IoSliceMut, Read}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct ReadVectoredFuture<'a, T: Unpin + ?Sized> { pub(crate) reader: &'a mut T, pub(crate) bufs: &'a mut [IoSliceMut<'a>], } impl Future for ReadVectoredFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { reader, bufs } = &mut *self; Pin::new(reader).poll_read_vectored(cx, bufs) } } async-rs-async-std-57f61ae/src/io/read/take.rs000066400000000000000000000150371476537407000212220ustar00rootroot00000000000000use std::cmp; use std::pin::Pin; use pin_project_lite::pin_project; use crate::io::{self, BufRead, Read}; use crate::task::{Context, Poll}; pin_project! { /// Reader adaptor which limits the bytes read from an underlying reader. /// /// This struct is generally created by calling [`take`] on a reader. /// Please see the documentation of [`take`] for more details. /// /// [`take`]: trait.Read.html#method.take #[derive(Debug)] pub struct Take { #[pin] pub(crate) inner: T, pub(crate) limit: u64, } } impl Take { /// Returns the number of bytes that can be read before this instance will /// return EOF. /// /// # Note /// /// This instance may reach `EOF` after reading fewer bytes than indicated by /// this method if the underlying [`Read`] instance reaches EOF. /// /// [`Read`]: trait.Read.html /// /// # Examples /// /// ```no_run /// # fn main() -> async_std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::fs::File; /// /// let f = File::open("foo.txt").await?; /// /// // read at most five bytes /// let handle = f.take(5); /// /// println!("limit: {}", handle.limit()); /// # /// # Ok(()) }) } /// ``` pub fn limit(&self) -> u64 { self.limit } /// Sets the number of bytes that can be read before this instance will /// return EOF. This is the same as constructing a new `Take` instance, so /// the amount of bytes read and the previous limit value don't matter when /// calling this method. /// /// # Examples /// /// ```no_run /// # fn main() -> async_std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::fs::File; /// /// let f = File::open("foo.txt").await?; /// /// // read at most five bytes /// let mut handle = f.take(5); /// handle.set_limit(10); /// /// assert_eq!(handle.limit(), 10); /// # /// # Ok(()) }) } /// ``` pub fn set_limit(&mut self, limit: u64) { self.limit = limit; } /// Consumes the `Take`, returning the wrapped reader. /// /// # Examples /// /// ```no_run /// # fn main() -> async_std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::fs::File; /// /// let file = File::open("foo.txt").await?; /// /// let mut buffer = [0; 5]; /// let mut handle = file.take(5); /// handle.read(&mut buffer).await?; /// /// let file = handle.into_inner(); /// # /// # Ok(()) }) } /// ``` pub fn into_inner(self) -> T { self.inner } /// Gets a reference to the underlying reader. /// /// # Examples /// /// ```no_run /// # fn main() -> async_std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::fs::File; /// /// let file = File::open("foo.txt").await?; /// /// let mut buffer = [0; 5]; /// let mut handle = file.take(5); /// handle.read(&mut buffer).await?; /// /// let file = handle.get_ref(); /// # /// # Ok(()) }) } /// ``` pub fn get_ref(&self) -> &T { &self.inner } /// Gets a mutable reference to the underlying reader. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying reader as doing so may corrupt the internal limit of this /// `Take`. /// /// # Examples /// /// ```no_run /// # fn main() -> async_std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::fs::File; /// /// let file = File::open("foo.txt").await?; /// /// let mut buffer = [0; 5]; /// let mut handle = file.take(5); /// handle.read(&mut buffer).await?; /// /// let file = handle.get_mut(); /// # /// # Ok(()) }) } /// ``` pub fn get_mut(&mut self) -> &mut T { &mut self.inner } } impl Read for Take { /// Attempt to read from the `AsyncRead` into `buf`. fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { let this = self.project(); take_read_internal(this.inner, cx, buf, this.limit) } } pub fn take_read_internal( mut rd: Pin<&mut R>, cx: &mut Context<'_>, buf: &mut [u8], limit: &mut u64, ) -> Poll> { // Don't call into inner reader at all at EOF because it may still block if *limit == 0 { return Poll::Ready(Ok(0)); } let max = cmp::min(buf.len() as u64, *limit) as usize; match futures_core::ready!(rd.as_mut().poll_read(cx, &mut buf[..max])) { Ok(n) => { *limit -= n as u64; Poll::Ready(Ok(n)) } Err(e) => Poll::Ready(Err(e)), } } impl BufRead for Take { fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); if *this.limit == 0 { return Poll::Ready(Ok(&[])); } match futures_core::ready!(this.inner.poll_fill_buf(cx)) { Ok(buf) => { let cap = cmp::min(buf.len() as u64, *this.limit) as usize; Poll::Ready(Ok(&buf[..cap])) } Err(e) => Poll::Ready(Err(e)), } } fn consume(self: Pin<&mut Self>, amt: usize) { let this = self.project(); // Don't let callers reset the limit by passing an overlarge value let amt = cmp::min(amt as u64, *this.limit) as usize; *this.limit -= amt as u64; this.inner.consume(amt); } } #[cfg(all(test, not(target_os = "unknown")))] mod tests { use crate::io; use crate::prelude::*; use crate::task; #[test] fn test_take_basics() -> std::io::Result<()> { let source: io::Cursor> = io::Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8]); task::block_on(async move { let mut buffer = [0u8; 5]; // read at most five bytes let mut handle = source.take(5); handle.read(&mut buffer).await?; assert_eq!(buffer, [0, 1, 2, 3, 4]); // check that the we are actually at the end assert_eq!(handle.read(&mut buffer).await.unwrap(), 0); Ok(()) }) } } async-rs-async-std-57f61ae/src/io/repeat.rs000066400000000000000000000024651476537407000206440ustar00rootroot00000000000000use std::fmt; use std::pin::Pin; use crate::io::{self, Read}; use crate::task::{Context, Poll}; /// Creates an instance of a reader that infinitely repeats one byte. /// /// All reads from this reader will succeed by filling the specified buffer with the given byte. /// /// ## Examples /// /// ```rust /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// use async_std::prelude::*; /// /// let mut buffer = [0; 3]; /// io::repeat(0b101).read_exact(&mut buffer).await?; /// /// assert_eq!(buffer, [0b101, 0b101, 0b101]); /// # /// # Ok(()) }) } /// ``` pub fn repeat(byte: u8) -> Repeat { Repeat { byte } } /// A reader which yields one byte over and over and over and over and over and... /// /// This reader is created by the [`repeat`] function. See its /// documentation for more. /// /// [`repeat`]: fn.repeat.html pub struct Repeat { byte: u8, } impl fmt::Debug for Repeat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Empty { .. }") } } impl Read for Repeat { #[inline] fn poll_read( self: Pin<&mut Self>, _: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { for b in &mut *buf { *b = self.byte; } Poll::Ready(Ok(buf.len())) } } async-rs-async-std-57f61ae/src/io/seek/000077500000000000000000000000001476537407000177365ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/io/seek/mod.rs000066400000000000000000000020311476537407000210570ustar00rootroot00000000000000mod seek; use seek::SeekFuture; use crate::io::SeekFrom; pub use futures_io::AsyncSeek as Seek; #[doc = r#" Extension methods for [`Seek`]. [`Seek`]: ../trait.Seek.html "#] pub trait SeekExt: Seek { #[doc = r#" Seeks to a new position in a byte stream. Returns the new position in the byte stream. A seek beyond the end of stream is allowed, but behavior is defined by the implementation. # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::io::SeekFrom; use async_std::prelude::*; let mut file = File::open("a.txt").await?; let file_len = file.seek(SeekFrom::End(0)).await?; # # Ok(()) }) } ``` "#] fn seek( &mut self, pos: SeekFrom, ) -> SeekFuture<'_, Self> where Self: Unpin, { SeekFuture { seeker: self, pos } } } impl SeekExt for T {} async-rs-async-std-57f61ae/src/io/seek/seek.rs000066400000000000000000000010611476537407000212310ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::io::{self, Seek, SeekFrom}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct SeekFuture<'a, T: Unpin + ?Sized> { pub(crate) seeker: &'a mut T, pub(crate) pos: SeekFrom, } impl Future for SeekFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let pos = self.pos; Pin::new(&mut *self.seeker).poll_seek(cx, pos) } } async-rs-async-std-57f61ae/src/io/sink.rs000066400000000000000000000024411476537407000203220ustar00rootroot00000000000000use std::fmt; use std::pin::Pin; use crate::io::{self, Write}; use crate::task::{Context, Poll}; /// Creates a writer that consumes and drops all data. /// /// # Examples /// /// ```rust /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// use async_std::prelude::*; /// /// let mut writer = io::sink(); /// writer.write(b"hello world").await?; /// # /// # Ok(()) }) } /// ``` pub fn sink() -> Sink { Sink { _private: () } } /// A writer that consumes and drops all data. /// /// This writer is constructed by the [`sink`] function. See its documentation /// for more. /// /// [`sink`]: fn.sink.html pub struct Sink { _private: (), } impl fmt::Debug for Sink { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Sink { .. }") } } impl Write for Sink { #[inline] fn poll_write( self: Pin<&mut Self>, _: &mut Context<'_>, buf: &[u8], ) -> Poll> { Poll::Ready(Ok(buf.len())) } #[inline] fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } #[inline] fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } } async-rs-async-std-57f61ae/src/io/stderr.rs000066400000000000000000000153621476537407000206670ustar00rootroot00000000000000use std::pin::Pin; use std::sync::Mutex; use std::future::Future; use crate::io::{self, Write}; use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; /// Constructs a new handle to the standard error of the current process. /// /// This function is an async version of [`std::io::stderr`]. /// /// [`std::io::stderr`]: https://doc.rust-lang.org/std/io/fn.stderr.html /// /// ### Note: Windows Portability Consideration /// /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return /// an error. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// use async_std::prelude::*; /// /// let mut stderr = io::stderr(); /// stderr.write_all(b"Hello, world!").await?; /// # /// # Ok(()) }) } /// ``` pub fn stderr() -> Stderr { Stderr(Mutex::new(State::Idle(Some(Inner { stderr: std::io::stderr(), buf: Vec::new(), last_op: None, })))) } /// A handle to the standard error of the current process. /// /// This writer is created by the [`stderr`] function. See its documentation for /// more. /// /// ### Note: Windows Portability Consideration /// /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return /// an error. /// /// [`stderr`]: fn.stderr.html #[derive(Debug)] pub struct Stderr(Mutex); /// The state of the asynchronous stderr. /// /// The stderr can be either idle or busy performing an asynchronous operation. #[derive(Debug)] enum State { /// The stderr is idle. Idle(Option), /// The stderr is blocked on an asynchronous operation. /// /// Awaiting this operation will result in the new state of the stderr. Busy(JoinHandle), } /// Inner representation of the asynchronous stderr. #[derive(Debug)] struct Inner { /// The blocking stderr handle. stderr: std::io::Stderr, /// The write buffer. buf: Vec, /// The result of the last asynchronous operation on the stderr. last_op: Option, } /// Possible results of an asynchronous operation on the stderr. #[derive(Debug)] enum Operation { Write(io::Result), Flush(io::Result<()>), } impl Write for Stderr { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { let mut state_guard = self.0.lock().unwrap(); let state = &mut *state_guard; loop { match state { State::Idle(opt) => { let inner = opt.as_mut().unwrap(); // Check if the operation has completed. if let Some(Operation::Write(res)) = inner.last_op.take() { let n = res?; // If more data was written than is available in the buffer, let's retry // the write operation. if n <= buf.len() { return Poll::Ready(Ok(n)); } } else { let mut inner = opt.take().unwrap(); // Set the length of the inner buffer to the length of the provided buffer. if inner.buf.len() < buf.len() { inner.buf.reserve(buf.len() - inner.buf.len()); } unsafe { inner.buf.set_len(buf.len()); } // Copy the data to write into the inner buffer. inner.buf[..buf.len()].copy_from_slice(buf); // Start the operation asynchronously. *state = State::Busy(spawn_blocking(move || { let res = std::io::Write::write(&mut inner.stderr, &inner.buf); inner.last_op = Some(Operation::Write(res)); State::Idle(Some(inner)) })); } } // Poll the asynchronous operation the stderr is currently blocked on. State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), } } } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut state_guard = self.0.lock().unwrap(); let state = &mut *state_guard; loop { match state { State::Idle(opt) => { let inner = opt.as_mut().unwrap(); // Check if the operation has completed. if let Some(Operation::Flush(res)) = inner.last_op.take() { return Poll::Ready(res); } else { let mut inner = opt.take().unwrap(); // Start the operation asynchronously. *state = State::Busy(spawn_blocking(move || { let res = std::io::Write::flush(&mut inner.stderr); inner.last_op = Some(Operation::Flush(res)); State::Idle(Some(inner)) })); } } // Poll the asynchronous operation the stderr is currently blocked on. State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), } } } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.poll_flush(cx) } } cfg_unix! { use crate::os::unix::io::{AsRawFd, RawFd}; impl AsRawFd for Stderr { fn as_raw_fd(&self) -> RawFd { std::io::stderr().as_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd}; impl AsFd for Stderr { fn as_fd(&self) -> BorrowedFd<'_> { unsafe { BorrowedFd::borrow_raw(std::io::stderr().as_raw_fd()) } } } } } cfg_windows! { use crate::os::windows::io::{AsRawHandle, RawHandle}; impl AsRawHandle for Stderr { fn as_raw_handle(&self) -> RawHandle { std::io::stderr().as_raw_handle() } } cfg_io_safety! { use crate::os::windows::io::{AsHandle, BorrowedHandle}; impl AsHandle for Stderr { fn as_handle(&self) -> BorrowedHandle<'_> { unsafe { BorrowedHandle::borrow_raw(std::io::stderr().as_raw_handle()) } } } } } async-rs-async-std-57f61ae/src/io/stdin.rs000066400000000000000000000167401476537407000205060ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use std::sync::Mutex; use crate::future; use crate::io::{self, Read}; use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; use crate::utils::Context as _; /// Constructs a new handle to the standard input of the current process. /// /// This function is an async version of [`std::io::stdin`]. /// /// [`std::io::stdin`]: https://doc.rust-lang.org/std/io/fn.stdin.html /// /// ### Note: Windows Portability Consideration /// /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return /// an error. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// /// let stdin = io::stdin(); /// let mut line = String::new(); /// stdin.read_line(&mut line).await?; /// # /// # Ok(()) }) } /// ``` pub fn stdin() -> Stdin { Stdin(Mutex::new(State::Idle(Some(Inner { stdin: std::io::stdin(), line: String::new(), buf: Vec::new(), last_op: None, })))) } /// A handle to the standard input of the current process. /// /// This reader is created by the [`stdin`] function. See its documentation for /// more. /// /// ### Note: Windows Portability Consideration /// /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return /// an error. /// /// [`stdin`]: fn.stdin.html #[derive(Debug)] pub struct Stdin(Mutex); /// The state of the asynchronous stdin. /// /// The stdin can be either idle or busy performing an asynchronous operation. #[derive(Debug)] enum State { /// The stdin is idle. Idle(Option), /// The stdin is blocked on an asynchronous operation. /// /// Awaiting this operation will result in the new state of the stdin. Busy(JoinHandle), } /// Inner representation of the asynchronous stdin. #[derive(Debug)] struct Inner { /// The blocking stdin handle. stdin: std::io::Stdin, /// The line buffer. line: String, /// The read buffer. buf: Vec, /// The result of the last asynchronous operation on the stdin. last_op: Option, } /// Possible results of an asynchronous operation on the stdin. #[derive(Debug)] enum Operation { ReadLine(io::Result), Read(io::Result), } impl Stdin { /// Reads a line of input into the specified buffer. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// /// let stdin = io::stdin(); /// let mut line = String::new(); /// stdin.read_line(&mut line).await?; /// # /// # Ok(()) }) } /// ``` pub async fn read_line(&self, buf: &mut String) -> io::Result { future::poll_fn(|cx| { let state = &mut *self.0.lock().unwrap(); loop { match state { State::Idle(opt) => { let inner = opt.as_mut().unwrap(); // Check if the operation has completed. if let Some(Operation::ReadLine(res)) = inner.last_op.take() { let n = res?; // Copy the read data into the buffer and return. buf.push_str(&inner.line); return Poll::Ready(Ok(n)); } else { let mut inner = opt.take().unwrap(); // Start the operation asynchronously. *state = State::Busy(spawn_blocking(move || { inner.line.clear(); let res = inner.stdin.read_line(&mut inner.line); inner.last_op = Some(Operation::ReadLine(res)); State::Idle(Some(inner)) })); } } // Poll the asynchronous operation the stdin is currently blocked on. State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), } } }) .await .context(|| String::from("could not read line on stdin")) } } impl Read for Stdin { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { let mut state_guard = self.0.lock().unwrap(); let state = &mut *state_guard; loop { match state { State::Idle(opt) => { let inner = opt.as_mut().unwrap(); // Check if the operation has completed. if let Some(Operation::Read(res)) = inner.last_op.take() { let n = res?; // If more data was read than fits into the buffer, let's retry the read // operation. if n <= buf.len() { // Copy the read data into the buffer and return. buf[..n].copy_from_slice(&inner.buf[..n]); return Poll::Ready(Ok(n)); } } else { let mut inner = opt.take().unwrap(); // Set the length of the inner buffer to the length of the provided buffer. if inner.buf.len() < buf.len() { inner.buf.reserve(buf.len() - inner.buf.len()); } unsafe { inner.buf.set_len(buf.len()); } // Start the operation asynchronously. *state = State::Busy(spawn_blocking(move || { let res = std::io::Read::read(&mut inner.stdin, &mut inner.buf); inner.last_op = Some(Operation::Read(res)); State::Idle(Some(inner)) })); } } // Poll the asynchronous operation the stdin is currently blocked on. State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), } } } } cfg_unix! { use crate::os::unix::io::{AsRawFd, RawFd}; impl AsRawFd for Stdin { fn as_raw_fd(&self) -> RawFd { std::io::stdin().as_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd}; impl AsFd for Stdin { fn as_fd(&self) -> BorrowedFd<'_> { unsafe { BorrowedFd::borrow_raw(std::io::stdin().as_raw_fd()) } } } } } cfg_windows! { use crate::os::windows::io::{AsRawHandle, RawHandle}; impl AsRawHandle for Stdin { fn as_raw_handle(&self) -> RawHandle { std::io::stdin().as_raw_handle() } } cfg_io_safety! { use crate::os::windows::io::{AsHandle, BorrowedHandle}; impl AsHandle for Stdin { fn as_handle(&self) -> BorrowedHandle<'_> { unsafe { BorrowedHandle::borrow_raw(std::io::stdin().as_raw_handle()) } } } } } async-rs-async-std-57f61ae/src/io/stdio.rs000066400000000000000000000010601476537407000204740ustar00rootroot00000000000000//! Internal types for stdio. //! //! This module is a port of `libstd/io/stdio.rs`,and contains internal types for `print`/`eprint`. use crate::io::{stderr, stdout}; use crate::prelude::*; use std::fmt; #[doc(hidden)] pub async fn _print(args: fmt::Arguments<'_>) { if let Err(e) = stdout().write_fmt(args).await { panic!("failed printing to stdout: {}", e); } } #[doc(hidden)] pub async fn _eprint(args: fmt::Arguments<'_>) { if let Err(e) = stderr().write_fmt(args).await { panic!("failed printing to stderr: {}", e); } } async-rs-async-std-57f61ae/src/io/stdout.rs000066400000000000000000000153641476537407000207100ustar00rootroot00000000000000use std::pin::Pin; use std::sync::Mutex; use std::future::Future; use crate::io::{self, Write}; use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; /// Constructs a new handle to the standard output of the current process. /// /// This function is an async version of [`std::io::stdout`]. /// /// [`std::io::stdout`]: https://doc.rust-lang.org/std/io/fn.stdout.html /// /// ### Note: Windows Portability Consideration /// /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return /// an error. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// use async_std::prelude::*; /// /// let mut stdout = io::stdout(); /// stdout.write_all(b"Hello, world!").await?; /// # /// # Ok(()) }) } /// ``` pub fn stdout() -> Stdout { Stdout(Mutex::new(State::Idle(Some(Inner { stdout: std::io::stdout(), buf: Vec::new(), last_op: None, })))) } /// A handle to the standard output of the current process. /// /// This writer is created by the [`stdout`] function. See its documentation /// for more. /// /// ### Note: Windows Portability Consideration /// /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return /// an error. /// /// [`stdout`]: fn.stdout.html #[derive(Debug)] pub struct Stdout(Mutex); /// The state of the asynchronous stdout. /// /// The stdout can be either idle or busy performing an asynchronous operation. #[derive(Debug)] enum State { /// The stdout is idle. Idle(Option), /// The stdout is blocked on an asynchronous operation. /// /// Awaiting this operation will result in the new state of the stdout. Busy(JoinHandle), } /// Inner representation of the asynchronous stdout. #[derive(Debug)] struct Inner { /// The blocking stdout handle. stdout: std::io::Stdout, /// The write buffer. buf: Vec, /// The result of the last asynchronous operation on the stdout. last_op: Option, } /// Possible results of an asynchronous operation on the stdout. #[derive(Debug)] enum Operation { Write(io::Result), Flush(io::Result<()>), } impl Write for Stdout { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { let mut state_guard = self.0.lock().unwrap(); let state = &mut *state_guard; loop { match state { State::Idle(opt) => { let inner = opt.as_mut().unwrap(); // Check if the operation has completed. if let Some(Operation::Write(res)) = inner.last_op.take() { let n = res?; // If more data was written than is available in the buffer, let's retry // the write operation. if n <= buf.len() { return Poll::Ready(Ok(n)); } } else { let mut inner = opt.take().unwrap(); // Set the length of the inner buffer to the length of the provided buffer. if inner.buf.len() < buf.len() { inner.buf.reserve(buf.len() - inner.buf.len()); } unsafe { inner.buf.set_len(buf.len()); } // Copy the data to write into the inner buffer. inner.buf[..buf.len()].copy_from_slice(buf); // Start the operation asynchronously. *state = State::Busy(spawn_blocking(move || { let res = std::io::Write::write(&mut inner.stdout, &inner.buf); inner.last_op = Some(Operation::Write(res)); State::Idle(Some(inner)) })); } } // Poll the asynchronous operation the stdout is currently blocked on. State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), } } } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut state_guard = self.0.lock().unwrap(); let state = &mut *state_guard; loop { match state { State::Idle(opt) => { let inner = opt.as_mut().unwrap(); // Check if the operation has completed. if let Some(Operation::Flush(res)) = inner.last_op.take() { return Poll::Ready(res); } else { let mut inner = opt.take().unwrap(); // Start the operation asynchronously. *state = State::Busy(spawn_blocking(move || { let res = std::io::Write::flush(&mut inner.stdout); inner.last_op = Some(Operation::Flush(res)); State::Idle(Some(inner)) })); } } // Poll the asynchronous operation the stdout is currently blocked on. State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), } } } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.poll_flush(cx) } } cfg_unix! { use crate::os::unix::io::{AsRawFd, RawFd}; impl AsRawFd for Stdout { fn as_raw_fd(&self) -> RawFd { std::io::stdout().as_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd}; impl AsFd for Stdout { fn as_fd(&self) -> BorrowedFd<'_> { unsafe { BorrowedFd::borrow_raw(std::io::stdout().as_raw_fd()) } } } } } cfg_windows! { use crate::os::windows::io::{AsRawHandle, RawHandle}; impl AsRawHandle for Stdout { fn as_raw_handle(&self) -> RawHandle { std::io::stdout().as_raw_handle() } } cfg_io_safety! { use crate::os::windows::io::{AsHandle, BorrowedHandle}; impl AsHandle for Stdout { fn as_handle(&self) -> BorrowedHandle<'_> { unsafe { BorrowedHandle::borrow_raw(std::io::stdout().as_raw_handle()) } } } } } async-rs-async-std-57f61ae/src/io/timeout.rs000066400000000000000000000034471476537407000210530ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; use std::time::Duration; use pin_project_lite::pin_project; use crate::io; use crate::utils::{timer_after, Timer}; /// Awaits an I/O future or times out after a duration of time. /// /// If you want to await a non I/O future consider using /// [`future::timeout`](../future/fn.timeout.html) instead. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use std::time::Duration; /// /// use async_std::io; /// /// io::timeout(Duration::from_secs(5), async { /// let stdin = io::stdin(); /// let mut line = String::new(); /// let n = stdin.read_line(&mut line).await?; /// Ok(()) /// }) /// .await?; /// # /// # Ok(()) }) } /// ``` pub async fn timeout(dur: Duration, f: F) -> io::Result where F: Future>, { Timeout { timeout: timer_after(dur), future: f, } .await } pin_project! { /// Future returned by the `FutureExt::timeout` method. #[derive(Debug)] pub struct Timeout where F: Future>, { #[pin] future: F, #[pin] timeout: Timer, } } impl Future for Timeout where F: Future>, { type Output = io::Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); match this.future.poll(cx) { Poll::Pending => {} other => return other, } if this.timeout.poll(cx).is_ready() { let err = Err(io::Error::new(io::ErrorKind::TimedOut, "future timed out")); Poll::Ready(err) } else { Poll::Pending } } } async-rs-async-std-57f61ae/src/io/utils.rs000066400000000000000000000020211476537407000205100ustar00rootroot00000000000000use crate::utils::Context; use std::{error::Error as StdError, fmt, io}; /// Wrap `std::io::Error` with additional message /// /// Keeps the original error kind and stores the original I/O error as `source`. impl Context for Result { fn context(self, message: impl Fn() -> String) -> Self { self.map_err(|e| VerboseError::wrap(e, message())) } } #[derive(Debug)] pub(crate) struct VerboseError { source: io::Error, message: String, } impl VerboseError { pub(crate) fn wrap(source: io::Error, message: impl Into) -> io::Error { io::Error::new( source.kind(), VerboseError { source, message: message.into(), }, ) } } impl fmt::Display for VerboseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.message) } } impl StdError for VerboseError { fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(&self.source) } } async-rs-async-std-57f61ae/src/io/write/000077500000000000000000000000001476537407000201415ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/io/write/flush.rs000066400000000000000000000007541476537407000216360ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::io::{self, Write}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct FlushFuture<'a, T: Unpin + ?Sized> { pub(crate) writer: &'a mut T, } impl Future for FlushFuture<'_, T> { type Output = io::Result<()>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { Pin::new(&mut *self.writer).poll_flush(cx) } } async-rs-async-std-57f61ae/src/io/write/mod.rs000066400000000000000000000122331476537407000212670ustar00rootroot00000000000000mod flush; mod write; mod write_all; mod write_fmt; mod write_vectored; use flush::FlushFuture; use write::WriteFuture; use write_all::WriteAllFuture; use write_fmt::WriteFmtFuture; use write_vectored::WriteVectoredFuture; use crate::io::{self, IoSlice}; pub use futures_io::AsyncWrite as Write; #[doc = r#" Extension methods for [`Write`]. [`Write`]: ../trait.Write.html "#] pub trait WriteExt: Write { #[doc = r#" Writes some bytes into the byte stream. Returns the number of bytes written from the start of the buffer. If the return value is `Ok(n)` then it must be guaranteed that `0 <= n <= buf.len()`. A return value of `0` typically means that the underlying object is no longer able to accept bytes and will likely not be able to in the future as well, or that the buffer provided is empty. # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::prelude::*; let mut file = File::create("a.txt").await?; let n = file.write(b"hello world").await?; # # Ok(()) }) } ``` "#] fn write<'a>( &'a mut self, buf: &'a [u8], ) -> WriteFuture<'a, Self> where Self: Unpin, { WriteFuture { writer: self, buf } } #[doc = r#" Flushes the stream to ensure that all buffered contents reach their destination. # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::prelude::*; let mut file = File::create("a.txt").await?; file.write_all(b"hello world").await?; file.flush().await?; # # Ok(()) }) } ``` "#] fn flush(&mut self) -> FlushFuture<'_, Self> where Self: Unpin, { FlushFuture { writer: self } } #[doc = r#" Like [`write`], except that it writes from a slice of buffers. Data is copied from each buffer in order, with the final buffer read from possibly being only partially consumed. This method must behave as a call to [`write`] with the buffers concatenated would. The default implementation calls [`write`] with either the first nonempty buffer provided, or an empty one if none exists. [`write`]: #tymethod.write "#] fn write_vectored<'a>( &'a mut self, bufs: &'a [IoSlice<'a>], ) -> WriteVectoredFuture<'a, Self> where Self: Unpin, { WriteVectoredFuture { writer: self, bufs } } #[doc = r#" Writes an entire buffer into the byte stream. This method will continuously call [`write`] until there is no more data to be written or an error is returned. This method will not return until the entire buffer has been successfully written or such an error occurs. [`write`]: #tymethod.write # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::prelude::*; let mut file = File::create("a.txt").await?; file.write_all(b"hello world").await?; # # Ok(()) }) } ``` [`write`]: #tymethod.write "#] fn write_all<'a>( &'a mut self, buf: &'a [u8], ) -> WriteAllFuture<'a, Self> where Self: Unpin, { WriteAllFuture { writer: self, buf } } #[doc = r#" Writes a formatted string into this writer, returning any error encountered. This method will continuously call [`write`] until there is no more data to be written or an error is returned. This future will not resolve until the entire buffer has been successfully written or such an error occurs. [`write`]: #tymethod.write # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::io::prelude::*; use async_std::fs::File; let mut buffer = File::create("foo.txt").await?; // this call write!(buffer, "{:.*}", 2, 1.234567).await?; // turns into this: buffer.write_fmt(format_args!("{:.*}", 2, 1.234567)).await?; # # Ok(()) }) } ``` "#] fn write_fmt<'a>( &'a mut self, fmt: std::fmt::Arguments<'_>, ) -> WriteFmtFuture<'a, Self> where Self: Unpin, { // In order to not have to implement an async version of `fmt` including private types // and all, we convert `Arguments` to a `Result>` and pass that to the Future. // Doing an owned conversion saves us from juggling references. let mut string = String::new(); let res = std::fmt::write(&mut string, fmt) .map(|_| string.into_bytes()) .map_err(|_| io::Error::new(io::ErrorKind::Other, "formatter error")); WriteFmtFuture { writer: self, res: Some(res), buffer: None, amt: 0 } } } impl WriteExt for T {} async-rs-async-std-57f61ae/src/io/write/write.rs000066400000000000000000000010561476537407000216430ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::io::{self, Write}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct WriteFuture<'a, T: Unpin + ?Sized> { pub(crate) writer: &'a mut T, pub(crate) buf: &'a [u8], } impl Future for WriteFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let buf = self.buf; Pin::new(&mut *self.writer).poll_write(cx, buf) } } async-rs-async-std-57f61ae/src/io/write/write_all.rs000066400000000000000000000016041476537407000224720ustar00rootroot00000000000000use std::mem; use std::pin::Pin; use std::future::Future; use crate::io::{self, Write}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct WriteAllFuture<'a, T: Unpin + ?Sized> { pub(crate) writer: &'a mut T, pub(crate) buf: &'a [u8], } impl Future for WriteAllFuture<'_, T> { type Output = io::Result<()>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { writer, buf } = &mut *self; while !buf.is_empty() { let n = futures_core::ready!(Pin::new(&mut **writer).poll_write(cx, buf))?; let (_, rest) = mem::replace(buf, &[]).split_at(n); *buf = rest; if n == 0 { return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); } } Poll::Ready(Ok(())) } } async-rs-async-std-57f61ae/src/io/write/write_fmt.rs000066400000000000000000000030451476537407000225110ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::io::{self, Write}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] #[must_use] pub struct WriteFmtFuture<'a, T: Unpin + ?Sized> { pub(crate) writer: &'a mut T, pub(crate) res: Option>>, pub(crate) buffer: Option>, pub(crate) amt: usize, } impl Future for WriteFmtFuture<'_, T> { type Output = io::Result<()>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { // Process the internal Result the first time we run. if self.buffer.is_none() { match self.res.take().unwrap() { Err(err) => return Poll::Ready(Err(err)), Ok(buffer) => self.buffer = Some(buffer), }; } // Get the types from the future. let Self { writer, amt, buffer, .. } = &mut *self; let buffer = buffer.as_mut().unwrap(); // Copy the data from the buffer into the writer until it's done. loop { if *amt == buffer.len() { futures_core::ready!(Pin::new(&mut **writer).poll_flush(cx))?; return Poll::Ready(Ok(())); } let i = futures_core::ready!(Pin::new(&mut **writer).poll_write(cx, &buffer[*amt..]))?; if i == 0 { return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); } *amt += i; } } } async-rs-async-std-57f61ae/src/io/write/write_vectored.rs000066400000000000000000000011351476537407000235340ustar00rootroot00000000000000use std::pin::Pin; use std::future::Future; use crate::io::{self, IoSlice, Write}; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct WriteVectoredFuture<'a, T: Unpin + ?Sized> { pub(crate) writer: &'a mut T, pub(crate) bufs: &'a [IoSlice<'a>], } impl Future for WriteVectoredFuture<'_, T> { type Output = io::Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let bufs = self.bufs; Pin::new(&mut *self.writer).poll_write_vectored(cx, bufs) } } async-rs-async-std-57f61ae/src/lib.rs000066400000000000000000000264511476537407000175240ustar00rootroot00000000000000#![allow(rustdoc::invalid_html_tags)] //! # Async version of the Rust standard library //! //! `async-std` is a foundation of portable Rust software, a set of minimal and battle-tested //! shared abstractions for the [broader Rust ecosystem][crates.io]. It offers std types, like //! [`Future`] and [`Stream`], library-defined [operations on language primitives](#primitives), //! [standard macros](#macros), [I/O] and [multithreading], among [many other things][other]. //! //! `async-std` is available from [crates.io]. Once included, `async-std` can be accessed //! in [`use`] statements through the path `async_std`, as in [`use async_std::future`]. //! //! [I/O]: io/index.html //! [multithreading]: task/index.html //! [other]: #what-is-in-the-standard-library-documentation //! [`use`]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html //! [`use async_std::future`]: future/index.html //! [crates.io]: https://crates.io //! [`Future`]: future/trait.Future.html //! [`Stream`]: stream/trait.Stream.html //! //! # How to read this documentation //! //! If you already know the name of what you are looking for, the fastest way to //! find it is to use the search //! bar at the top of the page. //! //! Otherwise, you may want to jump to one of these useful sections: //! //! * [`async_std::*` modules](#modules) //! * [Async macros](#macros) //! * [The Async Prelude](prelude/index.html) //! * [Cargo.toml feature flags](#features) //! * [Examples](#examples) //! //! If this is your first time, the documentation for `async-std` is //! written to be casually perused. Clicking on interesting things should //! generally lead you to interesting places. Still, there are important bits //! you don't want to miss, so read on for a tour of the `async-std` and //! its documentation! //! //! Once you are familiar with the contents of `async-std` you may //! begin to find the verbosity of the prose distracting. At this stage in your //! development you may want to press the `[-]` button near the top of the //! page to collapse it into a more skimmable view. //! //! While you are looking at that `[-]` button also notice the `[src]` //! button. Rust's API documentation comes with the source code and you are //! encouraged to read it. The `async-std` source is generally high //! quality and a peek behind the curtains is often enlightening. //! //! Modules in this crate are organized in the same way as in `std`, except blocking //! functions have been replaced with async functions and threads have been replaced with //! lightweight tasks. //! //! You can find more information, reading materials, and other resources here: //! //! * [The async-std website](https://async.rs/) //! * [The async-std book](https://book.async.rs) //! * [GitHub repository](https://github.com/async-rs/async-std) //! * [List of code examples](https://github.com/async-rs/async-std/tree/HEAD/examples) //! * [Discord chat](https://discord.gg/JvZeVNe) //! //! # What is in the `async-std` documentation? //! //! First, `async-std` is divided into a number of focused //! modules, [all listed further down this page](#modules). These modules are //! the bedrock upon which async Rust is forged, and they have mighty names //! like [`async_std::os`] and [`async_std::task`]. Modules' documentation //! typically includes an overview of the module along with examples, and are //! a smart place to start familiarizing yourself with the library. //! //! Second, `async-std` defines [The Async Prelude], a small collection //! of items - mostly traits - that should be imported into every module of //! every async crate. The traits in the prelude are pervasive, making the //! prelude documentation a good entry point to learning about the library. //! //! [The Async Prelude]: prelude/index.html //! [`async_std::os`]: os/index.html //! [`async_std::task`]: task/index.html //! //! And finally, `async-std` exports a number of async macros, and //! [lists them on this page](#macros). //! //! # Contributing changes to the documentation //! //! Check out `async-std`'s contribution guidelines [here](https://async.rs/contribute). //! The source for this documentation can be found on [GitHub](https://github.com/async-rs). //! To contribute changes, make sure you read the guidelines first, then submit //! pull requests for your suggested changes. //! //! Contributions are appreciated! If you see a part of the docs that can be //! improved, submit a PR, or chat with us first on //! [Discord](https://discord.gg/JvZeVNe). //! //! # A tour of `async-std` //! //! The rest of this crate documentation is dedicated to pointing out notable //! features of `async-std`. //! //! ## Platform abstractions and I/O //! //! Besides basic data types, `async-std` is largely concerned with //! abstracting over differences in common platforms, most notably Windows and //! Unix derivatives. //! //! Common types of I/O, including [files], [TCP], [UDP], are defined in the //! [`io`], [`fs`], and [`net`] modules. //! //! The [`task`] module contains `async-std`'s task abstractions. [`sync`] //! contains further primitive shared memory types. [`channel`] contains the channel types for message passing. //! //! [files]: fs/struct.File.html //! [TCP]: net/struct.TcpStream.html //! [UDP]: net/struct.UdpSocket.html //! [`io`]: io/index.html //! [`sync`]: sync/index.html //! [`channel`]: channel/index.html //! //! ## Timeouts, intervals, and delays //! //! `async-std` provides several methods to manipulate time: //! //! * [`task::sleep`] to wait for a duration to pass without blocking. //! * [`stream::interval`] for emitting an event at a set interval. //! * [`future::timeout`] to time-out futures if they don't resolve within a //! set interval. //! //! [`task::sleep`]: task/fn.sleep.html //! [`stream::interval`]: stream/fn.interval.html //! [`future::timeout`]: future/fn.timeout.html //! //! # Examples //! //! All examples require the [`"attributes"` feature](#features) to be enabled. //! This feature is not enabled by default because it significantly impacts //! compile times. See [`task::block_on`] for an alternative way to start //! executing tasks. //! //! Call an async function from the main function: //! #![cfg_attr(feature = "attributes", doc = "```")] #![cfg_attr(not(feature = "attributes"), doc = "```ignore")] //! async fn say_hello() { //! println!("Hello, world!"); //! } //! //! #[async_std::main] //! async fn main() { //! say_hello().await; //! } //! ``` //! //! Await two futures concurrently, and return a tuple of their output: //! #![cfg_attr(feature = "attributes", doc = "```")] #![cfg_attr(not(feature = "attributes"), doc = "```ignore")] //! use async_std::prelude::*; //! //! #[async_std::main] //! async fn main() { //! let a = async { 1u8 }; //! let b = async { 2u8 }; //! assert_eq!(a.join(b).await, (1u8, 2u8)) //! } //! ``` //! //! Create a UDP server that echoes back each received message to the sender: //! #![cfg_attr(feature = "attributes", doc = "```no_run")] #![cfg_attr(not(feature = "attributes"), doc = "```ignore")] //! use async_std::net::UdpSocket; //! //! #[async_std::main] //! async fn main() -> std::io::Result<()> { //! let socket = UdpSocket::bind("127.0.0.1:8080").await?; //! println!("Listening on {}", socket.local_addr()?); //! //! let mut buf = vec![0u8; 1024]; //! //! loop { //! let (recv, peer) = socket.recv_from(&mut buf).await?; //! let sent = socket.send_to(&buf[..recv], &peer).await?; //! println!("Sent {} out of {} bytes to {}", sent, recv, peer); //! } //! } //! ``` //! [`task::block_on`]: task/fn.block_on.html //! //! # Features //! //! Items marked with //! unstable //! are available only when the `unstable` Cargo feature is enabled: //! //! ```toml //! [dependencies.async-std] //! version = "1.7.0" //! features = ["unstable"] //! ``` //! //! Items marked with //! attributes //! are available only when the `attributes` Cargo feature is enabled: //! //! ```toml //! [dependencies.async-std] //! version = "1.7.0" //! features = ["attributes"] //! ``` //! //! Compatibility with the `tokio` 1.0 runtime is also simultaneously possible //! using the `tokio1` Cargo feature: //! //! ```toml //! [dependencies.async-std] //! version = "1.7.0" //! features = ["tokio1"] //! ``` //! //! Compatibility with the `tokio` 0.2 runtime is possible using the `tokio02` //! Cargo feature: //! //! ```toml //! [dependencies.async-std] //! version = "1.7.0" //! features = ["tokio02"] //! ``` //! //! Compatibility with the `tokio` 0.3 runtime is also simultaneously possible //! using the `tokio03` Cargo feature: //! //! ```toml //! [dependencies.async-std] //! version = "1.7.0" //! features = ["tokio03"] //! ``` //! //! Additionally it's possible to only use the core traits and combinators by //! only enabling the `std` Cargo feature: //! //! ```toml //! [dependencies.async-std] //! version = "1.7.0" //! default-features = false //! features = ["std"] //! ``` //! //! And to use async-std on `no_std` targets that only support `alloc` only //! enable the `alloc` Cargo feature: //! //! ```toml //! [dependencies.async-std] //! version = "1.7.0" //! default-features = false //! features = ["alloc"] //! ``` //! //! # Runtime configuration //! //! Several environment variables are available to tune the async-std //! runtime: //! //! * `ASYNC_STD_THREAD_COUNT`: The number of threads that the //! async-std runtime will start. By default, this is one per logical //! cpu as determined by [async-global-executor](async_global_executor), //! which may be different than the number of physical cpus. Async-std //! _will panic_ if this is set to any value other than a positive //! integer. //! * `ASYNC_STD_THREAD_NAME`: The name that async-std's runtime //! threads report to the operating system. The default value is //! `"async-std/runtime"`. //! #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(feature = "docs", feature(doc_cfg))] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] #![allow(clippy::mutex_atomic, clippy::module_inception)] #![doc(test(attr(deny(rust_2018_idioms))))] #![doc(test(attr(allow(unused_extern_crates, unused_variables))))] #![doc(html_logo_url = "https://async.rs/images/logo--hero.svg")] #[macro_use] mod utils; #[cfg(feature = "attributes")] #[cfg_attr(feature = "docs", doc(cfg(attributes)))] #[doc(inline)] pub use async_attributes::{main, test}; #[cfg(feature = "std")] mod macros; cfg_alloc! { pub mod task; pub mod future; pub mod stream; } cfg_std! { pub mod io; pub mod os; pub mod prelude; pub mod sync; pub mod channel; } cfg_default! { #[cfg(not(target_os = "unknown"))] pub mod fs; pub mod path; pub mod net; #[cfg(not(target_os = "unknown"))] pub(crate) mod rt; } cfg_unstable! { pub mod pin; #[cfg(all(not(target_os = "unknown"), feature = "std"))] pub mod process; mod unit; mod vec; mod result; mod option; mod string; mod collections; } cfg_unstable_default! { #[doc(inline)] pub use std::{write, writeln}; } async-rs-async-std-57f61ae/src/macros.rs000066400000000000000000000131501476537407000202320ustar00rootroot00000000000000/// Prints to the standard output. /// /// Equivalent to the [`println!`] macro except that a newline is not printed at /// the end of the message. /// /// Note that stdout is frequently line-buffered by default so it may be /// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted /// immediately. /// /// Use `print!` only for the primary output of your program. Use /// [`eprint!`] instead to print error and progress messages. /// /// [`println!`]: macro.println.html /// [flush]: io/trait.Write.html#tymethod.flush /// [`eprint!`]: macro.eprint.html /// /// # Panics /// /// Panics if writing to `io::stdout()` fails. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::io; /// use async_std::prelude::*; /// use async_std::print; /// /// print!("this ").await; /// print!("will ").await; /// print!("be ").await; /// print!("on ").await; /// print!("the ").await; /// print!("same ").await; /// print!("line ").await; /// /// io::stdout().flush().await.unwrap(); /// /// print!("this string has a newline, why not choose println! instead?\n").await; /// /// io::stdout().flush().await.unwrap(); /// # /// # }) /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[macro_export] macro_rules! print { ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))) } /// Prints to the standard output, with a newline. /// /// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone /// (no additional CARRIAGE RETURN (`\r`/`U+000D`)). /// /// Use the [`format!`] syntax to write data to the standard output. /// See [`std::fmt`] for more information. /// /// Use `println!` only for the primary output of your program. Use /// [`eprintln!`] instead to print error and progress messages. /// /// [`format!`]: macro.format.html /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html /// [`eprintln!`]: macro.eprintln.html /// # Panics /// /// Panics if writing to `io::stdout` fails. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::println; /// /// println!().await; // prints just a newline /// println!("hello there!").await; /// println!("format {} arguments", "some").await; /// # /// # }) /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[macro_export] macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => (async { $crate::io::_print(format_args!($($arg)*)).await; $crate::io::_print(format_args!("\n")).await; }) } /// Prints to the standard error. /// /// Equivalent to the [`print!`] macro, except that output goes to /// [`io::stderr`] instead of `io::stdout`. See [`print!`] for /// example usage. /// /// Use `eprint!` only for error and progress messages. Use `print!` /// instead for the primary output of your program. /// /// [`io::stderr`]: io/struct.Stderr.html /// [`print!`]: macro.print.html /// /// # Panics /// /// Panics if writing to `io::stderr` fails. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::eprint; /// /// eprint!("Error: Could not complete task").await; /// # /// # }) /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[macro_export] macro_rules! eprint { ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*))) } /// Prints to the standard error, with a newline. /// /// Equivalent to the [`println!`] macro, except that output goes to /// [`io::stderr`] instead of `io::stdout`. See [`println!`] for /// example usage. /// /// Use `eprintln!` only for error and progress messages. Use `println!` /// instead for the primary output of your program. /// /// [`io::stderr`]: io/struct.Stderr.html /// [`println!`]: macro.println.html /// /// # Panics /// /// Panics if writing to `io::stderr` fails. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::eprintln; /// /// eprintln!("Error: Could not complete task").await; /// # /// # }) /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[macro_export] macro_rules! eprintln { () => (async { $crate::eprint!("\n").await; }); ($($arg:tt)*) => ( async { $crate::io::_eprint(format_args!($($arg)*)).await; $crate::io::_eprint(format_args!("\n")).await; } ); } /// Declares task-local values. /// /// The macro wraps any number of static declarations and makes them task-local. Attributes and /// visibility modifiers are allowed. /// /// Each declared value is of the accessor type [`LocalKey`]. /// /// [`LocalKey`]: task/struct.LocalKey.html /// /// # Examples /// /// ``` /// # /// use std::cell::Cell; /// /// use async_std::prelude::*; /// use async_std::task; /// /// task_local! { /// static VAL: Cell = Cell::new(5); /// } /// /// task::block_on(async { /// let v = VAL.with(|c| c.get()); /// assert_eq!(v, 5); /// }); /// ``` #[cfg(feature = "default")] #[macro_export] macro_rules! task_local { () => (); ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( $(#[$attr])* $vis static $name: $crate::task::LocalKey<$t> = { #[inline] fn __init() -> $t { $init } $crate::task::LocalKey { __init, __key: ::std::sync::atomic::AtomicU32::new(0), } }; ); ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( $crate::task_local!($(#[$attr])* $vis static $name: $t = $init); $crate::task_local!($($rest)*); ); } async-rs-async-std-57f61ae/src/net/000077500000000000000000000000001476537407000171665ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/net/addr.rs000066400000000000000000000173271476537407000204600ustar00rootroot00000000000000use std::future::Future; use std::mem; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use std::pin::Pin; use crate::io; use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; use crate::utils::Context as ErrorContext; cfg_not_docs! { macro_rules! ret { (impl Future, $fut:ty) => ($fut); } } cfg_docs! { #[doc(hidden)] pub struct ImplFuture(std::marker::PhantomData); macro_rules! ret { (impl Future, $fut:ty) => (ImplFuture<$out>); } } /// Converts or resolves addresses to [`SocketAddr`] values. /// /// This trait is an async version of [`std::net::ToSocketAddrs`]. /// /// [`std::net::ToSocketAddrs`]: https://doc.rust-lang.org/std/net/trait.ToSocketAddrs.html /// [`SocketAddr`]: enum.SocketAddr.html /// /// # Examples /// /// ``` /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::ToSocketAddrs; /// /// let addr = "localhost:8080".to_socket_addrs().await?.next().unwrap(); /// println!("resolved: {:?}", addr); /// # /// # Ok(()) }) } /// ``` pub trait ToSocketAddrs { /// Returned iterator over socket addresses which this type may correspond to. type Iter: Iterator; /// Converts this object to an iterator of resolved `SocketAddr`s. /// /// The returned iterator may not actually yield any values depending on the outcome of any /// resolution performed. /// /// Note that this function may block a backend thread while resolution is performed. fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ); } #[doc(hidden)] #[allow(missing_debug_implementations)] pub enum ToSocketAddrsFuture { Resolving(JoinHandle>), Ready(io::Result), Done, } // The field of `Self::Resolving` is `Unpin`, and the field of `Self::Ready` is never pinned. impl Unpin for ToSocketAddrsFuture {} /// Wrap `std::io::Error` with additional message /// /// Keeps the original error kind and stores the original I/O error as `source`. impl ErrorContext for ToSocketAddrsFuture { fn context(self, message: impl Fn() -> String) -> Self { match self { ToSocketAddrsFuture::Ready(res) => ToSocketAddrsFuture::Ready(res.context(message)), x => x, } } } impl> Future for ToSocketAddrsFuture { type Output = io::Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.get_mut(); let state = mem::replace(this, ToSocketAddrsFuture::Done); match state { ToSocketAddrsFuture::Resolving(mut task) => { let poll = Pin::new(&mut task).poll(cx); if poll.is_pending() { *this = ToSocketAddrsFuture::Resolving(task); } poll } ToSocketAddrsFuture::Ready(res) => Poll::Ready(res), ToSocketAddrsFuture::Done => panic!("polled a completed future"), } } } impl ToSocketAddrs for SocketAddr { type Iter = std::option::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { ToSocketAddrsFuture::Ready(Ok(Some(*self).into_iter())) } } impl ToSocketAddrs for SocketAddrV4 { type Iter = std::option::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { SocketAddr::V4(*self) .to_socket_addrs() .context(|| format!("could not resolve address `{}`", self)) } } impl ToSocketAddrs for SocketAddrV6 { type Iter = std::option::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { SocketAddr::V6(*self) .to_socket_addrs() .context(|| format!("could not resolve address `{}`", self)) } } impl ToSocketAddrs for (IpAddr, u16) { type Iter = std::option::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { let (ip, port) = *self; match ip { IpAddr::V4(a) => (a, port).to_socket_addrs(), IpAddr::V6(a) => (a, port).to_socket_addrs(), } } } impl ToSocketAddrs for (Ipv4Addr, u16) { type Iter = std::option::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { let (ip, port) = *self; SocketAddrV4::new(ip, port).to_socket_addrs() } } impl ToSocketAddrs for (Ipv6Addr, u16) { type Iter = std::option::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { let (ip, port) = *self; SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs() } } impl ToSocketAddrs for (&str, u16) { type Iter = std::vec::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { let (host, port) = *self; if let Ok(addr) = host.parse::() { let addr = SocketAddrV4::new(addr, port); return ToSocketAddrsFuture::Ready(Ok(vec![SocketAddr::V4(addr)].into_iter())); } if let Ok(addr) = host.parse::() { let addr = SocketAddrV6::new(addr, port, 0, 0); return ToSocketAddrsFuture::Ready(Ok(vec![SocketAddr::V6(addr)].into_iter())); } let host = host.to_string(); let task = spawn_blocking(move || { let addr = (host.as_str(), port); std::net::ToSocketAddrs::to_socket_addrs(&addr) .context(|| format!("could not resolve address `{:?}`", addr)) }); ToSocketAddrsFuture::Resolving(task) } } impl ToSocketAddrs for str { type Iter = std::vec::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { if let Ok(addr) = self.parse() { return ToSocketAddrsFuture::Ready(Ok(vec![addr].into_iter())); } let addr = self.to_string(); let task = spawn_blocking(move || { std::net::ToSocketAddrs::to_socket_addrs(addr.as_str()) .context(|| format!("could not resolve address `{:?}`", addr)) }); ToSocketAddrsFuture::Resolving(task) } } impl<'a> ToSocketAddrs for &'a [SocketAddr] { type Iter = std::iter::Cloned>; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { ToSocketAddrsFuture::Ready(Ok(self.iter().cloned())) } } impl ToSocketAddrs for &T { type Iter = T::Iter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { (**self).to_socket_addrs() } } impl ToSocketAddrs for String { type Iter = std::vec::IntoIter; fn to_socket_addrs( &self, ) -> ret!( impl Future, ToSocketAddrsFuture ) { (&**self).to_socket_addrs() } } async-rs-async-std-57f61ae/src/net/mod.rs000066400000000000000000000052241476537407000203160ustar00rootroot00000000000000//! Networking primitives for TCP/UDP communication. //! //! This module provides networking functionality for the Transmission Control and User //! Datagram Protocols, as well as types for IP and socket addresses. //! //! This module is an async version of [`std::net`]. //! //! # Organization //! //! * [`TcpListener`] and [`TcpStream`] provide functionality for communication over TCP //! * [`UdpSocket`] provides functionality for communication over UDP //! * [`IpAddr`] represents IP addresses of either IPv4 or IPv6; [`Ipv4Addr`] and //! [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses //! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`] //! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses //! * [`ToSocketAddrs`] is a trait that used for generic address resolution when interacting //! with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`] //! * Other types are return or parameter types for various methods in this module //! //! [`IpAddr`]: enum.IpAddr.html //! [`Ipv4Addr`]: struct.Ipv4Addr.html //! [`Ipv6Addr`]: struct.Ipv6Addr.html //! [`SocketAddr`]: enum.SocketAddr.html //! [`SocketAddrV4`]: struct.SocketAddrV4.html //! [`SocketAddrV6`]: struct.SocketAddrV6.html //! [`TcpListener`]: struct.TcpListener.html //! [`TcpStream`]: struct.TcpStream.html //! [`ToSocketAddrs`]: trait.ToSocketAddrs.html //! [`UdpSocket`]: struct.UdpSocket.html //! //! # Platform-specific extensions //! //! APIs such as Unix domain sockets are available on certain platforms only. You can find //! platform-specific extensions in the [`async_std::os`] module. //! //! [`async_std::os`]: ../os/index.html //! [`std::net`]: https://doc.rust-lang.org/std/net/index.html //! //! # Examples //! //! A simple UDP echo server: //! //! ```no_run //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! use async_std::net::UdpSocket; //! //! let socket = UdpSocket::bind("127.0.0.1:8080").await?; //! let mut buf = vec![0u8; 1024]; //! //! loop { //! let (n, peer) = socket.recv_from(&mut buf).await?; //! socket.send_to(&buf[..n], &peer).await?; //! } //! # //! # }) } //! ``` pub use std::net::AddrParseError; pub use std::net::Shutdown; pub use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; pub use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; #[cfg(not(target_os = "unknown"))] pub use addr::ToSocketAddrs; #[cfg(not(target_os = "unknown"))] pub use tcp::{Incoming, TcpListener, TcpStream}; #[cfg(not(target_os = "unknown"))] pub use udp::UdpSocket; #[cfg(not(target_os = "unknown"))] mod addr; #[cfg(not(target_os = "unknown"))] mod tcp; #[cfg(not(target_os = "unknown"))] mod udp; async-rs-async-std-57f61ae/src/net/tcp/000077500000000000000000000000001476537407000177545ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/net/tcp/listener.rs000066400000000000000000000256351476537407000221620ustar00rootroot00000000000000use std::fmt; use std::net::SocketAddr; use std::net::TcpStream as StdTcpStream; use std::pin::Pin; use async_io::Async; use crate::io; use crate::net::{TcpStream, ToSocketAddrs}; use crate::stream::Stream; use crate::sync::Arc; use crate::task::{ready, Context, Poll}; /// A TCP socket server, listening for connections. /// /// After creating a `TcpListener` by [`bind`]ing it to a socket address, it listens for incoming /// TCP connections. These can be accepted by awaiting elements from the async stream of /// [`incoming`] connections. /// /// The socket will be closed when the value is dropped. /// /// The Transmission Control Protocol is specified in [IETF RFC 793]. /// /// This type is an async version of [`std::net::TcpListener`]. /// /// [`bind`]: #method.bind /// [`incoming`]: #method.incoming /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 /// [`std::net::TcpListener`]: https://doc.rust-lang.org/std/net/struct.TcpListener.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; /// use async_std::net::TcpListener; /// use async_std::prelude::*; /// /// let listener = TcpListener::bind("127.0.0.1:8080").await?; /// let mut incoming = listener.incoming(); /// /// while let Some(stream) = incoming.next().await { /// let stream = stream?; /// let (reader, writer) = &mut (&stream, &stream); /// io::copy(reader, writer).await?; /// } /// # /// # Ok(()) }) } /// ``` #[derive(Debug)] pub struct TcpListener { watcher: Async, } impl TcpListener { /// Creates a new `TcpListener` which will be bound to the specified address. /// /// The returned listener is ready for accepting connections. /// /// Binding with a port number of 0 will request that the OS assigns a port to this listener. /// The port allocated can be queried via the [`local_addr`] method. /// /// # Examples /// Create a TCP listener bound to 127.0.0.1:0: /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpListener; /// /// let listener = TcpListener::bind("127.0.0.1:0").await?; /// # /// # Ok(()) }) } /// ``` /// /// [`local_addr`]: #method.local_addr pub async fn bind(addrs: A) -> io::Result { let mut last_err = None; let addrs = addrs.to_socket_addrs().await?; for addr in addrs { match Async::::bind(addr) { Ok(listener) => { return Ok(TcpListener { watcher: listener }); } Err(err) => last_err = Some(err), } } Err(last_err.unwrap_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, "could not resolve to any addresses", ) })) } /// Accepts a new incoming connection to this listener. /// /// When a connection is established, the corresponding stream and address will be returned. /// /// ## Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpListener; /// /// let listener = TcpListener::bind("127.0.0.1:0").await?; /// let (stream, addr) = listener.accept().await?; /// # /// # Ok(()) }) } /// ``` pub async fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { let (stream, addr) = self.watcher.accept().await?; let stream = TcpStream { watcher: Arc::new(stream), }; Ok((stream, addr)) } /// Returns a stream of incoming connections. /// /// Iterating over this stream is equivalent to calling [`accept`] in a loop. The stream of /// connections is infinite, i.e awaiting the next connection will never result in [`None`]. /// /// [`accept`]: #method.accept /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// /// ## Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpListener; /// use async_std::prelude::*; /// /// let listener = TcpListener::bind("127.0.0.1:0").await?; /// let mut incoming = listener.incoming(); /// /// while let Some(stream) = incoming.next().await { /// let mut stream = stream?; /// stream.write_all(b"hello world").await?; /// } /// # /// # Ok(()) }) } /// ``` pub fn incoming(&self) -> Incoming<'_> { Incoming { incoming: Box::pin(self.watcher.incoming()), } } /// Turn this into a stream over the connections being received on this /// listener. /// /// The returned stream is infinite and will also not yield /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to /// calling [`TcpListener::accept`] in a loop. /// /// ## Examples /// /// Merge the incoming connections of multiple sockets into one [`Stream`]: /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpListener; /// /// // Our server listens on multiple ports for some reason /// let listeners = vec![ /// TcpListener::bind("[::0]:8080").await?, /// TcpListener::bind("[::0]:12345").await?, /// TcpListener::bind("[::0]:5678").await?, /// ]; /// // Iterate over all incoming connections /// let incoming = futures::stream::select_all( /// listeners.into_iter() /// .map(TcpListener::into_incoming) /// .map(Box::pin) /// ); /// # /// # Ok(()) }) } /// ``` #[cfg(feature = "unstable")] pub fn into_incoming(self) -> impl Stream> + Send { futures_lite::stream::unfold(self, |listener| async move { let res = listener.accept().await.map(|(stream, _)| stream); Some((res, listener)) }) } /// Returns the local address that this listener is bound to. /// /// This can be useful, for example, to identify when binding to port 0 which port was assigned /// by the OS. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpListener; /// /// let listener = TcpListener::bind("127.0.0.1:8080").await?; /// let addr = listener.local_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn local_addr(&self) -> io::Result { self.watcher.get_ref().local_addr() } } /// A stream of incoming TCP connections. /// /// This stream is infinite, i.e awaiting the next connection will never result in [`None`]. It is /// created by the [`incoming`] method on [`TcpListener`]. /// /// This type is an async version of [`std::net::Incoming`]. /// /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// [`incoming`]: struct.TcpListener.html#method.incoming /// [`TcpListener`]: struct.TcpListener.html /// [`std::net::Incoming`]: https://doc.rust-lang.org/std/net/struct.Incoming.html pub struct Incoming<'a> { incoming: Pin>> + Send + Sync + 'a>>, } impl Stream for Incoming<'_> { type Item = io::Result; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let res = ready!(Pin::new(&mut self.incoming).poll_next(cx)); Poll::Ready(res.map(|res| res.map(|stream| TcpStream { watcher: Arc::new(stream) }))) } } impl fmt::Debug for Incoming<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Incoming {{ ... }}") } } impl From for TcpListener { /// Converts a `std::net::TcpListener` into its asynchronous equivalent. fn from(listener: std::net::TcpListener) -> TcpListener { TcpListener { watcher: Async::new(listener).expect("TcpListener is known to be good"), } } } impl std::convert::TryFrom for std::net::TcpListener { type Error = io::Error; /// Converts a `TcpListener` into its synchronous equivalent. fn try_from(listener: TcpListener) -> io::Result { let inner = listener.watcher.into_inner()?; inner.set_nonblocking(false)?; Ok(inner) } } cfg_unix! { use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; impl AsRawFd for TcpListener { fn as_raw_fd(&self) -> RawFd { self.watcher.get_ref().as_raw_fd() } } impl FromRawFd for TcpListener { unsafe fn from_raw_fd(fd: RawFd) -> TcpListener { std::net::TcpListener::from_raw_fd(fd).into() } } impl IntoRawFd for TcpListener { fn into_raw_fd(self) -> RawFd { self.watcher.into_inner().unwrap().into_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; impl AsFd for TcpListener { fn as_fd(&self) -> BorrowedFd<'_> { self.watcher.get_ref().as_fd() } } impl From for TcpListener { fn from(fd: OwnedFd) -> TcpListener { std::net::TcpListener::from(fd).into() } } impl From for OwnedFd { fn from(listener: TcpListener) -> OwnedFd { listener.watcher.into_inner().unwrap().into() } } } } cfg_windows! { use crate::os::windows::io::{ AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket, }; impl AsRawSocket for TcpListener { fn as_raw_socket(&self) -> RawSocket { self.watcher.as_raw_socket() } } impl FromRawSocket for TcpListener { unsafe fn from_raw_socket(handle: RawSocket) -> TcpListener { std::net::TcpListener::from_raw_socket(handle).into() } } impl IntoRawSocket for TcpListener { fn into_raw_socket(self) -> RawSocket { self.watcher.into_inner().unwrap().into_raw_socket() } } cfg_io_safety! { use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket}; impl AsSocket for TcpListener { fn as_socket(&self) -> BorrowedSocket<'_> { self.watcher.get_ref().as_socket() } } impl From for TcpListener { fn from(fd: OwnedSocket) -> TcpListener { std::net::TcpListener::from(fd).into() } } impl From for OwnedSocket { fn from(listener: TcpListener) -> OwnedSocket { listener.watcher.into_inner().unwrap().into() } } } } async-rs-async-std-57f61ae/src/net/tcp/mod.rs000066400000000000000000000001411476537407000210750ustar00rootroot00000000000000pub use listener::{Incoming, TcpListener}; pub use stream::TcpStream; mod listener; mod stream; async-rs-async-std-57f61ae/src/net/tcp/stream.rs000066400000000000000000000353771476537407000216340ustar00rootroot00000000000000use std::io::{IoSlice, IoSliceMut}; use std::net::SocketAddr; use std::pin::Pin; use async_io::Async; use crate::io::{self, Read, Write}; use crate::net::ToSocketAddrs; use crate::sync::Arc; use crate::task::{Context, Poll}; /// A TCP stream between a local and a remote socket. /// /// A `TcpStream` can either be created by connecting to an endpoint, via the [`connect`] method, /// or by [accepting] a connection from a [listener]. It can be read or written to using the /// [`AsyncRead`], [`AsyncWrite`], and related extension traits in [`futures::io`]. /// /// The connection will be closed when the value is dropped. The reading and writing portions of /// the connection can also be shut down individually with the [`shutdown`] method. /// /// This type is an async version of [`std::net::TcpStream`]. /// /// [`connect`]: struct.TcpStream.html#method.connect /// [accepting]: struct.TcpListener.html#method.accept /// [listener]: struct.TcpListener.html /// [`AsyncRead`]: https://docs.rs/futures/0.3/futures/io/trait.AsyncRead.html /// [`AsyncWrite`]: https://docs.rs/futures/0.3/futures/io/trait.AsyncWrite.html /// [`futures::io`]: https://docs.rs/futures/0.3/futures/io/index.html /// [`shutdown`]: struct.TcpStream.html#method.shutdown /// [`std::net::TcpStream`]: https://doc.rust-lang.org/std/net/struct.TcpStream.html /// /// ## Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// use async_std::prelude::*; /// /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; /// stream.write_all(b"hello world").await?; /// /// let mut buf = vec![0u8; 1024]; /// let n = stream.read(&mut buf).await?; /// # /// # Ok(()) }) } /// ``` #[derive(Debug, Clone)] pub struct TcpStream { pub(super) watcher: Arc>, } impl TcpStream { /// Creates a new TCP stream connected to the specified address. /// /// This method will create a new TCP socket and attempt to connect it to the `addr` /// provided. The [returned future] will be resolved once the stream has successfully /// connected, or it will return an error if one occurs. /// /// [returned future]: struct.Connect.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:0").await?; /// # /// # Ok(()) }) } /// ``` pub async fn connect(addrs: A) -> io::Result { let mut last_err = None; let addrs = addrs.to_socket_addrs().await?; for addr in addrs { match Async::::connect(addr).await { Ok(stream) => { return Ok(TcpStream { watcher: Arc::new(stream), }); } Err(e) => { last_err = Some(e); continue; } } } Err(last_err.unwrap_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, "could not resolve to any addresses", ) })) } /// Returns the local address that this stream is connected to. /// /// ## Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8080").await?; /// let addr = stream.local_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn local_addr(&self) -> io::Result { self.watcher.get_ref().local_addr() } /// Returns the remote address that this stream is connected to. /// /// ## Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8080").await?; /// let peer = stream.peer_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn peer_addr(&self) -> io::Result { self.watcher.get_ref().peer_addr() } /// Gets the value of the `IP_TTL` option for this socket. /// /// For more information about this option, see [`set_ttl`]. /// /// [`set_ttl`]: #method.set_ttl /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8080").await?; /// /// stream.set_ttl(100)?; /// assert_eq!(stream.ttl()?, 100); /// # /// # Ok(()) }) } /// ``` pub fn ttl(&self) -> io::Result { self.watcher.get_ref().ttl() } /// Sets the value for the `IP_TTL` option on this socket. /// /// This value sets the time-to-live field that is used in every packet sent /// from this socket. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8080").await?; /// /// stream.set_ttl(100)?; /// assert_eq!(stream.ttl()?, 100); /// # /// # Ok(()) }) } /// ``` pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { self.watcher.get_ref().set_ttl(ttl) } /// Receives data on the socket from the remote address to which it is connected, without /// removing that data from the queue. /// /// On success, returns the number of bytes peeked. /// /// Successive calls return the same data. This is accomplished by passing `MSG_PEEK` as a flag /// to the underlying `recv` system call. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8000").await?; /// /// let mut buf = vec![0; 1024]; /// let n = stream.peek(&mut buf).await?; /// # /// # Ok(()) }) } /// ``` pub async fn peek(&self, buf: &mut [u8]) -> io::Result { self.watcher.peek(buf).await } /// Gets the value of the `TCP_NODELAY` option on this socket. /// /// For more information about this option, see [`set_nodelay`]. /// /// [`set_nodelay`]: #method.set_nodelay /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8080").await?; /// /// stream.set_nodelay(true)?; /// assert_eq!(stream.nodelay()?, true); /// # /// # Ok(()) }) } /// ``` pub fn nodelay(&self) -> io::Result { self.watcher.get_ref().nodelay() } /// Sets the value of the `TCP_NODELAY` option on this socket. /// /// If set, this option disables the Nagle algorithm. This means that /// segments are always sent as soon as possible, even if there is only a /// small amount of data. When not set, data is buffered until there is a /// sufficient amount to send out, thereby avoiding the frequent sending of /// small packets. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8080").await?; /// /// stream.set_nodelay(true)?; /// assert_eq!(stream.nodelay()?, true); /// # /// # Ok(()) }) } /// ``` pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { self.watcher.get_ref().set_nodelay(nodelay) } /// Shuts down the read, write, or both halves of this connection. /// /// This method will cause all pending and future I/O on the specified portions to return /// immediately with an appropriate value (see the documentation of [`Shutdown`]). /// /// [`Shutdown`]: https://doc.rust-lang.org/std/net/enum.Shutdown.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use std::net::Shutdown; /// /// use async_std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8080").await?; /// stream.shutdown(Shutdown::Both)?; /// # /// # Ok(()) }) } /// ``` pub fn shutdown(&self, how: std::net::Shutdown) -> std::io::Result<()> { self.watcher.get_ref().shutdown(how) } } impl Read for TcpStream { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { Pin::new(&mut &*self).poll_read(cx, buf) } fn poll_read_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>], ) -> Poll> { Pin::new(&mut &*self).poll_read_vectored(cx, bufs) } } impl Read for &TcpStream { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { Pin::new(&mut &*self.watcher).poll_read(cx, buf) } fn poll_read_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>], ) -> Poll> { Pin::new(&mut &*self.watcher).poll_read_vectored(cx, bufs) } } impl Write for TcpStream { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { Pin::new(&mut &*self).poll_write(cx, buf) } fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll> { Pin::new(&mut &*self).poll_write_vectored(cx, bufs) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self).poll_flush(cx) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self).poll_close(cx) } } impl Write for &TcpStream { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { Pin::new(&mut &*self.watcher).poll_write(cx, buf) } fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll> { Pin::new(&mut &*self.watcher).poll_write_vectored(cx, bufs) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self.watcher).poll_flush(cx) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self.watcher).poll_close(cx) } } impl From for TcpStream { /// Converts a `std::net::TcpStream` into its asynchronous equivalent. fn from(stream: std::net::TcpStream) -> TcpStream { TcpStream { watcher: Arc::new(Async::new(stream).expect("TcpStream is known to be good")), } } } impl std::convert::TryFrom for std::net::TcpStream { type Error = io::Error; /// Converts a `TcpStream` into its synchronous equivalent. fn try_from(stream: TcpStream) -> io::Result { let inner = Arc::try_unwrap(stream.watcher) .map_err(|_| io::Error::new( io::ErrorKind::Other, "Cannot convert TcpStream to synchronous: multiple references", ))? .into_inner()?; inner.set_nonblocking(false)?; Ok(inner) } } cfg_unix! { use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; impl AsRawFd for TcpStream { fn as_raw_fd(&self) -> RawFd { self.watcher.get_ref().as_raw_fd() } } impl FromRawFd for TcpStream { unsafe fn from_raw_fd(fd: RawFd) -> TcpStream { std::net::TcpStream::from_raw_fd(fd).into() } } impl IntoRawFd for TcpStream { fn into_raw_fd(self) -> RawFd { // TODO(stjepang): This does not mean `RawFd` is now the sole owner of the file // descriptor because it's possible that there are other clones of this `TcpStream` // using it at the same time. We should probably document that behavior. self.as_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; impl AsFd for TcpStream { fn as_fd(&self) -> BorrowedFd<'_> { self.watcher.get_ref().as_fd() } } impl From for TcpStream { fn from(fd: OwnedFd) -> TcpStream { std::net::TcpStream::from(fd).into() } } impl From for OwnedFd { fn from(stream: TcpStream) -> OwnedFd { stream.watcher.get_ref().try_clone().unwrap().into() } } } } cfg_windows! { use crate::os::windows::io::{ RawSocket, AsRawSocket, FromRawSocket, IntoRawSocket }; impl AsRawSocket for TcpStream { fn as_raw_socket(&self) -> RawSocket { self.watcher.get_ref().as_raw_socket() } } impl FromRawSocket for TcpStream { unsafe fn from_raw_socket(handle: RawSocket) -> TcpStream { std::net::TcpStream::from_raw_socket(handle).into() } } impl IntoRawSocket for TcpStream { fn into_raw_socket(self) -> RawSocket { // TODO(stjepang): This does not mean `RawFd` is now the sole owner of the file // descriptor because it's possible that there are other clones of this `TcpStream` // using it at the same time. We should probably document that behavior. self.as_raw_socket() } } cfg_io_safety! { use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket}; impl AsSocket for TcpStream { fn as_socket(&self) -> BorrowedSocket<'_> { self.watcher.get_ref().as_socket() } } impl From for TcpStream { fn from(fd: OwnedSocket) -> TcpStream { std::net::TcpStream::from(fd).into() } } impl From for OwnedSocket { fn from(stream: TcpStream) -> OwnedSocket { stream.watcher.get_ref().try_clone().unwrap().into() } } } } async-rs-async-std-57f61ae/src/net/udp/000077500000000000000000000000001476537407000177565ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/net/udp/mod.rs000066400000000000000000000476461476537407000211240ustar00rootroot00000000000000use std::io; use std::net::SocketAddr; use std::net::{Ipv4Addr, Ipv6Addr}; use async_io::Async; use crate::net::ToSocketAddrs; use crate::utils::Context as _; /// A UDP socket. /// /// After creating a `UdpSocket` by [`bind`]ing it to a socket address, data can be [sent to] and /// [received from] any other socket address. /// /// As stated in the User Datagram Protocol's specification in [IETF RFC 768], UDP is an unordered, /// unreliable protocol. Refer to [`TcpListener`] and [`TcpStream`] for async TCP primitives. /// /// This type is an async version of [`std::net::UdpSocket`]. /// /// [`bind`]: #method.bind /// [received from]: #method.recv_from /// [sent to]: #method.send_to /// [`TcpListener`]: struct.TcpListener.html /// [`TcpStream`]: struct.TcpStream.html /// [`std::net`]: https://doc.rust-lang.org/std/net/index.html /// [IETF RFC 768]: https://tools.ietf.org/html/rfc768 /// [`std::net::UdpSocket`]: https://doc.rust-lang.org/std/net/struct.UdpSocket.html /// /// ## Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:8080").await?; /// let mut buf = vec![0u8; 1024]; /// /// loop { /// let (n, peer) = socket.recv_from(&mut buf).await?; /// socket.send_to(&buf[..n], &peer).await?; /// } /// # /// # }) } /// ``` #[derive(Debug)] pub struct UdpSocket { watcher: Async, } impl UdpSocket { /// Creates a UDP socket from the given address. /// /// Binding with a port number of 0 will request that the OS assigns a port to this socket. The /// port allocated can be queried via the [`local_addr`] method. /// /// [`local_addr`]: #method.local_addr /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// # /// # Ok(()) }) } /// ``` pub async fn bind(addrs: A) -> io::Result { let mut last_err = None; let addrs = addrs.to_socket_addrs().await?; for addr in addrs { match Async::::bind(addr) { Ok(socket) => { return Ok(UdpSocket { watcher: socket }); } Err(err) => last_err = Some(err), } } Err(last_err.unwrap_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, "could not resolve to any addresses", ) })) } /// Returns the peer address that this listener is connected to. /// /// This can be useful, for example, when connect to port 0 to figure out which port was /// actually connected. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket1 = UdpSocket::bind("127.0.0.1:0").await?; /// let socket2 = UdpSocket::bind("127.0.0.1:0").await?; /// socket1.connect(socket2.local_addr()?).await?; /// let addr = socket1.peer_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn peer_addr(&self) -> io::Result { self.watcher .get_ref() .peer_addr() .context(|| String::from("could not get peer address")) } /// Returns the local address that this listener is bound to. /// /// This can be useful, for example, when binding to port 0 to figure out which port was /// actually bound. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// let addr = socket.local_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn local_addr(&self) -> io::Result { self.watcher .get_ref() .local_addr() .context(|| String::from("could not get local address")) } /// Sends data on the socket to the given address. /// /// On success, returns the number of bytes written. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// const THE_MERCHANT_OF_VENICE: &[u8] = b" /// If you prick us, do we not bleed? /// If you tickle us, do we not laugh? /// If you poison us, do we not die? /// And if you wrong us, shall we not revenge? /// "; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// /// let addr = "127.0.0.1:7878"; /// let sent = socket.send_to(THE_MERCHANT_OF_VENICE, &addr).await?; /// println!("Sent {} bytes to {}", sent, addr); /// # /// # Ok(()) }) } /// ``` pub async fn send_to(&self, buf: &[u8], addrs: A) -> io::Result { let addr = match addrs.to_socket_addrs().await?.next() { Some(addr) => addr, None => { return Err(io::Error::new( io::ErrorKind::InvalidInput, "no addresses to send data to", )); } }; self.watcher .send_to(buf, addr) .await .context(|| format!("could not send packet to {}", addr)) } /// Receives data from the socket. /// /// On success, returns the number of bytes read and the origin. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// /// let mut buf = vec![0; 1024]; /// let (n, peer) = socket.recv_from(&mut buf).await?; /// println!("Received {} bytes from {}", n, peer); /// # /// # Ok(()) }) } /// ``` pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.watcher.recv_from(buf).await } /// Receives data from socket without removing it from the queue. /// /// On success, returns the number of bytes peeked and the origin. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// /// let mut buf = vec![0; 1024]; /// let (n, peer) = socket.peek_from(&mut buf).await?; /// println!("Peeked {} bytes from {}", n, peer); /// # /// # Ok (()) }) } /// ``` pub async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.watcher.peek_from(buf).await } /// Connects the UDP socket to a remote address. /// /// When connected, methods [`send`] and [`recv`] will use the specified address for sending /// and receiving messages. Additionally, a filter will be applied to [`recv_from`] so that it /// only receives messages from that same address. /// /// [`send`]: #method.send /// [`recv`]: #method.recv /// [`recv_from`]: #method.recv_from /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// socket.connect("127.0.0.1:8080").await?; /// # /// # Ok(()) }) } /// ``` pub async fn connect(&self, addrs: A) -> io::Result<()> { let mut last_err = None; let addrs = addrs .to_socket_addrs() .await .context(|| String::from("could not resolve addresses"))?; for addr in addrs { // TODO(stjepang): connect on the blocking pool match self.watcher.get_ref().connect(addr) { Ok(()) => return Ok(()), Err(err) => last_err = Some(err), } } Err(last_err.unwrap_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, "could not resolve to any addresses", ) })) } /// Sends data on the socket to the remote address to which it is connected. /// /// The [`connect`] method will connect this socket to a remote address. /// This method will fail if the socket is not connected. /// /// [`connect`]: #method.connect /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:34254").await?; /// socket.connect("127.0.0.1:8080").await?; /// let bytes = socket.send(b"Hi there!").await?; /// /// println!("Sent {} bytes", bytes); /// # /// # Ok(()) }) } /// ``` pub async fn send(&self, buf: &[u8]) -> io::Result { self.watcher.send(buf).await } /// Receives data from the socket. /// /// On success, returns the number of bytes read. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// socket.connect("127.0.0.1:8080").await?; /// /// let mut buf = vec![0; 1024]; /// let n = socket.recv(&mut buf).await?; /// println!("Received {} bytes", n); /// # /// # Ok(()) }) } /// ``` pub async fn recv(&self, buf: &mut [u8]) -> io::Result { self.watcher.recv(buf).await } /// Receives data from the socket without removing it from the queue. /// /// On success, returns the number of bytes peeked. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// socket.connect("127.0.0.1:8080").await?; /// /// let mut buf = vec![0; 1024]; /// let n = socket.peek(&mut buf).await?; /// println!("Peeked {} bytes", n); /// # /// # Ok(()) }) } /// ``` pub async fn peek(&self, buf: &mut [u8]) -> io::Result { self.watcher.peek(buf).await } /// Gets the value of the `SO_BROADCAST` option for this socket. /// /// For more information about this option, see [`set_broadcast`]. /// /// [`set_broadcast`]: #method.set_broadcast pub fn broadcast(&self) -> io::Result { self.watcher.get_ref().broadcast() } /// Sets the value of the `SO_BROADCAST` option for this socket. /// /// When enabled, this socket is allowed to send packets to a broadcast address. pub fn set_broadcast(&self, on: bool) -> io::Result<()> { self.watcher.get_ref().set_broadcast(on) } /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket. /// /// For more information about this option, see [`set_multicast_loop_v4`]. /// /// [`set_multicast_loop_v4`]: #method.set_multicast_loop_v4 pub fn multicast_loop_v4(&self) -> io::Result { self.watcher.get_ref().multicast_loop_v4() } /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket. /// /// If enabled, multicast packets will be looped back to the local socket. /// /// # Note /// /// This may not have any affect on IPv6 sockets. pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> { self.watcher.get_ref().set_multicast_loop_v4(on) } /// Gets the value of the `IP_MULTICAST_TTL` option for this socket. /// /// For more information about this option, see [`set_multicast_ttl_v4`]. /// /// [`set_multicast_ttl_v4`]: #method.set_multicast_ttl_v4 pub fn multicast_ttl_v4(&self) -> io::Result { self.watcher.get_ref().multicast_ttl_v4() } /// Sets the value of the `IP_MULTICAST_TTL` option for this socket. /// /// Indicates the time-to-live value of outgoing multicast packets for this socket. The default /// value is 1 which means that multicast packets don't leave the local network unless /// explicitly requested. /// /// # Note /// /// This may not have any affect on IPv6 sockets. pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> { self.watcher.get_ref().set_multicast_ttl_v4(ttl) } /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket. /// /// For more information about this option, see [`set_multicast_loop_v6`]. /// /// [`set_multicast_loop_v6`]: #method.set_multicast_loop_v6 pub fn multicast_loop_v6(&self) -> io::Result { self.watcher.get_ref().multicast_loop_v6() } /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket. /// /// Controls whether this socket sees the multicast packets it sends itself. /// /// # Note /// /// This may not have any affect on IPv4 sockets. pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> { self.watcher.get_ref().set_multicast_loop_v6(on) } /// Gets the value of the `IP_TTL` option for this socket. /// /// For more information about this option, see [`set_ttl`]. /// /// [`set_ttl`]: #method.set_ttl pub fn ttl(&self) -> io::Result { self.watcher.get_ref().ttl() } /// Sets the value for the `IP_TTL` option on this socket. /// /// This value sets the time-to-live field that is used in every packet sent /// from this socket. pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { self.watcher.get_ref().set_ttl(ttl) } /// Executes an operation of the `IP_ADD_MEMBERSHIP` type. /// /// This method specifies a new multicast group for this socket to join. The address must be /// a valid multicast address, and `interface` is the address of the local interface with which /// the system should join the multicast group. If it's equal to `INADDR_ANY` then an /// appropriate interface is chosen by the system. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use std::net::Ipv4Addr; /// /// use async_std::net::UdpSocket; /// /// let interface = Ipv4Addr::new(0, 0, 0, 0); /// let mdns_addr = Ipv4Addr::new(224, 0, 0, 123); /// /// let socket = UdpSocket::bind("127.0.0.1:0").await?; /// socket.join_multicast_v4(mdns_addr, interface)?; /// # /// # Ok(()) }) } /// ``` pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> { self.watcher .get_ref() .join_multicast_v4(&multiaddr, &interface) } /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type. /// /// This method specifies a new multicast group for this socket to join. The address must be /// a valid multicast address, and `interface` is the index of the interface to join/leave (or /// 0 to indicate any interface). /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use std::net::{Ipv6Addr, SocketAddr}; /// /// use async_std::net::UdpSocket; /// /// let socket_addr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into(), 0); /// let mdns_addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x0123); /// let socket = UdpSocket::bind(&socket_addr).await?; /// /// socket.join_multicast_v6(&mdns_addr, 0)?; /// # /// # Ok(()) }) } /// ``` pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { self.watcher .get_ref() .join_multicast_v6(multiaddr, interface) } /// Executes an operation of the `IP_DROP_MEMBERSHIP` type. /// /// For more information about this option, see [`join_multicast_v4`]. /// /// [`join_multicast_v4`]: #method.join_multicast_v4 pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> { self.watcher .get_ref() .leave_multicast_v4(&multiaddr, &interface) } /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type. /// /// For more information about this option, see [`join_multicast_v6`]. /// /// [`join_multicast_v6`]: #method.join_multicast_v6 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { self.watcher .get_ref() .leave_multicast_v6(multiaddr, interface) } } impl From for UdpSocket { /// Converts a `std::net::UdpSocket` into its asynchronous equivalent. fn from(socket: std::net::UdpSocket) -> UdpSocket { UdpSocket { watcher: Async::new(socket).expect("UdpSocket is known to be good"), } } } impl std::convert::TryFrom for std::net::UdpSocket { type Error = io::Error; /// Converts a `UdpSocket` into its synchronous equivalent. fn try_from(listener: UdpSocket) -> io::Result { let inner = listener.watcher.into_inner()?; inner.set_nonblocking(false)?; Ok(inner) } } cfg_unix! { use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; impl AsRawFd for UdpSocket { fn as_raw_fd(&self) -> RawFd { self.watcher.get_ref().as_raw_fd() } } impl FromRawFd for UdpSocket { unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket { std::net::UdpSocket::from_raw_fd(fd).into() } } impl IntoRawFd for UdpSocket { fn into_raw_fd(self) -> RawFd { self.watcher.into_inner().unwrap().into_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; impl AsFd for UdpSocket { fn as_fd(&self) -> BorrowedFd<'_> { self.watcher.get_ref().as_fd() } } impl From for UdpSocket { fn from(fd: OwnedFd) -> UdpSocket { std::net::UdpSocket::from(fd).into() } } impl From for OwnedFd { fn from(stream: UdpSocket) -> OwnedFd { stream.watcher.into_inner().unwrap().into() } } } } cfg_windows! { use crate::os::windows::io::{ RawSocket, AsRawSocket, IntoRawSocket, FromRawSocket }; impl AsRawSocket for UdpSocket { fn as_raw_socket(&self) -> RawSocket { self.watcher.get_ref().as_raw_socket() } } impl FromRawSocket for UdpSocket { unsafe fn from_raw_socket(handle: RawSocket) -> UdpSocket { std::net::UdpSocket::from_raw_socket(handle).into() } } impl IntoRawSocket for UdpSocket { fn into_raw_socket(self) -> RawSocket { self.watcher.into_inner().unwrap().into_raw_socket() } } cfg_io_safety! { use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket}; impl AsSocket for UdpSocket { fn as_socket(&self) -> BorrowedSocket<'_> { self.watcher.get_ref().as_socket() } } impl From for UdpSocket { fn from(fd: OwnedSocket) -> UdpSocket { std::net::UdpSocket::from(fd).into() } } impl From for OwnedSocket { fn from(stream: UdpSocket) -> OwnedSocket { stream.watcher.into_inner().unwrap().into() } } } } async-rs-async-std-57f61ae/src/option/000077500000000000000000000000001476537407000177105ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/option/from_stream.rs000066400000000000000000000024341476537407000225770ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{FromStream, IntoStream}; use std::convert::identity; impl FromStream> for Option where V: FromStream, { /// Takes each element in the stream: if it is `None`, no further /// elements are taken, and `None` is returned. Should no `None` /// occur, a container with the values of each `Option` is returned. #[inline] fn from_stream<'a, S: IntoStream> + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { // Using `take_while` here because it is able to stop the stream early // if a failure occurs let mut found_none = false; let out: V = stream .take_while(|elem| { elem.is_some() || { found_none = true; // Stop processing the stream on `None` false } }) .filter_map(identity) .collect() .await; if found_none { None } else { Some(out) } }) } } async-rs-async-std-57f61ae/src/option/mod.rs000066400000000000000000000004141476537407000210340ustar00rootroot00000000000000//! The Rust core optional value type //! //! This module provides the `Option` type for returning and //! propagating optional values. mod from_stream; #[allow(unused)] #[doc(inline)] pub use std::option::Option; cfg_unstable! { mod product; mod sum; } async-rs-async-std-57f61ae/src/option/product.rs000066400000000000000000000034261476537407000217430ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{Product, Stream}; use std::convert::identity; impl Product> for Option where T: Product, { #[doc = r#" Takes each element in the `Stream`: if it is a `None`, no further elements are taken, and the `None` is returned. Should no `None` occur, the product of all elements is returned. # Examples This multiplies every integer in a vector, rejecting the product if a negative element is encountered: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let v = stream::from_iter(vec![1, 2, 4]); let prod: Option = v.map(|x| if x < 0 { None } else { Some(x) }).product().await; assert_eq!(prod, Some(8)); # # }) } ``` "#] fn product<'a, S>(stream: S) -> Pin> + 'a>> where S: Stream> + 'a, { Box::pin(async move { // Using `take_while` here because it is able to stop the stream early // if a failure occurs let mut found_none = false; let out = >::product( stream .take_while(|elem| { elem.is_some() || { found_none = true; // Stop processing the stream on `None` false } }) .filter_map(identity), ) .await; if found_none { None } else { Some(out) } }) } } async-rs-async-std-57f61ae/src/option/sum.rs000066400000000000000000000033441476537407000210660ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{Stream, Sum}; use std::convert::identity; impl Sum> for Option where T: Sum, { #[doc = r#" Takes each element in the `Iterator`: if it is a `None`, no further elements are taken, and the `None` is returned. Should no `None` occur, the sum of all elements is returned. # Examples This sums up the position of the character 'a' in a vector of strings, if a word did not have the character 'a' the operation returns `None`: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let words = stream::from_iter(vec!["have", "a", "great", "day"]); let total: Option = words.map(|w| w.find('a')).sum().await; assert_eq!(total, Some(5)); # # }) } ``` "#] fn sum<'a, S>(stream: S) -> Pin> + 'a>> where S: Stream> + 'a, { Box::pin(async move { // Using `take_while` here because it is able to stop the stream early // if a failure occurs let mut found_none = false; let out = >::sum( stream .take_while(|elem| { elem.is_some() || { found_none = true; // Stop processing the stream on `None` false } }) .filter_map(identity), ) .await; if found_none { None } else { Some(out) } }) } } async-rs-async-std-57f61ae/src/os/000077500000000000000000000000001476537407000170215ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/os/mod.rs000066400000000000000000000001441476537407000201450ustar00rootroot00000000000000//! OS-specific extensions. cfg_unix! { pub mod unix; } cfg_windows! { pub mod windows; } async-rs-async-std-57f61ae/src/os/unix/000077500000000000000000000000001476537407000200045ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/os/unix/fs.rs000066400000000000000000000047201476537407000207650ustar00rootroot00000000000000//! Unix-specific filesystem extensions. use crate::io; use crate::path::Path; use crate::task::spawn_blocking; /// Creates a new symbolic link on the filesystem. /// /// The `dst` path will be a symbolic link pointing to the `src` path. /// /// This function is an async version of [`std::os::unix::fs::symlink`]. /// /// [`std::os::unix::fs::symlink`]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::fs::symlink; /// /// symlink("a.txt", "b.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { let src = src.as_ref().to_owned(); let dst = dst.as_ref().to_owned(); spawn_blocking(move || std::os::unix::fs::symlink(&src, &dst)).await } cfg_not_docs! { pub use std::os::unix::fs::{DirBuilderExt, DirEntryExt, OpenOptionsExt}; } cfg_docs! { /// Unix-specific extensions to `DirBuilder`. pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// `0o777`. fn mode(&mut self, mode: u32) -> &mut Self; } /// Unix-specific extension methods for `DirEntry`. pub trait DirEntryExt { /// Returns the underlying `d_ino` field in the contained `dirent` /// structure. fn ino(&self) -> u64; } /// Unix-specific extensions to `OpenOptions`. pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. /// /// If a new file is created as part of a `File::open_opts` call then this /// specified `mode` will be used as the permission bits for the new file. /// If no `mode` is set, the default of `0o666` will be used. /// The operating system masks out bits with the systems `umask`, to produce /// the final permissions. fn mode(&mut self, mode: u32) -> &mut Self; /// Pass custom flags to the `flags` argument of `open`. /// /// The bits that define the access mode are masked out with `O_ACCMODE`, to /// ensure they do not interfere with the access mode set by Rusts options. /// /// Custom flags can only set flags, not remove flags set by Rusts options. /// This options overwrites any previously set custom flags. fn custom_flags(&mut self, flags: i32) -> &mut Self; } } async-rs-async-std-57f61ae/src/os/unix/io.rs000066400000000000000000000046201476537407000207630ustar00rootroot00000000000000//! Unix-specific I/O extensions. cfg_not_docs! { pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; cfg_io_safety! { pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; } } cfg_docs! { /// Raw file descriptors. pub type RawFd = std::os::raw::c_int; /// A trait to extract the raw unix file descriptor from an underlying /// object. /// /// This is only available on unix platforms and must be imported in order /// to call the method. Windows platforms have a corresponding `AsRawHandle` /// and `AsRawSocket` set of traits. pub trait AsRawFd { /// Extracts the raw file descriptor. /// /// This method does **not** pass ownership of the raw file descriptor /// to the caller. The descriptor is only guaranteed to be valid while /// the original object has not yet been destroyed. fn as_raw_fd(&self) -> RawFd; } /// A trait to express the ability to construct an object from a raw file /// descriptor. pub trait FromRawFd { /// Constructs a new instance of `Self` from the given raw file /// descriptor. /// /// This function **consumes ownership** of the specified file /// descriptor. The returned object will take responsibility for closing /// it when the object goes out of scope. /// /// This function is also unsafe as the primitives currently returned /// have the contract that they are the sole owner of the file /// descriptor they are wrapping. Usage of this function could /// accidentally allow violating this contract which can cause memory /// unsafety in code that relies on it being true. unsafe fn from_raw_fd(fd: RawFd) -> Self; } /// A trait to express the ability to consume an object and acquire ownership of /// its raw file descriptor. pub trait IntoRawFd { /// Consumes this object, returning the raw underlying file descriptor. /// /// This function **transfers ownership** of the underlying file descriptor /// to the caller. Callers are then the unique owners of the file descriptor /// and must close the descriptor once it's no longer needed. fn into_raw_fd(self) -> RawFd; } cfg_io_safety! { #[doc(inline)] pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; } } async-rs-async-std-57f61ae/src/os/unix/mod.rs000066400000000000000000000004431476537407000211320ustar00rootroot00000000000000//! Platform-specific extensions for Unix platforms. cfg_std! { pub mod io; } cfg_default! { pub mod fs; pub mod net; } #[cfg(all(feature = "unstable", feature = "std"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::unix as process; async-rs-async-std-57f61ae/src/os/unix/net/000077500000000000000000000000001476537407000205725ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/os/unix/net/datagram.rs000066400000000000000000000247731476537407000227350ustar00rootroot00000000000000//! Unix-specific networking extensions. use std::fmt; use std::net::Shutdown; use std::os::unix::net::UnixDatagram as StdUnixDatagram; use async_io::Async; use super::SocketAddr; use crate::io; use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::path::Path; /// A Unix datagram socket. /// /// After creating a `UnixDatagram` by [`bind`]ing it to a path, data can be [sent to] and /// [received from] any other socket address. /// /// This type is an async version of [`std::os::unix::net::UnixDatagram`]. /// /// [`std::os::unix::net::UnixDatagram`]: /// https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html /// [`bind`]: #method.bind /// [received from]: #method.recv_from /// [sent to]: #method.send_to /// /// ## Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::bind("/tmp/socket1").await?; /// socket.send_to(b"hello world", "/tmp/socket2").await?; /// /// let mut buf = vec![0u8; 1024]; /// let (n, peer) = socket.recv_from(&mut buf).await?; /// # /// # Ok(()) }) } /// ``` pub struct UnixDatagram { watcher: Async, } impl UnixDatagram { fn new(socket: StdUnixDatagram) -> UnixDatagram { UnixDatagram { watcher: Async::new(socket).expect("UnixDatagram is known to be good"), } } /// Creates a Unix datagram socket bound to the given path. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::bind("/tmp/socket").await?; /// # /// # Ok(()) }) } /// ``` pub async fn bind>(path: P) -> io::Result { let path = path.as_ref().to_owned(); let socket = Async::::bind(path)?; Ok(UnixDatagram { watcher: socket }) } /// Creates a Unix datagram which is not bound to any address. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::unbound()?; /// # /// # Ok(()) }) } /// ``` pub fn unbound() -> io::Result { let socket = StdUnixDatagram::unbound()?; Ok(UnixDatagram::new(socket)) } /// Creates an unnamed pair of connected sockets. /// /// Returns two sockets which are connected to each other. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let (socket1, socket2) = UnixDatagram::pair()?; /// # /// # Ok(()) }) } /// ``` pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { let (a, b) = StdUnixDatagram::pair()?; let a = UnixDatagram::new(a); let b = UnixDatagram::new(b); Ok((a, b)) } /// Connects the socket to the specified address. /// /// The [`send`] method may be used to send data to the specified address. [`recv`] and /// [`recv_from`] will only receive data from that address. /// /// [`send`]: #method.send /// [`recv`]: #method.recv /// [`recv_from`]: #method.recv_from /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::unbound()?; /// socket.connect("/tmp/socket").await?; /// # /// # Ok(()) }) } /// ``` pub async fn connect>(&self, path: P) -> io::Result<()> { // TODO(stjepang): Connect the socket on a blocking pool. let p = path.as_ref(); self.watcher.get_ref().connect(p) } /// Returns the address of this socket. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::bind("/tmp/socket").await?; /// let addr = socket.local_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn local_addr(&self) -> io::Result { self.watcher.get_ref().local_addr() } /// Returns the address of this socket's peer. /// /// The [`connect`] method will connect the socket to a peer. /// /// [`connect`]: #method.connect /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::unbound()?; /// socket.connect("/tmp/socket").await?; /// let peer = socket.peer_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn peer_addr(&self) -> io::Result { self.watcher.get_ref().peer_addr() } /// Receives data from the socket. /// /// On success, returns the number of bytes read and the address from where the data came. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::unbound()?; /// let mut buf = vec![0; 1024]; /// let (n, peer) = socket.recv_from(&mut buf).await?; /// # /// # Ok(()) }) } /// ``` pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.watcher.recv_from(buf).await } /// Receives data from the socket. /// /// On success, returns the number of bytes read. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::bind("/tmp/socket").await?; /// let mut buf = vec![0; 1024]; /// let n = socket.recv(&mut buf).await?; /// # /// # Ok(()) }) } /// ``` pub async fn recv(&self, buf: &mut [u8]) -> io::Result { self.watcher.recv(buf).await } /// Sends data on the socket to the specified address. /// /// On success, returns the number of bytes written. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::unbound()?; /// socket.send_to(b"hello world", "/tmp/socket").await?; /// # /// # Ok(()) }) } /// ``` pub async fn send_to>(&self, buf: &[u8], path: P) -> io::Result { self.watcher.send_to(buf, path.as_ref()).await } /// Sends data on the socket to the socket's peer. /// /// On success, returns the number of bytes written. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::unbound()?; /// socket.connect("/tmp/socket").await?; /// socket.send(b"hello world").await?; /// # /// # Ok(()) }) } /// ``` pub async fn send(&self, buf: &[u8]) -> io::Result { self.watcher.send(buf).await } /// Shut down the read, write, or both halves of this connection. /// /// This function will cause all pending and future I/O calls on the specified portions to /// immediately return with an appropriate value (see the documentation of [`Shutdown`]). /// /// [`Shutdown`]: https://doc.rust-lang.org/std/net/enum.Shutdown.html /// /// ## Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixDatagram; /// use std::net::Shutdown; /// /// let socket = UnixDatagram::unbound()?; /// socket.shutdown(Shutdown::Both)?; /// # /// # Ok(()) }) } /// ``` pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.watcher.get_ref().shutdown(how) } } impl fmt::Debug for UnixDatagram { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut builder = f.debug_struct("UnixDatagram"); builder.field("fd", &self.as_raw_fd()); if let Ok(addr) = self.local_addr() { builder.field("local", &addr); } if let Ok(addr) = self.peer_addr() { builder.field("peer", &addr); } builder.finish() } } impl From for UnixDatagram { /// Converts a `std::os::unix::net::UnixDatagram` into its asynchronous equivalent. fn from(datagram: StdUnixDatagram) -> UnixDatagram { UnixDatagram { watcher: Async::new(datagram).expect("UnixDatagram is known to be good"), } } } impl std::convert::TryFrom for StdUnixDatagram { type Error = io::Error; /// Converts a `UnixDatagram` into its synchronous equivalent. fn try_from(listener: UnixDatagram) -> io::Result { let inner = listener.watcher.into_inner()?; inner.set_nonblocking(false)?; Ok(inner) } } impl AsRawFd for UnixDatagram { fn as_raw_fd(&self) -> RawFd { self.watcher.as_raw_fd() } } impl FromRawFd for UnixDatagram { unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { let raw = StdUnixDatagram::from_raw_fd(fd); let datagram = Async::::new(raw).expect("invalid file descriptor"); UnixDatagram { watcher: datagram } } } impl IntoRawFd for UnixDatagram { fn into_raw_fd(self) -> RawFd { self.watcher.into_inner().unwrap().into_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; impl AsFd for UnixDatagram { fn as_fd(&self) -> BorrowedFd<'_> { self.watcher.get_ref().as_fd() } } impl From for UnixDatagram { fn from(fd: OwnedFd) -> UnixDatagram { StdUnixDatagram::from(fd).into() } } impl From for OwnedFd { fn from(stream: UnixDatagram) -> OwnedFd { stream.watcher.into_inner().unwrap().into() } } } async-rs-async-std-57f61ae/src/os/unix/net/listener.rs000066400000000000000000000172401476537407000227710ustar00rootroot00000000000000//! Unix-specific networking extensions. use std::fmt; use std::os::unix::net::UnixListener as StdUnixListener; use std::os::unix::net::UnixStream as StdUnixStream; use std::pin::Pin; use async_io::Async; use super::SocketAddr; use super::UnixStream; use crate::io; use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::path::Path; use crate::stream::Stream; use crate::sync::Arc; use crate::task::{ready, Context, Poll}; /// A Unix domain socket server, listening for connections. /// /// After creating a `UnixListener` by [`bind`]ing it to a socket address, it listens for incoming /// connections. These can be accepted by awaiting elements from the async stream of [`incoming`] /// connections. /// /// The socket will be closed when the value is dropped. /// /// This type is an async version of [`std::os::unix::net::UnixListener`]. /// /// [`std::os::unix::net::UnixListener`]: /// https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html /// [`bind`]: #method.bind /// [`incoming`]: #method.incoming /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixListener; /// use async_std::prelude::*; /// /// let listener = UnixListener::bind("/tmp/socket").await?; /// let mut incoming = listener.incoming(); /// /// while let Some(stream) = incoming.next().await { /// let mut stream = stream?; /// stream.write_all(b"hello world").await?; /// } /// # /// # Ok(()) }) } /// ``` pub struct UnixListener { watcher: Async, } impl UnixListener { /// Creates a Unix datagram listener bound to the given path. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixListener; /// /// let listener = UnixListener::bind("/tmp/socket").await?; /// # /// # Ok(()) }) } /// ``` pub async fn bind>(path: P) -> io::Result { let path = path.as_ref().to_owned(); let listener = Async::::bind(path)?; Ok(UnixListener { watcher: listener }) } /// Accepts a new incoming connection to this listener. /// /// When a connection is established, the corresponding stream and address will be returned. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixListener; /// /// let listener = UnixListener::bind("/tmp/socket").await?; /// let (socket, addr) = listener.accept().await?; /// # /// # Ok(()) }) } /// ``` pub async fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { let (stream, addr) = self.watcher.accept().await?; Ok(( UnixStream { watcher: Arc::new(stream), }, addr, )) } /// Returns a stream of incoming connections. /// /// Iterating over this stream is equivalent to calling [`accept`] in a loop. The stream of /// connections is infinite, i.e awaiting the next connection will never result in [`None`]. /// /// [`accept`]: #method.accept /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixListener; /// use async_std::prelude::*; /// /// let listener = UnixListener::bind("/tmp/socket").await?; /// let mut incoming = listener.incoming(); /// /// while let Some(stream) = incoming.next().await { /// let mut stream = stream?; /// stream.write_all(b"hello world").await?; /// } /// # /// # Ok(()) }) } /// ``` pub fn incoming(&self) -> Incoming<'_> { Incoming { incoming: Box::pin(self.watcher.incoming()), } } /// Returns the local socket address of this listener. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixListener; /// /// let listener = UnixListener::bind("/tmp/socket").await?; /// let addr = listener.local_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn local_addr(&self) -> io::Result { self.watcher.get_ref().local_addr() } } impl fmt::Debug for UnixListener { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut builder = f.debug_struct("UnixListener"); builder.field("fd", &self.as_raw_fd()); if let Ok(addr) = self.local_addr() { builder.field("local", &addr); } builder.finish() } } /// A stream of incoming Unix domain socket connections. /// /// This stream is infinite, i.e awaiting the next connection will never result in [`None`]. It is /// created by the [`incoming`] method on [`UnixListener`]. /// /// This type is an async version of [`std::os::unix::net::Incoming`]. /// /// [`std::os::unix::net::Incoming`]: https://doc.rust-lang.org/std/os/unix/net/struct.Incoming.html /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// [`incoming`]: struct.UnixListener.html#method.incoming /// [`UnixListener`]: struct.UnixListener.html pub struct Incoming<'a> { incoming: Pin>> + Send + Sync + 'a>>, } impl Stream for Incoming<'_> { type Item = io::Result; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let res = ready!(Pin::new(&mut self.incoming).poll_next(cx)); Poll::Ready(res.map(|res| res.map(|stream| UnixStream { watcher: Arc::new(stream) }))) } } impl fmt::Debug for Incoming<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Incoming") .finish() } } impl From for UnixListener { /// Converts a `std::os::unix::net::UnixListener` into its asynchronous equivalent. fn from(listener: StdUnixListener) -> UnixListener { UnixListener { watcher: Async::new(listener).expect("UnixListener is known to be good"), } } } impl std::convert::TryFrom for StdUnixListener { type Error = io::Error; /// Converts a `UnixListener` into its synchronous equivalent. fn try_from(listener: UnixListener) -> io::Result { let inner = listener.watcher.into_inner()?; inner.set_nonblocking(false)?; Ok(inner) } } impl AsRawFd for UnixListener { fn as_raw_fd(&self) -> RawFd { self.watcher.as_raw_fd() } } impl FromRawFd for UnixListener { unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { let listener = std::os::unix::net::UnixListener::from_raw_fd(fd); listener.into() } } impl IntoRawFd for UnixListener { fn into_raw_fd(self) -> RawFd { self.watcher.into_inner().unwrap().into_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; impl AsFd for UnixListener { fn as_fd(&self) -> BorrowedFd<'_> { self.watcher.get_ref().as_fd() } } impl From for UnixListener { fn from(fd: OwnedFd) -> UnixListener { std::os::unix::net::UnixListener::from(fd).into() } } impl From for OwnedFd { fn from(stream: UnixListener) -> OwnedFd { stream.watcher.into_inner().unwrap().into() } } } async-rs-async-std-57f61ae/src/os/unix/net/mod.rs000066400000000000000000000051611476537407000217220ustar00rootroot00000000000000//! Unix-specific networking extensions. pub use datagram::UnixDatagram; pub use listener::{Incoming, UnixListener}; pub use stream::UnixStream; mod datagram; mod listener; mod stream; cfg_not_docs! { pub use std::os::unix::net::SocketAddr; } cfg_docs! { use std::fmt; use crate::path::Path; /// An address associated with a Unix socket. /// /// # Examples /// /// ``` /// use async_std::os::unix::net::UnixListener; /// /// let socket = UnixListener::bind("/tmp/socket").await?; /// let addr = socket.local_addr()?; /// ``` #[derive(Clone)] pub struct SocketAddr { _private: (), } impl SocketAddr { /// Returns `true` if the address is unnamed. /// /// # Examples /// /// A named address: /// /// ```no_run /// use async_std::os::unix::net::UnixListener; /// /// let socket = UnixListener::bind("/tmp/socket").await?; /// let addr = socket.local_addr()?; /// assert_eq!(addr.is_unnamed(), false); /// ``` /// /// An unnamed address: /// /// ```no_run /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::unbound().await?; /// let addr = socket.local_addr()?; /// assert_eq!(addr.is_unnamed(), true); /// ``` pub fn is_unnamed(&self) -> bool { unreachable!("this impl only appears in the rendered docs") } /// Returns the contents of this address if it is a `pathname` address. /// /// # Examples /// /// With a pathname: /// /// ```no_run /// use async_std::os::unix::net::UnixListener; /// use async_std::path::Path; /// /// let socket = UnixListener::bind("/tmp/socket").await?; /// let addr = socket.local_addr()?; /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/socket"))); /// ``` /// /// Without a pathname: /// /// ``` /// use async_std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::unbound()?; /// let addr = socket.local_addr()?; /// assert_eq!(addr.as_pathname(), None); /// ``` pub fn as_pathname(&self) -> Option<&Path> { unreachable!("this impl only appears in the rendered docs") } } impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { unreachable!("this impl only appears in the rendered docs") } } } async-rs-async-std-57f61ae/src/os/unix/net/stream.rs000066400000000000000000000176521476537407000224460ustar00rootroot00000000000000//! Unix-specific networking extensions. use std::fmt; use std::net::Shutdown; use std::os::unix::net::UnixStream as StdUnixStream; use std::pin::Pin; use async_io::Async; use super::SocketAddr; use crate::io::{self, Read, Write}; use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::path::Path; use crate::sync::Arc; use crate::task::{Context, Poll}; /// A Unix stream socket. /// /// This type is an async version of [`std::os::unix::net::UnixStream`]. /// /// [`std::os::unix::net::UnixStream`]: /// https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixStream; /// use async_std::prelude::*; /// /// let mut stream = UnixStream::connect("/tmp/socket").await?; /// stream.write_all(b"hello world").await?; /// /// let mut response = Vec::new(); /// stream.read_to_end(&mut response).await?; /// # /// # Ok(()) }) } /// ``` #[derive(Clone)] pub struct UnixStream { pub(super) watcher: Arc>, } impl UnixStream { /// Connects to the socket to the specified address. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixStream; /// /// let stream = UnixStream::connect("/tmp/socket").await?; /// # /// # Ok(()) }) } /// ``` pub async fn connect>(path: P) -> io::Result { let path = path.as_ref().to_owned(); let stream = Arc::new(Async::::connect(path).await?); Ok(UnixStream { watcher: stream }) } /// Creates an unnamed pair of connected sockets. /// /// Returns two streams which are connected to each other. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixStream; /// /// let stream = UnixStream::pair()?; /// # /// # Ok(()) }) } /// ``` pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let (a, b) = Async::::pair()?; let a = UnixStream { watcher: Arc::new(a), }; let b = UnixStream { watcher: Arc::new(b), }; Ok((a, b)) } /// Returns the socket address of the local half of this connection. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixStream; /// /// let stream = UnixStream::connect("/tmp/socket").await?; /// let addr = stream.local_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn local_addr(&self) -> io::Result { self.watcher.get_ref().local_addr() } /// Returns the socket address of the remote half of this connection. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixStream; /// /// let stream = UnixStream::connect("/tmp/socket").await?; /// let peer = stream.peer_addr()?; /// # /// # Ok(()) }) } /// ``` pub fn peer_addr(&self) -> io::Result { self.watcher.get_ref().peer_addr() } /// Shuts down the read, write, or both halves of this connection. /// /// This function will cause all pending and future I/O calls on the specified portions to /// immediately return with an appropriate value (see the documentation of [`Shutdown`]). /// /// [`Shutdown`]: https://doc.rust-lang.org/std/net/enum.Shutdown.html /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::unix::net::UnixStream; /// use std::net::Shutdown; /// /// let stream = UnixStream::connect("/tmp/socket").await?; /// stream.shutdown(Shutdown::Both)?; /// # /// # Ok(()) }) } /// ``` pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.watcher.get_ref().shutdown(how) } } impl Read for UnixStream { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { Pin::new(&mut &*self).poll_read(cx, buf) } } impl Read for &UnixStream { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { Pin::new(&mut &*self.watcher).poll_read(cx, buf) } } impl Write for UnixStream { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { Pin::new(&mut &*self).poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self).poll_flush(cx) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self).poll_close(cx) } } impl Write for &UnixStream { fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { Pin::new(&mut &*self.watcher).poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self.watcher).poll_flush(cx) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut &*self.watcher).poll_close(cx) } } impl fmt::Debug for UnixStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut builder = f.debug_struct("UnixStream"); builder.field("fd", &self.as_raw_fd()); if let Ok(addr) = self.local_addr() { builder.field("local", &addr); } if let Ok(addr) = self.peer_addr() { builder.field("peer", &addr); } builder.finish() } } impl From for UnixStream { /// Converts a `std::os::unix::net::UnixStream` into its asynchronous equivalent. fn from(stream: StdUnixStream) -> UnixStream { let stream = Async::new(stream).expect("UnixStream is known to be good"); UnixStream { watcher: Arc::new(stream), } } } impl std::convert::TryFrom for StdUnixStream { type Error = io::Error; /// Converts a `UnixStream` into its synchronous equivalent. fn try_from(stream: UnixStream) -> io::Result { let inner = Arc::try_unwrap(stream.watcher) .map_err(|_| io::Error::new( io::ErrorKind::Other, "Cannot convert UnixStream to synchronous: multiple references", ))? .into_inner()?; inner.set_nonblocking(false)?; Ok(inner) } } impl AsRawFd for UnixStream { fn as_raw_fd(&self) -> RawFd { self.watcher.as_raw_fd() } } impl FromRawFd for UnixStream { unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { let stream = std::os::unix::net::UnixStream::from_raw_fd(fd); stream.into() } } impl IntoRawFd for UnixStream { fn into_raw_fd(self) -> RawFd { (*self.watcher).get_ref().try_clone().unwrap().into_raw_fd() } } cfg_io_safety! { use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; impl AsFd for UnixStream { fn as_fd(&self) -> BorrowedFd<'_> { self.watcher.get_ref().as_fd() } } impl From for UnixStream { fn from(fd: OwnedFd) -> UnixStream { std::os::unix::net::UnixStream::from(fd).into() } } impl From for OwnedFd { fn from(stream: UnixStream) -> OwnedFd { stream.watcher.get_ref().try_clone().unwrap().into() } } } async-rs-async-std-57f61ae/src/os/windows/000077500000000000000000000000001476537407000205135ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/os/windows/fs.rs000066400000000000000000000033711476537407000214750ustar00rootroot00000000000000//! Windows-specific filesystem extensions. use crate::io; use crate::path::Path; use crate::task::spawn_blocking; /// Creates a new directory symbolic link on the filesystem. /// /// The `dst` path will be a directory symbolic link pointing to the `src` path. /// /// This function is an async version of [`std::os::windows::fs::symlink_dir`]. /// /// [`std::os::windows::fs::symlink_dir`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::windows::fs::symlink_dir; /// /// symlink_dir("a", "b").await?; /// # /// # Ok(()) }) } /// ``` pub async fn symlink_dir, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { let src = src.as_ref().to_owned(); let dst = dst.as_ref().to_owned(); spawn_blocking(move || std::os::windows::fs::symlink_dir(&src, &dst)).await } /// Creates a new file symbolic link on the filesystem. /// /// The `dst` path will be a file symbolic link pointing to the `src` path. /// /// This function is an async version of [`std::os::windows::fs::symlink_file`]. /// /// [`std::os::windows::fs::symlink_file`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::os::windows::fs::symlink_file; /// /// symlink_file("a.txt", "b.txt").await?; /// # /// # Ok(()) }) } /// ``` pub async fn symlink_file, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { let src = src.as_ref().to_owned(); let dst = dst.as_ref().to_owned(); spawn_blocking(move || std::os::windows::fs::symlink_file(&src, &dst)).await } async-rs-async-std-57f61ae/src/os/windows/io.rs000066400000000000000000000067311476537407000214770ustar00rootroot00000000000000//! Windows-specific I/O extensions. cfg_not_docs! { pub use std::os::windows::io::{ AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle, AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket, }; cfg_io_safety! { pub use std::os::windows::io::{ AsHandle, BorrowedHandle, OwnedHandle, AsSocket, BorrowedSocket, OwnedSocket, }; } } cfg_docs! { /// Raw HANDLEs. pub type RawHandle = *mut std::os::raw::c_void; /// Raw SOCKETs. pub type RawSocket = u64; /// Extracts raw handles. pub trait AsRawHandle { /// Extracts the raw handle, without taking any ownership. fn as_raw_handle(&self) -> RawHandle; } /// Construct I/O objects from raw handles. pub trait FromRawHandle { /// Constructs a new I/O object from the specified raw handle. /// /// This function will **consume ownership** of the handle given, /// passing responsibility for closing the handle to the returned /// object. /// /// This function is also unsafe as the primitives currently returned /// have the contract that they are the sole owner of the file /// descriptor they are wrapping. Usage of this function could /// accidentally allow violating this contract which can cause memory /// unsafety in code that relies on it being true. unsafe fn from_raw_handle(handle: RawHandle) -> Self; } /// A trait to express the ability to consume an object and acquire ownership of /// its raw `HANDLE`. pub trait IntoRawHandle { /// Consumes this object, returning the raw underlying handle. /// /// This function **transfers ownership** of the underlying handle to the /// caller. Callers are then the unique owners of the handle and must close /// it once it's no longer needed. fn into_raw_handle(self) -> RawHandle; } /// Creates I/O objects from raw sockets. pub trait FromRawSocket { /// Creates a new I/O object from the given raw socket. /// /// This function will consume ownership of the socket provided and it will be closed when the returned object goes out of scope. /// /// This function is also unsafe as the primitives currently returned have the contract that they are the sole owner of the /// file descriptor they are wrapping. Usage of this function could accidentally allow violating this contract which can cause /// memory unsafety in code that relies on it being true. unsafe fn from_raw_socket(sock: RawSocket) -> Self; } /// Extracts raw sockets. pub trait AsRawSocket { /// Extracts the underlying raw socket from this object. fn as_raw_socket(&self) -> RawSocket; } /// A trait to express the ability to consume an object and acquire ownership of /// its raw `SOCKET`. pub trait IntoRawSocket { /// Consumes this object, returning the raw underlying socket. /// /// This function **transfers ownership** of the underlying socket to the /// caller. Callers are then the unique owners of the socket and must close /// it once it's no longer needed. fn into_raw_socket(self) -> RawSocket; } cfg_io_safety! { #[doc(inline)] pub use std::os::windows::io::{ AsHandle, BorrowedHandle, OwnedHandle, AsSocket, BorrowedSocket, OwnedSocket, }; } } async-rs-async-std-57f61ae/src/os/windows/mod.rs000066400000000000000000000003561476537407000216440ustar00rootroot00000000000000//! Platform-specific extensions for Windows. cfg_std! { pub mod io; } cfg_unstable! { #[cfg(feature = "default")] pub mod fs; #[cfg(feature = "std")] #[cfg(windows)] pub use async_process::windows as process; } async-rs-async-std-57f61ae/src/path/000077500000000000000000000000001476537407000173345ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/path/ancestors.rs000066400000000000000000000015331476537407000217050ustar00rootroot00000000000000use std::iter::FusedIterator; use crate::path::Path; /// An iterator over [`Path`] and its ancestors. /// /// This `struct` is created by the [`ancestors`] method on [`Path`]. /// See its documentation for more. /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("/foo/bar"); /// /// for ancestor in path.ancestors() { /// println!("{}", ancestor.display()); /// } /// ``` /// /// [`ancestors`]: struct.Path.html#method.ancestors /// [`Path`]: struct.Path.html #[derive(Copy, Clone, Debug)] pub struct Ancestors<'a> { pub(crate) next: Option<&'a Path>, } impl<'a> Iterator for Ancestors<'a> { type Item = &'a Path; fn next(&mut self) -> Option { let next = self.next; self.next = next.and_then(Path::parent); next } } impl FusedIterator for Ancestors<'_> {} async-rs-async-std-57f61ae/src/path/components.rs000066400000000000000000000035631476537407000220760ustar00rootroot00000000000000use std::ffi::OsStr; use std::iter::FusedIterator; use crate::path::{Component, Path}; /// An iterator over the [`Component`]s of a [`Path`]. /// /// This `struct` is created by the [`components`] method on [`Path`]. /// See its documentation for more. /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("/tmp/foo/bar.txt"); /// /// for component in path.components() { /// println!("{:?}", component); /// } /// ``` /// /// [`Component`]: enum.Component.html /// [`components`]: struct.Path.html#method.components /// [`Path`]: struct.Path.html #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Components<'a> { pub(crate) inner: std::path::Components<'a>, } impl<'a> Components<'a> { /// Extracts a slice corresponding to the portion of the path remaining for iteration. /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let mut components = Path::new("/tmp/foo/bar.txt").components(); /// components.next(); /// components.next(); /// /// assert_eq!(Path::new("foo/bar.txt"), components.as_path()); /// ``` pub fn as_path(&self) -> &'a Path { self.inner.as_path().into() } } impl AsRef for Components<'_> { fn as_ref(&self) -> &Path { self.as_path() } } impl AsRef for Components<'_> { fn as_ref(&self) -> &OsStr { self.as_path().as_os_str() } } impl<'a> Iterator for Components<'a> { type Item = Component<'a>; fn next(&mut self) -> Option> { self.inner.next() } } impl<'a> DoubleEndedIterator for Components<'a> { fn next_back(&mut self) -> Option> { self.inner.next_back() } } impl FusedIterator for Components<'_> {} impl AsRef for Component<'_> { fn as_ref(&self) -> &Path { self.as_os_str().as_ref() } } async-rs-async-std-57f61ae/src/path/iter.rs000066400000000000000000000037521476537407000206540ustar00rootroot00000000000000use std::ffi::OsStr; use std::fmt; use std::iter::FusedIterator; use crate::path::{Component, Components, Path}; /// An iterator over the [`Component`]s of a [`Path`], as [`OsStr`] slices. /// /// This `struct` is created by the [`iter`] method on [`Path`]. /// See its documentation for more. /// /// [`Component`]: enum.Component.html /// [`iter`]: struct.Path.html#method.iter /// [`OsStr`]: ../../std/ffi/struct.OsStr.html /// [`Path`]: struct.Path.html #[derive(Clone)] pub struct Iter<'a> { pub(crate) inner: Components<'a>, } impl<'a> Iter<'a> { /// Extracts a slice corresponding to the portion of the path remaining for iteration. /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let mut iter = Path::new("/tmp/foo/bar.txt").iter(); /// iter.next(); /// iter.next(); /// /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path()); /// ``` pub fn as_path(&self) -> &'a Path { self.inner.as_path() } } impl<'a> Iterator for Iter<'a> { type Item = &'a OsStr; fn next(&mut self) -> Option<&'a OsStr> { self.inner.next().map(Component::as_os_str) } } impl fmt::Debug for Iter<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { struct DebugHelper<'a>(&'a Path); impl fmt::Debug for DebugHelper<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.0.iter()).finish() } } f.debug_tuple("Iter") .field(&DebugHelper(self.as_path())) .finish() } } impl AsRef for Iter<'_> { fn as_ref(&self) -> &Path { self.as_path() } } impl AsRef for Iter<'_> { fn as_ref(&self) -> &OsStr { self.as_path().as_os_str() } } impl<'a> DoubleEndedIterator for Iter<'a> { fn next_back(&mut self) -> Option<&'a OsStr> { self.inner.next_back().map(Component::as_os_str) } } impl FusedIterator for Iter<'_> {} async-rs-async-std-57f61ae/src/path/mod.rs000066400000000000000000000054731476537407000204720ustar00rootroot00000000000000//! Cross-platform path manipulation. //! //! This module is an async version of [`std::path`]. //! //! This module provides two types, [`PathBuf`] and [`Path`][`Path`] (akin to [`String`] //! and [`str`]), for working with paths abstractly. These types are thin wrappers //! around [`OsString`] and [`OsStr`] respectively, meaning that they work directly //! on strings according to the local platform's path syntax. //! //! Paths can be parsed into [`Component`]s by iterating over the structure //! returned by the [`components`] method on [`Path`]. [`Component`]s roughly //! correspond to the substrings between path separators (`/` or `\`). You can //! reconstruct an equivalent path from components with the [`push`] method on //! [`PathBuf`]; note that the paths may differ syntactically by the //! normalization described in the documentation for the [`components`] method. //! //! [`std::path`]: https://doc.rust-lang.org/std/path/index.html //! //! ## Simple usage //! //! Path manipulation includes both parsing components from slices and building //! new owned paths. //! //! To parse a path, you can create a [`Path`] slice from a [`str`] //! slice and start asking questions: //! //! ``` //! use async_std::path::Path; //! use std::ffi::OsStr; //! //! let path = Path::new("/tmp/foo/bar.txt"); //! //! let parent = path.parent(); //! assert_eq!(parent, Some(Path::new("/tmp/foo"))); //! //! let file_stem = path.file_stem(); //! assert_eq!(file_stem, Some(OsStr::new("bar"))); //! //! let extension = path.extension(); //! assert_eq!(extension, Some(OsStr::new("txt"))); //! ``` //! //! To build or modify paths, use [`PathBuf`]: //! //! ``` //! use async_std::path::PathBuf; //! //! // This way works... //! let mut path = PathBuf::from("c:\\"); //! //! path.push("windows"); //! path.push("system32"); //! //! path.set_extension("dll"); //! //! // ... but push is best used if you don't know everything up //! // front. If you do, this way is better: //! let path: PathBuf = ["c:\\", "windows", "system32.dll"].iter().collect(); //! ``` //! //! [`Component`]: enum.Component.html //! [`components`]: struct.Path.html#method.components //! [`PathBuf`]: struct.PathBuf.html //! [`Path`]: struct.Path.html //! [`push`]: struct.PathBuf.html#method.push //! [`String`]: https://doc.rust-lang.org/std/string/struct.String.html //! //! [`str`]: https://doc.rust-lang.org/std/primitive.str.html //! [`OsString`]: https://doc.rust-lang.org/std/ffi/struct.OsString.html //! [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html mod ancestors; mod components; mod iter; mod path; mod pathbuf; #[doc(inline)] pub use std::path::{ is_separator, Component, Display, Prefix, PrefixComponent, StripPrefixError, MAIN_SEPARATOR, }; pub use ancestors::Ancestors; pub use components::Components; pub use iter::Iter; pub use path::Path; pub use pathbuf::PathBuf; async-rs-async-std-57f61ae/src/path/path.rs000066400000000000000000000762331476537407000206510ustar00rootroot00000000000000use std::borrow::{Cow, ToOwned}; use std::cmp::Ordering; use std::ffi::{OsStr, OsString}; use std::rc::Rc; use std::sync::Arc; use crate::path::{Ancestors, Components, Display, Iter, PathBuf, StripPrefixError}; #[cfg(not(target_os = "unknown"))] use crate::{fs, io}; /// A slice of a path. /// /// This struct is an async version of [`std::path::Path`]. /// /// This type supports a number of operations for inspecting a path, including /// breaking the path into its components (separated by `/` on Unix and by either /// `/` or `\` on Windows), extracting the file name, determining whether the path /// is absolute, and so on. /// /// This is an *unsized* type, meaning that it must always be used behind a /// pointer like `&` or `Box`. For an owned version of this type, /// see [`PathBuf`]. /// /// [`PathBuf`]: struct.PathBuf.html /// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html /// /// More details about the overall approach can be found in /// the [module documentation](index.html). /// /// # Examples /// /// ``` /// use std::path::Path; /// use std::ffi::OsStr; /// /// // Note: this example does work on Windows /// let path = Path::new("./foo/bar.txt"); /// /// let parent = path.parent(); /// assert_eq!(parent, Some(Path::new("./foo"))); /// /// let file_stem = path.file_stem(); /// assert_eq!(file_stem, Some(OsStr::new("bar"))); /// /// let extension = path.extension(); /// assert_eq!(extension, Some(OsStr::new("txt"))); /// ``` #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Path { inner: std::path::Path, } impl Path { /// Directly wraps a string slice as a `Path` slice. /// /// This is a cost-free conversion. /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// Path::new("foo.txt"); /// ``` /// /// You can create `Path`s from `String`s, or even other `Path`s: /// /// ``` /// use async_std::path::Path; /// /// let string = String::from("foo.txt"); /// let from_string = Path::new(&string); /// let from_path = Path::new(&from_string); /// assert_eq!(from_string, from_path); /// ``` pub fn new + ?Sized>(s: &S) -> &Path { unsafe { &*(std::path::Path::new(s) as *const std::path::Path as *const Path) } } /// Returns the underlying [`OsStr`] slice. /// /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html /// /// # Examples /// /// ``` /// use std::ffi::OsStr; /// /// use async_std::path::Path; /// /// let os_str = Path::new("foo.txt").as_os_str(); /// assert_eq!(os_str, OsStr::new("foo.txt")); /// ``` pub fn as_os_str(&self) -> &OsStr { self.inner.as_os_str() } /// Returns a [`&str`] slice if the `Path` is valid unicode. /// /// This conversion may entail doing a check for UTF-8 validity. /// Note that validation is performed because non-UTF-8 strings are /// perfectly valid for some OS. /// /// [`&str`]: https://doc.rust-lang.org/std/primitive.str.html /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("foo.txt"); /// assert_eq!(path.to_str(), Some("foo.txt")); /// ``` pub fn to_str(&self) -> Option<&str> { self.inner.to_str() } /// Converts a `Path` to a [`Cow`]. /// /// Any non-Unicode sequences are replaced with /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]. /// /// [`Cow`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html /// [U+FFFD]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html /// /// # Examples /// /// Calling `to_string_lossy` on a `Path` with valid unicode: /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("foo.txt"); /// assert_eq!(path.to_string_lossy(), "foo.txt"); /// ``` /// /// Had `path` contained invalid unicode, the `to_string_lossy` call might /// have returned `"fo�.txt"`. pub fn to_string_lossy(&self) -> Cow<'_, str> { self.inner.to_string_lossy() } /// Converts a `Path` to an owned [`PathBuf`]. /// /// [`PathBuf`]: struct.PathBuf.html /// /// # Examples /// /// ``` /// use async_std::path::{Path, PathBuf}; /// /// let path_buf = Path::new("foo.txt").to_path_buf(); /// assert_eq!(path_buf, PathBuf::from("foo.txt")); /// ``` pub fn to_path_buf(&self) -> PathBuf { PathBuf::from(self.inner.to_path_buf()) } /// Returns `true` if the `Path` is absolute, i.e. if it is independent of /// the current directory. /// /// * On Unix, a path is absolute if it starts with the root, so /// `is_absolute` and [`has_root`] are equivalent. /// /// * On Windows, a path is absolute if it has a prefix and starts with the /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not. /// /// [`has_root`]: #method.has_root /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// assert!(!Path::new("foo.txt").is_absolute()); /// ``` pub fn is_absolute(&self) -> bool { self.inner.is_absolute() } /// Returns `true` if the `Path` is relative, i.e. not absolute. /// /// See [`is_absolute`]'s documentation for more details. /// /// [`is_absolute`]: #method.is_absolute /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// assert!(Path::new("foo.txt").is_relative()); /// ``` pub fn is_relative(&self) -> bool { self.inner.is_relative() } /// Returns `true` if the `Path` has a root. /// /// * On Unix, a path has a root if it begins with `/`. /// /// * On Windows, a path has a root if it: /// * has no prefix and begins with a separator, e.g. `\windows` /// * has a prefix followed by a separator, e.g. `c:\windows` but not `c:windows` /// * has any non-disk prefix, e.g. `\\server\share` /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// assert!(Path::new("/etc/passwd").has_root()); /// ``` pub fn has_root(&self) -> bool { self.inner.has_root() } /// Returns the `Path` without its final component, if there is one. /// /// Returns [`None`] if the path terminates in a root or prefix. /// /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("/foo/bar"); /// let parent = path.parent().unwrap(); /// assert_eq!(parent, Path::new("/foo")); /// /// let grand_parent = parent.parent().unwrap(); /// assert_eq!(grand_parent, Path::new("/")); /// assert_eq!(grand_parent.parent(), None); /// ``` pub fn parent(&self) -> Option<&Path> { self.inner.parent().map(|p| p.into()) } /// Produces an iterator over `Path` and its ancestors. /// /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`, /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns /// [`None`], the iterator will do likewise. The iterator will always yield at least one value, /// namely `&self`. /// /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html /// [`parent`]: struct.Path.html#method.parent /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let mut ancestors = Path::new("/foo/bar").ancestors(); /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar").into())); /// assert_eq!(ancestors.next(), Some(Path::new("/foo").into())); /// assert_eq!(ancestors.next(), Some(Path::new("/").into())); /// assert_eq!(ancestors.next(), None); /// ``` pub fn ancestors(&self) -> Ancestors<'_> { Ancestors { next: Some(&self) } } /// Returns the final component of the `Path`, if there is one. /// /// If the path is a normal file, this is the file name. If it's the path of a directory, this /// is the directory name. /// /// Returns [`None`] if the path terminates in `..`. /// /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// /// # Examples /// /// ``` /// use std::ffi::OsStr; /// /// use async_std::path::Path; /// /// assert_eq!(Some(OsStr::new("bin")), Path::new("/usr/bin/").file_name()); /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name()); /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name()); /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name()); /// assert_eq!(None, Path::new("foo.txt/..").file_name()); /// assert_eq!(None, Path::new("/").file_name()); /// ``` pub fn file_name(&self) -> Option<&OsStr> { self.inner.file_name() } /// Returns a path that becomes `self` when joined onto `base`. /// /// # Errors /// /// If `base` is not a prefix of `self` (i.e., [`starts_with`] /// returns `false`), returns [`Err`]. /// /// [`starts_with`]: #method.starts_with /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err /// /// # Examples /// /// ``` /// use async_std::path::{Path, PathBuf}; /// /// let path = Path::new("/test/haha/foo.txt"); /// /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt"))); /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt"))); /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt"))); /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new(""))); /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new(""))); /// assert_eq!(path.strip_prefix("test").is_ok(), false); /// assert_eq!(path.strip_prefix("/haha").is_ok(), false); /// /// let prefix = PathBuf::from("/test/"); /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt"))); /// ``` pub fn strip_prefix

(&self, base: P) -> Result<&Path, StripPrefixError> where P: AsRef, { Ok(self.inner.strip_prefix(base.as_ref())?.into()) } /// Determines whether `base` is a prefix of `self`. /// /// Only considers whole path components to match. /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("/etc/passwd"); /// /// assert!(path.starts_with("/etc")); /// assert!(path.starts_with("/etc/")); /// assert!(path.starts_with("/etc/passwd")); /// assert!(path.starts_with("/etc/passwd/")); /// /// assert!(!path.starts_with("/e")); /// ``` pub fn starts_with>(&self, base: P) -> bool { self.inner.starts_with(base.as_ref()) } /// Determines whether `child` is a suffix of `self`. /// /// Only considers whole path components to match. /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("/etc/passwd"); /// /// assert!(path.ends_with("passwd")); /// ``` pub fn ends_with>(&self, child: P) -> bool { self.inner.ends_with(child.as_ref()) } /// Extracts the stem (non-extension) portion of [`file_name`]. /// /// [`file_name`]: struct.Path.html#method.file_name /// /// The stem is: /// /// * [`None`], if there is no file name /// * The entire file name if there is no embedded `.` /// * The entire file name if the file name begins with `.` and has no other `.`s within /// * Otherwise, the portion of the file name before the final `.` /// /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("foo.rs"); /// /// assert_eq!("foo", path.file_stem().unwrap()); /// ``` pub fn file_stem(&self) -> Option<&OsStr> { self.inner.file_stem() } /// Extracts the extension of [`file_name`], if possible. /// /// The extension is: /// /// * [`None`], if there is no file name /// * [`None`], if there is no embedded `.` /// * [`None`], if the file name begins with `.` and has no other `.`s within /// * Otherwise, the portion of the file name after the final `.` /// /// [`file_name`]: struct.Path.html#method.file_name /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("foo.rs"); /// /// assert_eq!("rs", path.extension().unwrap()); /// ``` pub fn extension(&self) -> Option<&OsStr> { self.inner.extension() } /// Creates an owned [`PathBuf`] with `path` adjoined to `self`. /// /// See [`PathBuf::push`] for more details on what it means to adjoin a path. /// /// [`PathBuf`]: struct.PathBuf.html /// [`PathBuf::push`]: struct.PathBuf.html#method.push /// /// # Examples /// /// ``` /// use async_std::path::{Path, PathBuf}; /// /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd")); /// ``` pub fn join>(&self, path: P) -> PathBuf { self.inner.join(path.as_ref()).into() } /// Creates an owned [`PathBuf`] like `self` but with the given file name. /// /// See [`PathBuf::set_file_name`] for more details. /// /// [`PathBuf`]: struct.PathBuf.html /// [`PathBuf::set_file_name`]: struct.PathBuf.html#method.set_file_name /// /// # Examples /// /// ``` /// use async_std::path::{Path, PathBuf}; /// /// let path = Path::new("/tmp/foo.txt"); /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt")); /// /// let path = Path::new("/tmp"); /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var")); /// ``` pub fn with_file_name>(&self, file_name: S) -> PathBuf { self.inner.with_file_name(file_name).into() } /// Creates an owned [`PathBuf`] like `self` but with the given extension. /// /// See [`PathBuf::set_extension`] for more details. /// /// [`PathBuf`]: struct.PathBuf.html /// [`PathBuf::set_extension`]: struct.PathBuf.html#method.set_extension /// /// # Examples /// /// ``` /// use async_std::path::{Path, PathBuf}; /// /// let path = Path::new("foo.rs"); /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt")); /// ``` pub fn with_extension>(&self, extension: S) -> PathBuf { self.inner.with_extension(extension).into() } /// Produces an iterator over the [`Component`]s of the path. /// /// When parsing the path, there is a small amount of normalization: /// /// * Repeated separators are ignored, so `a/b` and `a//b` both have /// `a` and `b` as components. /// /// * Occurrences of `.` are normalized away, except if they are at the /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and /// `a/b` all have `a` and `b` as components, but `./a/b` starts with /// an additional [`CurDir`] component. /// /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent. /// /// Note that no other normalization takes place; in particular, `a/c` /// and `a/b/../c` are distinct, to account for the possibility that `b` /// is a symbolic link (so its parent isn't `a`). /// /// [`Component`]: enum.Component.html /// [`CurDir`]: enum.Component.html#variant.CurDir /// /// # Examples /// /// ``` /// use std::ffi::OsStr; /// /// use async_std::path::{Path, Component}; /// /// let mut components = Path::new("/tmp/foo.txt").components(); /// /// assert_eq!(components.next(), Some(Component::RootDir)); /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp")))); /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt")))); /// assert_eq!(components.next(), None); /// ``` pub fn components(&self) -> Components<'_> { Components { inner: self.inner.components(), } } /// Produces an iterator over the path's components viewed as [`OsStr`] /// slices. /// /// For more information about the particulars of how the path is separated /// into components, see [`components`]. /// /// [`components`]: #method.components /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html /// /// # Examples /// /// ``` /// use std::ffi::OsStr; /// /// use async_std::path::{self, Path}; /// /// let mut it = Path::new("/tmp/foo.txt").iter(); /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string()))); /// assert_eq!(it.next(), Some(OsStr::new("tmp"))); /// assert_eq!(it.next(), Some(OsStr::new("foo.txt"))); /// assert_eq!(it.next(), None) /// ``` pub fn iter(&self) -> Iter<'_> { Iter { inner: self.components(), } } /// Returns an object that implements [`Display`] for safely printing paths /// that may contain non-Unicode data. /// /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path = Path::new("/tmp/foo.rs"); /// /// println!("{}", path.display()); /// ``` pub fn display(&self) -> Display<'_> { self.inner.display() } /// Reads the metadata of a file or directory. /// /// This function will traverse symbolic links to query information about the /// destination file. /// /// This is an alias to [`fs::metadata`]. /// /// [`fs::metadata`]: ../fs/fn.metadata.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::path::Path; /// /// let path = Path::new("/Minas/tirith"); /// let metadata = path.metadata().await?; /// println!("{:?}", metadata.file_type()); /// # /// # Ok(()) }) } /// ``` #[cfg(not(target_os = "unknown"))] pub async fn metadata(&self) -> io::Result { fs::metadata(self).await } /// Reads the metadata of a file or directory without following symbolic links. /// /// This is an alias to [`fs::symlink_metadata`]. /// /// [`fs::symlink_metadata`]: ../fs/fn.symlink_metadata.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::path::Path; /// /// let path = Path::new("/Minas/tirith"); /// let metadata = path.symlink_metadata().await?; /// println!("{:?}", metadata.file_type()); /// # /// # Ok(()) }) } /// ``` #[cfg(not(target_os = "unknown"))] pub async fn symlink_metadata(&self) -> io::Result { fs::symlink_metadata(self).await } /// Returns the canonical form of a path. /// /// The returned path is in absolute form with all intermediate components normalized and /// symbolic links resolved. /// /// This is an alias to [`fs::canonicalize`]. /// /// [`fs::canonicalize`]: ../fs/fn.canonicalize.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::path::{Path, PathBuf}; /// /// let path = Path::new("/foo/test/../test/bar.rs"); /// assert_eq!(path.canonicalize().await?, PathBuf::from("/foo/test/bar.rs")); /// # /// # Ok(()) }) } /// ``` #[cfg(not(target_os = "unknown"))] pub async fn canonicalize(&self) -> io::Result { fs::canonicalize(self).await } /// Reads a symbolic link, returning the file that the link points to. /// /// This is an alias to [`fs::read_link`]. /// /// [`fs::read_link`]: ../fs/fn.read_link.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::path::Path; /// /// let path = Path::new("/laputa/sky_castle.rs"); /// let path_link = path.read_link().await?; /// # /// # Ok(()) }) } /// ``` #[cfg(not(target_os = "unknown"))] pub async fn read_link(&self) -> io::Result { fs::read_link(self).await } /// Returns a stream over the entries within a directory. /// /// The stream will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. New /// errors may be encountered after an iterator is initially constructed. /// /// This is an alias to [`fs::read_dir`]. /// /// [`io::Result`]: ../io/type.Result.html /// [`DirEntry`]: ../fs/struct.DirEntry.html /// [`fs::read_dir`]: ../fs/fn.read_dir.html /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::fs; /// use async_std::path::Path; /// use async_std::prelude::*; /// /// let path = Path::new("/laputa"); /// let mut dir = fs::read_dir(&path).await?; /// /// while let Some(res) = dir.next().await { /// let entry = res?; /// println!("{}", entry.file_name().to_string_lossy()); /// } /// # /// # Ok(()) }) } /// ``` #[cfg(not(target_os = "unknown"))] pub async fn read_dir(&self) -> io::Result { fs::read_dir(self).await } /// Returns `true` if the path points at an existing entity. /// /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// /// If you cannot access the directory containing the file, e.g., because of a /// permission error, this will return `false`. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::path::Path; /// assert_eq!(Path::new("does_not_exist.txt").exists().await, false); /// # /// # Ok(()) }) } /// ``` /// /// # See Also /// /// This is a convenience function that coerces errors to false. If you want to /// check errors, call [fs::metadata]. /// /// [fs::metadata]: ../fs/fn.metadata.html #[cfg(not(target_os = "unknown"))] pub async fn exists(&self) -> bool { fs::metadata(self).await.is_ok() } /// Returns `true` if the path exists on disk and is pointing at a regular file. /// /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// /// If you cannot access the directory containing the file, e.g., because of a /// permission error, this will return `false`. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::path::Path; /// assert_eq!(Path::new("./is_a_directory/").is_file().await, false); /// assert_eq!(Path::new("a_file.txt").is_file().await, true); /// # /// # Ok(()) }) } /// ``` /// /// # See Also /// /// This is a convenience function that coerces errors to false. If you want to /// check errors, call [fs::metadata] and handle its Result. Then call /// [fs::Metadata::is_file] if it was Ok. /// /// [fs::metadata]: ../fs/fn.metadata.html /// [fs::Metadata::is_file]: ../fs/struct.Metadata.html#method.is_file #[cfg(not(target_os = "unknown"))] pub async fn is_file(&self) -> bool { fs::metadata(self) .await .map(|m| m.is_file()) .unwrap_or(false) } /// Returns `true` if the path exists on disk and is pointing at a directory. /// /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `false`. /// /// If you cannot access the directory containing the file, e.g., because of a /// permission error, this will return `false`. /// /// # Examples /// /// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::path::Path; /// /// assert_eq!(Path::new("./is_a_directory/").is_dir().await, true); /// assert_eq!(Path::new("a_file.txt").is_dir().await, false); /// # /// # Ok(()) }) } /// ``` /// /// # See Also /// /// This is a convenience function that coerces errors to false. If you want to /// check errors, call [fs::metadata] and handle its Result. Then call /// [fs::Metadata::is_dir] if it was Ok. /// /// [fs::metadata]: ../fs/fn.metadata.html /// [fs::Metadata::is_dir]: ../fs/struct.Metadata.html#method.is_dir #[cfg(not(target_os = "unknown"))] pub async fn is_dir(&self) -> bool { fs::metadata(self) .await .map(|m| m.is_dir()) .unwrap_or(false) } /// Converts a [`Box`][`Box`] into a [`PathBuf`] without copying or /// allocating. /// /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html /// [`PathBuf`]: struct.PathBuf.html /// /// # Examples /// /// ``` /// use async_std::path::Path; /// /// let path: Box = Path::new("foo.txt").into(); /// let path_buf = path.into_path_buf(); /// ``` pub fn into_path_buf(self: Box) -> PathBuf { let rw = Box::into_raw(self) as *mut std::path::Path; let inner = unsafe { Box::from_raw(rw) }; inner.into_path_buf().into() } } impl From<&Path> for Box { fn from(path: &Path) -> Box { let boxed: Box = path.inner.into(); let rw = Box::into_raw(boxed) as *mut Path; unsafe { Box::from_raw(rw) } } } impl From<&Path> for Arc { /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Arc { let arc: Arc = Arc::from(s.as_os_str()); unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) } } } impl From<&Path> for Rc { #[inline] fn from(s: &Path) -> Rc { let rc: Rc = Rc::from(s.as_os_str()); unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) } } } impl ToOwned for Path { type Owned = PathBuf; fn to_owned(&self) -> PathBuf { self.to_path_buf() } } impl AsRef for Path { fn as_ref(&self) -> &OsStr { self.inner.as_ref() } } impl AsRef for Path { fn as_ref(&self) -> &Path { self } } impl AsRef for OsStr { fn as_ref(&self) -> &Path { Path::new(self) } } impl<'a> From<&'a Path> for Cow<'a, Path> { #[inline] fn from(s: &'a Path) -> Cow<'a, Path> { Cow::Borrowed(s) } } impl AsRef for Cow<'_, OsStr> { fn as_ref(&self) -> &Path { Path::new(self) } } impl AsRef for OsString { fn as_ref(&self) -> &Path { Path::new(self) } } impl AsRef for str { fn as_ref(&self) -> &Path { Path::new(self) } } impl AsRef for String { fn as_ref(&self) -> &Path { Path::new(self) } } impl AsRef for PathBuf { fn as_ref(&self) -> &Path { self } } impl<'a> IntoIterator for &'a PathBuf { type Item = &'a OsStr; type IntoIter = Iter<'a>; fn into_iter(self) -> Iter<'a> { self.iter() } } impl<'a> IntoIterator for &'a Path { type Item = &'a OsStr; type IntoIter = Iter<'a>; fn into_iter(self) -> Iter<'a> { self.iter() } } macro_rules! impl_cmp { ($lhs:ty, $rhs: ty) => { impl<'a, 'b> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { ::eq(self, other) } } impl<'a, 'b> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { ::eq(self, other) } } impl<'a, 'b> PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { ::partial_cmp(self, other) } } impl<'a, 'b> PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { ::partial_cmp(self, other) } } }; } impl_cmp!(PathBuf, Path); impl_cmp!(PathBuf, &'a Path); impl_cmp!(Cow<'a, Path>, Path); impl_cmp!(Cow<'a, Path>, &'b Path); impl_cmp!(Cow<'a, Path>, PathBuf); macro_rules! impl_cmp_os_str { ($lhs:ty, $rhs: ty) => { impl<'a, 'b> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { ::eq(self, other.as_ref()) } } impl<'a, 'b> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { ::eq(self.as_ref(), other) } } impl<'a, 'b> PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { ::partial_cmp(self, other.as_ref()) } } impl<'a, 'b> PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { ::partial_cmp(self.as_ref(), other) } } }; } impl_cmp_os_str!(PathBuf, OsStr); impl_cmp_os_str!(PathBuf, &'a OsStr); impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>); impl_cmp_os_str!(PathBuf, OsString); impl_cmp_os_str!(Path, OsStr); impl_cmp_os_str!(Path, &'a OsStr); impl_cmp_os_str!(Path, Cow<'a, OsStr>); impl_cmp_os_str!(Path, OsString); impl_cmp_os_str!(&'a Path, OsStr); impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>); impl_cmp_os_str!(&'a Path, OsString); impl<'a> From<&'a std::path::Path> for &'a Path { fn from(path: &'a std::path::Path) -> &'a Path { &Path::new(path.as_os_str()) } } impl<'a> Into<&'a std::path::Path> for &'a Path { fn into(self) -> &'a std::path::Path { std::path::Path::new(&self.inner) } } impl AsRef for Path { fn as_ref(&self) -> &std::path::Path { self.into() } } impl AsRef for std::path::Path { fn as_ref(&self) -> &Path { self.into() } } impl AsRef for std::path::PathBuf { fn as_ref(&self) -> &Path { let p: &std::path::Path = self.as_ref(); p.into() } } async-rs-async-std-57f61ae/src/path/pathbuf.rs000066400000000000000000000232271476537407000213410ustar00rootroot00000000000000use std::borrow::{Borrow, Cow}; use std::ffi::{OsStr, OsString}; use std::iter::{self, FromIterator}; use std::ops::Deref; #[cfg(feature = "unstable")] use std::pin::Pin; use std::rc::Rc; use std::str::FromStr; use std::sync::Arc; use crate::path::Path; #[cfg(feature = "unstable")] use crate::prelude::*; #[cfg(feature = "unstable")] use crate::stream::{self, FromStream, IntoStream}; /// This struct is an async version of [`std::path::PathBuf`]. /// /// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PathBuf { inner: std::path::PathBuf, } impl PathBuf { /// Allocates an empty `PathBuf`. /// /// # Examples /// /// ``` /// use async_std::path::PathBuf; /// /// let path = PathBuf::new(); /// ``` pub fn new() -> PathBuf { std::path::PathBuf::new().into() } /// Coerces to a [`Path`] slice. /// /// [`Path`]: struct.Path.html /// /// # Examples /// /// ``` /// use async_std::path::{Path, PathBuf}; /// /// let p = PathBuf::from("/test"); /// assert_eq!(Path::new("/test"), p.as_path()); /// ``` pub fn as_path(&self) -> &Path { self.inner.as_path().into() } /// Extends `self` with `path`. /// /// If `path` is absolute, it replaces the current path. /// /// On Windows: /// /// * if `path` has a root but no prefix (e.g., `\windows`), it /// replaces everything except for the prefix (if any) of `self`. /// * if `path` has a prefix but no root, it replaces `self`. /// /// # Examples /// /// Pushing a relative path extends the existing path: /// /// ``` /// use async_std::path::PathBuf; /// /// let mut path = PathBuf::from("/tmp"); /// path.push("file.bk"); /// assert_eq!(path, PathBuf::from("/tmp/file.bk")); /// ``` /// /// Pushing an absolute path replaces the existing path: /// /// ``` /// use async_std::path::PathBuf; /// /// let mut path = PathBuf::from("/tmp"); /// path.push("/etc"); /// assert_eq!(path, PathBuf::from("/etc")); /// ``` pub fn push>(&mut self, path: P) { self.inner.push(path.as_ref()) } /// Truncates `self` to [`self.parent`]. /// /// Returns `false` and does nothing if [`self.parent`] is [`None`]. /// Otherwise, returns `true`. /// /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// [`self.parent`]: struct.PathBuf.html#method.parent /// /// # Examples /// /// ``` /// use async_std::path::{Path, PathBuf}; /// /// let mut p = PathBuf::from("/test/test.rs"); /// /// p.pop(); /// assert_eq!(Path::new("/test"), p); /// p.pop(); /// assert_eq!(Path::new("/"), p); /// ``` pub fn pop(&mut self) -> bool { self.inner.pop() } /// Updates [`self.file_name`] to `file_name`. /// /// If [`self.file_name`] was [`None`], this is equivalent to pushing /// `file_name`. /// /// Otherwise it is equivalent to calling [`pop`] and then pushing /// `file_name`. The new path will be a sibling of the original path. /// (That is, it will have the same parent.) /// /// [`self.file_name`]: struct.PathBuf.html#method.file_name /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// [`pop`]: struct.PathBuf.html#method.pop /// /// # Examples /// /// ``` /// use async_std::path::PathBuf; /// /// let mut buf = PathBuf::from("/"); /// assert!(buf.file_name() == None); /// buf.set_file_name("bar"); /// assert!(buf == PathBuf::from("/bar")); /// assert!(buf.file_name().is_some()); /// buf.set_file_name("baz.txt"); /// assert!(buf == PathBuf::from("/baz.txt")); /// ``` pub fn set_file_name>(&mut self, file_name: S) { self.inner.set_file_name(file_name) } /// Updates [`self.extension`] to `extension`. /// /// Returns `false` and does nothing if [`self.file_name`] is [`None`], /// returns `true` and updates the extension otherwise. /// /// If [`self.extension`] is [`None`], the extension is added; otherwise /// it is replaced. /// /// [`self.file_name`]: struct.PathBuf.html#method.file_name /// [`self.extension`]: struct.PathBuf.html#method.extension /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// /// # Examples /// /// ``` /// use async_std::path::{Path, PathBuf}; /// /// let mut p = PathBuf::from("/feel/the"); /// /// p.set_extension("force"); /// assert_eq!(Path::new("/feel/the.force"), p.as_path()); /// /// p.set_extension("dark_side"); /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path()); /// ``` pub fn set_extension>(&mut self, extension: S) -> bool { self.inner.set_extension(extension) } /// Consumes the `PathBuf`, returning its internal [`OsString`] storage. /// /// [`OsString`]: https://doc.rust-lang.org/std/ffi/struct.OsString.html /// /// # Examples /// /// ``` /// use async_std::path::PathBuf; /// /// let p = PathBuf::from("/the/head"); /// let os_str = p.into_os_string(); /// ``` pub fn into_os_string(self) -> OsString { self.inner.into_os_string() } /// Converts this `PathBuf` into a [boxed][`Box`] [`Path`]. /// /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html /// [`Path`]: struct.Path.html pub fn into_boxed_path(self) -> Box { let rw = Box::into_raw(self.inner.into_boxed_path()) as *mut Path; unsafe { Box::from_raw(rw) } } } impl From> for PathBuf { fn from(boxed: Box) -> PathBuf { boxed.into_path_buf() } } impl From for Box { fn from(p: PathBuf) -> Box { p.into_boxed_path() } } impl Clone for Box { #[inline] fn clone(&self) -> Self { self.to_path_buf().into_boxed_path() } } impl> From<&T> for PathBuf { fn from(s: &T) -> PathBuf { PathBuf::from(s.as_ref().to_os_string()) } } impl From for PathBuf { fn from(s: OsString) -> PathBuf { PathBuf { inner: s.into() } } } impl From for OsString { fn from(path_buf: PathBuf) -> OsString { path_buf.inner.into() } } impl From for PathBuf { fn from(s: String) -> PathBuf { PathBuf::from(OsString::from(s)) } } impl FromStr for PathBuf { type Err = core::convert::Infallible; fn from_str(s: &str) -> Result { Ok(PathBuf::from(s)) } } impl> FromIterator

for PathBuf { fn from_iter>(iter: I) -> PathBuf { let mut buf = PathBuf::new(); buf.extend(iter); buf } } impl> iter::Extend

for PathBuf { fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |p| self.push(p.as_ref())); } } impl Deref for PathBuf { type Target = Path; fn deref(&self) -> &Path { Path::new(&self.inner) } } impl Borrow for PathBuf { fn borrow(&self) -> &Path { self.deref() } } impl<'a> From for Cow<'a, Path> { #[inline] fn from(s: PathBuf) -> Cow<'a, Path> { Cow::Owned(s) } } impl<'a> From<&'a PathBuf> for Cow<'a, Path> { #[inline] fn from(p: &'a PathBuf) -> Cow<'a, Path> { Cow::Borrowed(p.as_path()) } } impl<'a> From> for PathBuf { #[inline] fn from(p: Cow<'a, Path>) -> Self { p.into_owned() } } impl From for Arc { #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) } } } impl From for Rc { #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) } } } impl AsRef for PathBuf { fn as_ref(&self) -> &OsStr { self.inner.as_ref() } } #[cfg(feature = "unstable")] impl> stream::Extend

for PathBuf { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { pin_utils::pin_mut!(stream); while let Some(item) = stream.next().await { self.push(item.as_ref()); } }) } } #[cfg(feature = "unstable")] impl<'b, P: AsRef + 'b + Send> FromStream

for PathBuf { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = Self::new(); stream::extend(&mut out, stream).await; out }) } } impl From for PathBuf { fn from(path: std::path::PathBuf) -> PathBuf { PathBuf { inner: path } } } impl Into for PathBuf { fn into(self) -> std::path::PathBuf { self.inner } } impl AsRef for PathBuf { fn as_ref(&self) -> &std::path::Path { self.inner.as_ref() } } async-rs-async-std-57f61ae/src/pin/000077500000000000000000000000001476537407000171665ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/pin/mod.rs000066400000000000000000000002711476537407000203130ustar00rootroot00000000000000//! Types that pin data to its location in memory. //! //! For more documentation see [`std::pin`](https://doc.rust-lang.org/std/pin/index.html). #[doc(inline)] pub use std::pin::Pin; async-rs-async-std-57f61ae/src/prelude.rs000066400000000000000000000023141476537407000204060ustar00rootroot00000000000000//! The async prelude. //! //! The prelude re-exports most commonly used traits and macros from this crate. //! //! # Examples //! //! Import the prelude with: //! //! ``` //! # #[allow(unused_imports)] //! use async_std::prelude::*; //! ``` cfg_std! { #[doc(no_inline)] pub use std::future::Future; #[doc(no_inline)] pub use crate::stream::Stream; #[doc(inline)] pub use crate::future::future::FutureExt; #[doc(inline)] pub use crate::stream::stream::StreamExt; #[doc(no_inline)] pub use crate::io::BufRead as _; #[doc(no_inline)] pub use crate::io::Read as _; #[doc(no_inline)] pub use crate::io::Seek as _; #[doc(no_inline)] pub use crate::io::Write as _; #[doc(no_inline)] pub use crate::io::prelude::BufReadExt as _; #[doc(no_inline)] pub use crate::io::prelude::ReadExt as _; #[doc(no_inline)] pub use crate::io::prelude::SeekExt as _; #[doc(no_inline)] pub use crate::io::prelude::WriteExt as _; } cfg_default! { #[doc(no_inline)] pub use crate::task_local; } cfg_unstable! { #[doc(no_inline)] pub use crate::stream::DoubleEndedStream; #[doc(no_inline)] pub use crate::stream::ExactSizeStream; } async-rs-async-std-57f61ae/src/process.rs000066400000000000000000000022561476537407000204310ustar00rootroot00000000000000//! A module for working with processes. //! //! This module is mostly concerned with spawning and interacting with child processes, but it also //! provides abort and exit for terminating the current process. //! //! This is an async version of [`std::process`]. //! //! [`std::process`]: https://doc.rust-lang.org/std/process/index.html #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::ExitStatus; #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::Output; #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::Stdio; #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::Child; #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::ChildStderr; #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::ChildStdin; #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::ChildStdout; #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[doc(inline)] pub use async_process::Command; // Re-export functions. pub use std::process::{abort, exit, id}; async-rs-async-std-57f61ae/src/result/000077500000000000000000000000001476537407000177165ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/result/from_stream.rs000066400000000000000000000042041476537407000226020ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{FromStream, IntoStream}; impl FromStream> for Result where T: Send, E: Send, V: FromStream, { /// Takes each element in the stream: if it is an `Err`, no further /// elements are taken, and the `Err` is returned. Should no `Err` /// occur, a container with the values of each `Result` is returned. /// /// # Examples /// /// ``` /// # fn main() { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let v = stream::from_iter(vec![1, 2]); /// let res: Result, &'static str> = v.map(|x: u32| /// x.checked_add(1).ok_or("Overflow!") /// ).collect().await; /// assert_eq!(res, Ok(vec![2, 3])); /// # /// # }) } /// ``` #[inline] fn from_stream<'a, S: IntoStream> + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { // Using `take_while` here because it is able to stop the stream early // if a failure occurs let mut is_error = false; let mut found_error = None; let out: V = stream .take_while(|elem| { // Stop processing the stream on `Err` !is_error && (elem.is_ok() || { is_error = true; // Capture first `Err` true }) }) .filter_map(|elem| match elem { Ok(value) => Some(value), Err(err) => { found_error = Some(err); None } }) .collect() .await; if is_error { Err(found_error.unwrap()) } else { Ok(out) } }) } } async-rs-async-std-57f61ae/src/result/mod.rs000066400000000000000000000004061476537407000210430ustar00rootroot00000000000000//! The Rust core error handling type //! //! This module provides the `Result` type for returning and //! propagating errors. mod from_stream; #[allow(unused)] #[doc(inline)] pub use std::result::Result; cfg_unstable! { mod product; mod sum; } async-rs-async-std-57f61ae/src/result/product.rs000066400000000000000000000043441476537407000217510ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{Product, Stream}; impl Product> for Result where T: Product, { #[doc = r#" Takes each element in the `Stream`: if it is an `Err`, no further elements are taken, and the `Err` is returned. Should no `Err` occur, the product of all elements is returned. # Examples This multiplies every integer in a vector, rejecting the product if a negative element is encountered: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let v = stream::from_iter(vec![1, 2, 4]); let res: Result = v.map(|x| if x < 0 { Err("Negative element found") } else { Ok(x) }).product().await; assert_eq!(res, Ok(8)); # # }) } ``` "#] fn product<'a, S>(stream: S) -> Pin> + 'a>> where S: Stream> + 'a, { Box::pin(async move { // Using `take_while` here because it is able to stop the stream early // if a failure occurs let mut is_error = false; let mut found_error = None; let out = >::product( stream .take_while(|elem| { // Stop processing the stream on `Err` !is_error && (elem.is_ok() || { is_error = true; // Capture first `Err` true }) }) .filter_map(|elem| match elem { Ok(value) => Some(value), Err(err) => { found_error = Some(err); None } }), ) .await; if is_error { Err(found_error.unwrap()) } else { Ok(out) } }) } } async-rs-async-std-57f61ae/src/result/sum.rs000066400000000000000000000042721476537407000210750ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{Stream, Sum}; impl Sum> for Result where T: Sum, { #[doc = r#" Takes each element in the `Stream`: if it is an `Err`, no further elements are taken, and the `Err` is returned. Should no `Err` occur, the sum of all elements is returned. # Examples This sums up every integer in a vector, rejecting the sum if a negative element is encountered: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let v = stream::from_iter(vec![1, 2]); let res: Result = v.map(|x| if x < 0 { Err("Negative element found") } else { Ok(x) }).sum().await; assert_eq!(res, Ok(3)); # # }) } ``` "#] fn sum<'a, S>(stream: S) -> Pin> + 'a>> where S: Stream> + 'a, { Box::pin(async move { // Using `take_while` here because it is able to stop the stream early // if a failure occurs let mut is_error = false; let mut found_error = None; let out = >::sum( stream .take_while(|elem| { // Stop processing the stream on `Err` !is_error && (elem.is_ok() || { is_error = true; // Capture first `Err` true }) }) .filter_map(|elem| match elem { Ok(value) => Some(value), Err(err) => { found_error = Some(err); None } }), ) .await; if is_error { Err(found_error.unwrap()) } else { Ok(out) } }) } } async-rs-async-std-57f61ae/src/rt/000077500000000000000000000000001476537407000170255ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/rt/mod.rs000066400000000000000000000010371476537407000201530ustar00rootroot00000000000000//! The runtime. use std::env; use once_cell::sync::Lazy; /// Dummy runtime struct. pub struct Runtime {} /// The global runtime. pub static RUNTIME: Lazy = Lazy::new(|| { // Create an executor thread pool. let thread_name = env::var("ASYNC_STD_THREAD_NAME").unwrap_or_else(|_| "async-std/runtime".to_string()); 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())); Runtime {} }); async-rs-async-std-57f61ae/src/stream/000077500000000000000000000000001476537407000176735ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/stream/double_ended_stream/000077500000000000000000000000001476537407000236575ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/stream/double_ended_stream/mod.rs000066400000000000000000000155411476537407000250120ustar00rootroot00000000000000use crate::stream::Stream; use std::pin::Pin; use std::task::{Context, Poll}; mod next_back; mod nth_back; mod rfind; mod rfold; mod try_rfold; use next_back::NextBackFuture; use nth_back::NthBackFuture; use rfind::RFindFuture; use rfold::RFoldFuture; use try_rfold::TryRFoldFuture; /// A stream able to yield elements from both ends. /// /// Something that implements `DoubleEndedStream` has one extra capability /// over something that implements [`Stream`]: the ability to also take /// `Item`s from the back, as well as the front. /// /// [`Stream`]: trait.Stream.html #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait DoubleEndedStream: Stream { #[doc = r#" Attempts to receive the next item from the back of the stream. There are several possible return values: * `Poll::Pending` means this stream's next_back value is not ready yet. * `Poll::Ready(None)` means this stream has been exhausted. * `Poll::Ready(Some(item))` means `item` was received out of the stream. # Examples ``` # fn main() { async_std::task::block_on(async { # use std::pin::Pin; use async_std::prelude::*; use async_std::stream; use async_std::task::{Context, Poll}; fn increment( s: impl DoubleEndedStream + Unpin, ) -> impl DoubleEndedStream + Unpin { struct Increment(S); impl + Unpin> Stream for Increment { type Item = S::Item; fn poll_next( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { match Pin::new(&mut self.0).poll_next(cx) { Poll::Pending => Poll::Pending, Poll::Ready(None) => Poll::Ready(None), Poll::Ready(Some(item)) => Poll::Ready(Some(item + 1)), } } } impl + Unpin> DoubleEndedStream for Increment { fn poll_next_back( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { match Pin::new(&mut self.0).poll_next_back(cx) { Poll::Pending => Poll::Pending, Poll::Ready(None) => Poll::Ready(None), Poll::Ready(Some(item)) => Poll::Ready(Some(item + 1)), } } } Increment(s) } let mut s = increment(stream::once(7)); assert_eq!(s.next_back().await, Some(8)); assert_eq!(s.next_back().await, None); # # }) } ``` "#] fn poll_next_back(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; #[doc = r#" Advances the stream and returns the next value. Returns [`None`] when iteration is finished. Individual stream implementations may choose to resume iteration, and so calling `next()` again may or may not eventually start returning more values. [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::from_iter(vec![7u8]); assert_eq!(s.next_back().await, Some(7)); assert_eq!(s.next_back().await, None); # # }) } ``` "#] fn next_back(&mut self) -> NextBackFuture<'_, Self> where Self: Unpin, { NextBackFuture { stream: self } } #[doc = r#" Returns the nth element from the back of the stream. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::from_iter(vec![1u8, 2, 3, 4, 5]); let second = s.nth_back(1).await; assert_eq!(second, Some(4)); # # }) } ``` "#] fn nth_back(&mut self, n: usize) -> NthBackFuture<'_, Self> where Self: Unpin + Sized, { NthBackFuture::new(self, n) } #[doc = r#" Returns the first element from the right that matches the predicate. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::from_iter(vec![1u8, 2, 3, 4, 5]); let second = s.rfind(|v| v % 2 == 0).await; assert_eq!(second, Some(4)); # # }) } ``` "#] fn rfind

(&mut self, p: P) -> RFindFuture<'_, Self, P> where Self: Unpin + Sized, P: FnMut(&Self::Item) -> bool, { RFindFuture::new(self, p) } #[doc = r#" # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1u8, 2, 3, 4, 5]); let second = s.rfold(0, |acc, v| v + acc).await; assert_eq!(second, 15); # # }) } ``` "#] fn rfold(self, accum: B, f: F) -> RFoldFuture where Self: Sized, F: FnMut(B, Self::Item) -> B, { RFoldFuture::new(self, accum, f) } #[doc = r#" A combinator that applies a function as long as it returns successfully, producing a single, final value. Immediately returns the error when the function returns unsuccessfully. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1u8, 2, 3, 4, 5]); let sum = s.try_rfold(0, |acc, v| { if (acc+v) % 2 == 1 { Ok(v+3) } else { Err("fail") } }).await; assert_eq!(sum, Err("fail")); # # }) } ``` "#] fn try_rfold(self, accum: B, f: F) -> TryRFoldFuture where Self: Sized, F: FnMut(B, Self::Item) -> Result, { TryRFoldFuture::new(self, accum, f) } } async-rs-async-std-57f61ae/src/stream/double_ended_stream/next_back.rs000066400000000000000000000010151476537407000261600ustar00rootroot00000000000000use core::pin::Pin; use core::future::Future; use crate::stream::DoubleEndedStream; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct NextBackFuture<'a, T: Unpin + ?Sized> { pub(crate) stream: &'a mut T, } impl Future for NextBackFuture<'_, T> { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { Pin::new(&mut *self.stream).poll_next_back(cx) } } async-rs-async-std-57f61ae/src/stream/double_ended_stream/nth_back.rs000066400000000000000000000017751476537407000260100ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll}; use crate::stream::DoubleEndedStream; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct NthBackFuture<'a, S> { stream: &'a mut S, n: usize, } impl<'a, S> NthBackFuture<'a, S> { pub(crate) fn new(stream: &'a mut S, n: usize) -> Self { NthBackFuture { stream, n } } } impl<'a, S> Future for NthBackFuture<'a, S> where S: DoubleEndedStream + Sized + Unpin, { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next_back(cx)); match next { Some(v) => match self.n { 0 => Poll::Ready(Some(v)), _ => { self.n -= 1; cx.waker().wake_by_ref(); Poll::Pending } }, None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/double_ended_stream/rfind.rs000066400000000000000000000020111476537407000253210ustar00rootroot00000000000000use core::task::{Context, Poll}; use core::future::Future; use core::pin::Pin; use crate::stream::DoubleEndedStream; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct RFindFuture<'a, S, P> { stream: &'a mut S, p: P, } impl<'a, S, P> RFindFuture<'a, S, P> { pub(super) fn new(stream: &'a mut S, p: P) -> Self { RFindFuture { stream, p } } } impl Unpin for RFindFuture<'_, S, P> {} impl<'a, S, P> Future for RFindFuture<'a, S, P> where S: DoubleEndedStream + Unpin + Sized, P: FnMut(&S::Item) -> bool, { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let item = futures_core::ready!(Pin::new(&mut *self.stream).poll_next_back(cx)); match item { Some(v) if (&mut self.p)(&v) => Poll::Ready(Some(v)), Some(_) => { cx.waker().wake_by_ref(); Poll::Pending } None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/double_ended_stream/rfold.rs000066400000000000000000000023231476537407000253330ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; use crate::stream::DoubleEndedStream; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct RFoldFuture { #[pin] stream: S, f: F, acc: Option, } } impl RFoldFuture { pub(super) fn new(stream: S, init: B, f: F) -> Self { RFoldFuture { stream, f, acc: Some(init), } } } impl Future for RFoldFuture where S: DoubleEndedStream + Sized, F: FnMut(B, S::Item) -> B, { type Output = B; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next_back(cx)); match next { Some(v) => { let old = this.acc.take().unwrap(); let new = (this.f)(old, v); *this.acc = Some(new); } None => return Poll::Ready(this.acc.take().unwrap()), } } } } async-rs-async-std-57f61ae/src/stream/double_ended_stream/try_rfold.rs000066400000000000000000000025761476537407000262430ustar00rootroot00000000000000use crate::future::Future; use core::pin::Pin; use crate::task::{Context, Poll}; use pin_project_lite::pin_project; use crate::stream::DoubleEndedStream; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct TryRFoldFuture { #[pin] stream: S, f: F, acc: Option, } } impl TryRFoldFuture { pub(super) fn new(stream: S, init: T, f: F) -> Self { TryRFoldFuture { stream, f, acc: Some(init), } } } impl Future for TryRFoldFuture where S: DoubleEndedStream + Unpin, F: FnMut(T, S::Item) -> Result, { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next_back(cx)); match next { Some(v) => { let old = this.acc.take().unwrap(); let new = (this.f)(old, v); match new { Ok(o) => *this.acc = Some(o), Err(e) => return Poll::Ready(Err(e)), } } None => return Poll::Ready(Ok(this.acc.take().unwrap())), } } } } async-rs-async-std-57f61ae/src/stream/empty.rs000066400000000000000000000017541476537407000214060ustar00rootroot00000000000000use core::marker::PhantomData; use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; /// Creates a stream that doesn't yield any items. /// /// This `struct` is created by the [`empty`] function. See its /// documentation for more. /// /// [`empty`]: fn.empty.html /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut s = stream::empty::(); /// /// assert_eq!(s.next().await, None); /// # /// # }) /// ``` pub fn empty() -> Empty { Empty { _marker: PhantomData, } } /// A stream that doesn't yield any items. /// /// This stream is constructed by the [`empty`] function. /// /// [`empty`]: fn.empty.html #[derive(Debug)] pub struct Empty { _marker: PhantomData, } impl Stream for Empty { type Item = T; fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(None) } } async-rs-async-std-57f61ae/src/stream/exact_size_stream.rs000066400000000000000000000072351476537407000237610ustar00rootroot00000000000000pub use crate::stream::Stream; /// A stream that knows its exact length. /// /// Many [`Stream`]s don't know how many times they will iterate, but some do. /// If a stream knows how many times it can iterate, providing access to /// that information can be useful. For example, if you want to iterate /// backwards, a good start is to know where the end is. /// /// When implementing an `ExactSizeStream`, you must also implement /// [`Stream`]. When doing so, the implementation of [`size_hint`] *must* /// return the exact size of the stream. /// /// [`Stream`]: trait.Stream.html /// [`size_hint`]: trait.Stream.html#method.size_hint /// /// The [`len`] method has a default implementation, so you usually shouldn't /// implement it. However, you may be able to provide a more performant /// implementation than the default, so overriding it in this case makes sense. /// /// [`len`]: #method.len /// /// # Examples /// /// Basic usage: /// /// ``` /// // a finite range knows exactly how many times it will iterate /// let five = 0..5; /// /// assert_eq!(5, five.len()); /// ``` /// /// In the [module level docs][moddocs], we implemented an [`Stream`], /// `Counter`. Let's implement `ExactSizeStream` for it as well: /// /// [moddocs]: index.html /// /// ``` /// # use std::task::{Context, Poll}; /// # use std::pin::Pin; /// # use async_std::prelude::*; /// # struct Counter { /// # count: usize, /// # } /// # impl Counter { /// # fn new() -> Counter { /// # Counter { count: 0 } /// # } /// # } /// # impl Stream for Counter { /// # type Item = usize; /// # fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { /// # self.count += 1; /// # if self.count < 6 { /// # Poll::Ready(Some(self.count)) /// # } else { /// # Poll::Ready(None) /// # } /// # } /// # } /// # async_std::task::block_on(async { /// # /// impl ExactSizeStream for Counter { /// // We can easily calculate the remaining number of iterations. /// fn len(&self) -> usize { /// 5 - self.count /// } /// } /// /// // And now we can use it! /// /// let counter = Counter::new(); /// /// assert_eq!(5, counter.len()); /// # }); /// ``` #[allow(clippy::len_without_is_empty)] // ExactSizeIterator::is_empty is unstable #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait ExactSizeStream: Stream { /// Returns the exact number of times the stream will iterate. /// /// This method has a default implementation, so you usually should not /// implement it directly. However, if you can provide a more efficient /// implementation, you can do so. See the [trait-level] docs for an /// example. /// /// This function has the same safety guarantees as the [`size_hint`] /// function. /// /// [trait-level]: trait.ExactSizeStream.html /// [`size_hint`]: trait.Stream.html#method.size_hint /// /// # Examples /// /// Basic usage: /// /// ``` /// // a finite range knows exactly how many times it will iterate /// let five = 0..5; /// /// assert_eq!(5, five.len()); /// ``` fn len(&self) -> usize { let (lower, upper) = self.size_hint(); // Note: This assertion is overly defensive, but it checks the invariant // guaranteed by the trait. If this trait were rust-internal, // we could use debug_assert!; assert_eq! will check all Rust user // implementations too. assert_eq!(upper, Some(lower)); lower } } impl ExactSizeStream for &mut I { fn len(&self) -> usize { (**self).len() } } async-rs-async-std-57f61ae/src/stream/extend.rs000066400000000000000000000046161476537407000215370ustar00rootroot00000000000000use core::pin::Pin; use core::future::Future; use crate::stream::IntoStream; /// Extends a collection with the contents of a stream. /// /// Streams produce a series of values asynchronously, and collections can also be thought of as a /// series of values. The `Extend` trait bridges this gap, allowing you to extend a collection /// asynchronously by including the contents of that stream. When extending a collection with an /// already existing key, that entry is updated or, in the case of collections that permit multiple /// entries with equal keys, that entry is inserted. /// /// ## Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut v: Vec = vec![1, 2]; /// let s = stream::repeat(3usize).take(3); /// stream::Extend::extend(&mut v, s).await; /// /// assert_eq!(v, vec![1, 2, 3, 3, 3]); /// # /// # }) /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait Extend { /// Extends a collection with the contents of a stream. fn extend<'a, T: IntoStream + 'a>( &'a mut self, stream: T, ) -> Pin + 'a + Send>> where ::IntoStream: Send; } /// Extends a collection with the contents of a stream. /// /// Streams produce a series of values asynchronously, and collections can also be thought of as a /// series of values. The [`Extend`] trait bridges this gap, allowing you to extend a collection /// asynchronously by including the contents of that stream. When extending a collection with an /// already existing key, that entry is updated or, in the case of collections that permit multiple /// entries with equal keys, that entry is inserted. /// /// [`Extend`]: trait.Extend.html /// /// ## Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut v: Vec = vec![1, 2]; /// let s = stream::repeat(3usize).take(3); /// stream::extend(&mut v, s).await; /// /// assert_eq!(v, vec![1, 2, 3, 3, 3]); /// # /// # }) /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub async fn extend<'a, C, T, S>(collection: &mut C, stream: S) where C: Extend, S: IntoStream + 'a, ::IntoStream: Send, { Extend::extend(collection, stream).await } async-rs-async-std-57f61ae/src/stream/from_fn.rs000066400000000000000000000027541476537407000216770ustar00rootroot00000000000000use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; /// A stream that yields elements by calling a closure. /// /// This stream is created by the [`from_fn`] function. See its /// documentation for more. /// /// [`from_fn`]: fn.from_fn.html #[derive(Clone, Debug)] pub struct FromFn { f: F, } impl Unpin for FromFn {} /// Creates a new stream where to produce each new element a provided closure is called. /// /// This allows creating a custom stream with any behaviour without using the more verbose /// syntax of creating a dedicated type and implementing a `Stream` trait for it. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut count = 0u8; /// let s = stream::from_fn(|| { /// count += 1; /// if count > 3 { /// None /// } else { /// Some(count) /// } /// }); /// /// pin_utils::pin_mut!(s); /// /// assert_eq!(s.next().await, Some(1)); /// assert_eq!(s.next().await, Some(2)); /// assert_eq!(s.next().await, Some(3)); /// assert_eq!(s.next().await, None); /// # /// # }) /// ``` pub fn from_fn(f: F) -> FromFn where F: FnMut() -> Option, { FromFn { f } } impl Stream for FromFn where F: FnMut() -> Option, { type Item = T; fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { let item = (&mut self.f)(); Poll::Ready(item) } } async-rs-async-std-57f61ae/src/stream/from_iter.rs000066400000000000000000000030221476537407000222240ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; #[cfg(feature = "unstable")] use crate::stream::double_ended_stream::DoubleEndedStream; use crate::task::{Context, Poll}; pin_project! { /// A stream that was created from iterator. /// /// This stream is created by the [`from_iter`] function. /// See it documentation for more. /// /// [`from_iter`]: fn.from_iter.html #[derive(Clone, Debug)] pub struct FromIter { iter: I, } } /// Converts an iterator into a stream. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut s = stream::from_iter(vec![0, 1, 2, 3]); /// /// assert_eq!(s.next().await, Some(0)); /// assert_eq!(s.next().await, Some(1)); /// assert_eq!(s.next().await, Some(2)); /// assert_eq!(s.next().await, Some(3)); /// assert_eq!(s.next().await, None); /// # /// # }) /// ``` pub fn from_iter(iter: I) -> FromIter { FromIter { iter: iter.into_iter(), } } impl Stream for FromIter { type Item = I::Item; fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(self.iter.next()) } } #[cfg(feature = "unstable")] impl DoubleEndedStream for FromIter { fn poll_next_back(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(self.iter.next_back()) } } async-rs-async-std-57f61ae/src/stream/from_stream.rs000066400000000000000000000071651476537407000225700ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use crate::stream::IntoStream; /// Conversion from a `Stream`. /// /// By implementing `FromStream` for a type, you define how it will be created from a stream. /// This is common for types which describe a collection of some kind. /// /// See also: [`IntoStream`]. /// /// # Examples /// /// Basic usage: /// /// ``` /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream::{self, FromStream}; /// /// let five_fives = stream::repeat(5).take(5); /// /// let v = Vec::from_stream(five_fives).await; /// /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// # /// # Ok(()) }) } /// ``` /// /// Using `collect` to implicitly use `FromStream` /// /// ``` /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// let five_fives = stream::repeat(5).take(5); /// /// let v: Vec = five_fives.collect().await; /// /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// # /// # Ok(()) }) } /// ``` /// /// Implementing `FromStream` for your type: /// /// ``` /// use async_std::prelude::*; /// use async_std::stream::{self, FromStream, IntoStream}; /// use std::pin::Pin; /// /// // A sample collection, that's just a wrapper over Vec /// #[derive(Debug)] /// struct MyCollection(Vec); /// /// // Let's give it some methods so we can create one and add things /// // to it. /// impl MyCollection { /// fn new() -> MyCollection { /// MyCollection(Vec::new()) /// } /// /// fn add(&mut self, elem: i32) { /// self.0.push(elem); /// } /// } /// /// // and we'll implement FromIterator /// impl FromStream for MyCollection { /// fn from_stream<'a, S: IntoStream + 'a>( /// stream: S, /// ) -> Pin + 'a + Send>> /// where /// ::IntoStream: Send, /// { /// let stream = stream.into_stream(); /// /// Box::pin(async move { /// let mut c = MyCollection::new(); /// /// let mut v = vec![]; /// stream::extend(&mut v, stream).await; /// /// for i in v { /// c.add(i); /// } /// c /// }) /// } /// } /// /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// // Now we can make a new stream... /// let stream = stream::repeat(5).take(5); /// /// // ...and make a MyCollection out of it /// let c = MyCollection::from_stream(stream).await; /// /// assert_eq!(c.0, vec![5, 5, 5, 5, 5]); /// /// // collect works too! /// /// let stream = stream::repeat(5).take(5); /// let c: MyCollection = stream.collect().await; /// /// assert_eq!(c.0, vec![5, 5, 5, 5, 5]); /// # /// # Ok(()) }) } /// ``` /// /// [`IntoStream`]: trait.IntoStream.html #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait FromStream { /// Creates a value from a stream. /// /// # Examples /// /// Basic usage: /// /// ``` /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream::{self, FromStream}; /// /// let five_fives = stream::repeat(5).take(5); /// /// let v = Vec::from_stream(five_fives).await; /// /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// # /// # Ok(()) }) } /// ``` fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send; } async-rs-async-std-57f61ae/src/stream/fused_stream.rs000066400000000000000000000017011476537407000227210ustar00rootroot00000000000000use crate::stream::Stream; /// A stream that always continues to yield `None` when exhausted. /// /// Calling next on a fused stream that has returned `None` once is guaranteed /// to return [`None`] again. This trait should be implemented by all streams /// that behave this way because it allows optimizing [`Stream::fuse`]. /// /// Note: In general, you should not use `FusedStream` in generic bounds if /// you need a fused stream. Instead, you should just call [`Stream::fuse`] /// on the stream. If the stream is already fused, the additional [`Fuse`] /// wrapper will be a no-op with no performance penalty. /// /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// [`Stream::fuse`]: trait.Stream.html#method.fuse /// [`Fuse`]: struct.Fuse.html #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait FusedStream: Stream {} impl FusedStream for &mut S {} async-rs-async-std-57f61ae/src/stream/interval.rs000066400000000000000000000042231476537407000220660ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; use std::time::Duration; use crate::stream::Stream; use crate::utils::{timer_after, Timer}; /// Creates a new stream that yields at a set interval. /// /// The stream first yields after `dur`, and continues to yield every /// `dur` after that. The stream accounts for time elapsed between calls, and /// will adjust accordingly to prevent time skews. /// /// Each interval may be slightly longer than the specified duration, but never /// less. /// /// Note that intervals are not intended for high resolution timers, but rather /// they will likely fire some granularity after the exact instant that they're /// otherwise indicated to fire at. /// /// See also: [`task::sleep`]. /// /// [`task::sleep`]: ../task/fn.sleep.html /// /// # Examples /// /// Basic example: /// /// ```no_run /// use async_std::prelude::*; /// use async_std::stream; /// use std::time::Duration; /// /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// let mut interval = stream::interval(Duration::from_secs(4)); /// while let Some(_) = interval.next().await { /// println!("prints every four seconds"); /// } /// # /// # Ok(()) }) } /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub fn interval(dur: Duration) -> Interval { Interval { delay: timer_after(dur), interval: dur, } } /// A stream representing notifications at fixed interval /// /// This stream is created by the [`interval`] function. See its /// documentation for more. /// /// [`interval`]: fn.interval.html #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[derive(Debug)] pub struct Interval { delay: Timer, interval: Duration, } impl Stream for Interval { type Item = (); fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { if Pin::new(&mut self.delay).poll(cx).is_pending() { return Poll::Pending; } let interval = self.interval; let _ = std::mem::replace(&mut self.delay, timer_after(interval)); Poll::Ready(Some(())) } } async-rs-async-std-57f61ae/src/stream/into_stream.rs000066400000000000000000000017061476537407000225710ustar00rootroot00000000000000use crate::stream::Stream; /// Conversion into a `Stream`. /// /// By implementing `IntoIterator` for a type, you define how it will be /// converted to an iterator. This is common for types which describe a /// collection of some kind. /// /// [`from_stream`]: #tymethod.from_stream /// [`Stream`]: trait.Stream.html /// [`collect`]: trait.Stream.html#method.collect /// /// See also: [`FromStream`]. /// /// [`FromStream`]: trait.FromStream.html #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait IntoStream { /// The type of the elements being iterated over. type Item; /// Which kind of stream are we turning this into? type IntoStream: Stream; /// Creates a stream from a value. fn into_stream(self) -> Self::IntoStream; } impl IntoStream for I { type Item = I::Item; type IntoStream = I; #[inline] fn into_stream(self) -> I { self } } async-rs-async-std-57f61ae/src/stream/mod.rs000066400000000000000000000264171476537407000210320ustar00rootroot00000000000000//! Composable asynchronous iteration. //! //! This module is an async version of [`std::iter`]. //! //! If you've found yourself with an asynchronous collection of some kind, //! and needed to perform an operation on the elements of said collection, //! you'll quickly run into 'streams'. Streams are heavily used in idiomatic //! asynchronous Rust code, so it's worth becoming familiar with them. //! //! Before explaining more, let's talk about how this module is structured: //! //! # Organization //! //! This module is largely organized by type: //! //! * [Traits] are the core portion: these traits define what kind of streams //! exist and what you can do with them. The methods of these traits are worth //! putting some extra study time into. //! * [Functions] provide some helpful ways to create some basic streams. //! * [Structs] are often the return types of the various methods on this //! module's traits. You'll usually want to look at the method that creates //! the `struct`, rather than the `struct` itself. For more detail about why, //! see '[Implementing Stream](#implementing-stream)'. //! //! [Traits]: #traits //! [Functions]: #functions //! [Structs]: #structs //! //! That's it! Let's dig into streams. //! //! # Stream //! //! The heart and soul of this module is the [`Stream`] trait. The core of //! [`Stream`] looks like this: //! //! ``` //! #![allow(dead_code)] //! # use async_std::task::{Context, Poll}; //! # use std::pin::Pin; //! pub trait Stream { //! type Item; //! fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; //! } //! # impl Stream for () { //! # type Item = (); //! # fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Poll::Pending } //! # } //! ``` //! //! A stream has a method, [`next`], which when called, returns an //! [`Poll`]<[`Option`]`>`. [`next`] will return `Ready(Some(Item))` //! as long as there are elements, and once they've all been exhausted, will //! return `None` to indicate that iteration is finished. If we're waiting on //! something asynchronous to resolve `Pending` is returned. //! //! Individual streams may choose to resume iteration, and so calling //! [`next`] again may or may not eventually start returning `Ready(Some(Item))` //! again at some point. //! //! [`Stream`]'s full definition includes a number of other methods as well, //! but they are default methods, built on top of [`next`], and so you get //! them for free. //! //! Streams are also composable, and it's common to chain them together to do //! more complex forms of processing. See the [Adapters](#adapters) section //! below for more details. //! //! [`Poll`]: ../task/enum.Poll.html //! [`Stream`]: trait.Stream.html //! [`next`]: trait.Stream.html#tymethod.next //! [`Option`]: ../../std/option/enum.Option.html //! //! # The three forms of streaming //! //! There are three common methods which can create streams from a collection: //! //! * `stream()`, which iterates over `&T`. //! * `stream_mut()`, which iterates over `&mut T`. //! * `into_stream()`, which iterates over `T`. //! //! Various things in async-std may implement one or more of the //! three, where appropriate. //! //! # Implementing Stream //! //! Creating a stream of your own involves two steps: creating a `struct` to //! hold the stream's state, and then `impl`ementing [`Stream`] for that //! `struct`. This is why there are so many `struct`s in this module: there is //! one for each stream and iterator adapter. //! //! Let's make a stream named `Counter` which counts from `1` to `5`: //! //! ``` //! # use async_std::prelude::*; //! # use async_std::task::{Context, Poll}; //! # use std::pin::Pin; //! // First, the struct: //! //! /// A stream which counts from one to five //! struct Counter { //! count: usize, //! } //! //! // we want our count to start at one, so let's add a new() method to help. //! // This isn't strictly necessary, but is convenient. Note that we start //! // `count` at zero, we'll see why in `next()`'s implementation below. //! impl Counter { //! fn new() -> Counter { //! Counter { count: 0 } //! } //! } //! //! // Then, we implement `Stream` for our `Counter`: //! //! impl Stream for Counter { //! // we will be counting with usize //! type Item = usize; //! //! // poll_next() is the only required method //! fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { //! // Increment our count. This is why we started at zero. //! self.count += 1; //! //! // Check to see if we've finished counting or not. //! if self.count < 6 { //! Poll::Ready(Some(self.count)) //! } else { //! Poll::Ready(None) //! } //! } //! } //! //! // And now we can use it! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! let mut counter = Counter::new(); //! //! let x = counter.next().await.unwrap(); //! println!("{}", x); //! //! let x = counter.next().await.unwrap(); //! println!("{}", x); //! //! let x = counter.next().await.unwrap(); //! println!("{}", x); //! //! let x = counter.next().await.unwrap(); //! println!("{}", x); //! //! let x = counter.next().await.unwrap(); //! println!("{}", x); //! # //! # Ok(()) }) } //! ``` //! //! This will print `1` through `5`, each on their own line. //! //! Calling `next().await` this way gets repetitive. Rust has a construct which //! can call `next()` on your stream, until it reaches `None`. Let's go over //! that next. //! //! # while let Loops and IntoStream //! //! Rust's `while let` loop syntax is an idiomatic way to iterate over streams. Here's a basic //! example of `while let`: //! //! ``` //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! # use async_std::prelude::*; //! # use async_std::stream; //! let mut values = stream::from_iter(1u8..6); //! //! while let Some(x) = values.next().await { //! println!("{}", x); //! } //! # //! # Ok(()) }) } //! ``` //! //! This will print the numbers one through five, each on their own line. But //! you'll notice something here: we never called anything on our vector to //! produce a stream. What gives? //! //! There's a trait in the standard library for converting something into an //! stream: [`IntoStream`]. This trait has one method, [`into_stream`], //! which converts the thing implementing [`IntoStream`] into a stream. //! //! Unlike `std::iter::IntoIterator`, `IntoStream` does not have compiler //! support yet. This means that automatic conversions like with `for` loops //! doesn't occur yet, and `into_stream` or `from_iter` as above will always //! have to be called manually. //! //! [`IntoStream`]: trait.IntoStream.html //! [`into_stream`]: trait.IntoStream.html#tymethod.into_stream //! //! # Adapters //! //! Functions which take an [`Stream`] and return another [`Stream`] are //! often called 'stream adapters', as they are a form of the 'adapter //! pattern'. //! //! Common stream adapters include [`map`], [`take`], and [`filter`]. //! For more, see their documentation. //! //! [`map`]: trait.Stream.html#method.map //! [`take`]: trait.Stream.html#method.take //! [`filter`]: trait.Stream.html#method.filter //! //! # Laziness //! //! Streams (and stream [adapters](#adapters)) are *lazy*. This means that //! just creating a stream doesn't _do_ a whole lot. Nothing really happens //! until you call [`next`]. This is sometimes a source of confusion when //! creating a stream solely for its side effects. For example, the [`map`] //! method calls a closure on each element it iterates over: //! //! ``` //! # #![allow(unused_must_use)] //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! # use async_std::prelude::*; //! # use async_std::stream; //! let v = stream::repeat(1u8).take(5); //! v.map(|x| println!("{}", x)); //! # //! # Ok(()) }) } //! ``` //! //! This will not print any values, as we only created a stream, rather than //! using it. The compiler will warn us about this kind of behavior: //! //! ```text //! warning: unused result that must be used: streams are lazy and //! do nothing unless consumed //! ``` //! //! The idiomatic way to write a [`map`] for its side effects is to use a //! `while let` loop instead: //! //! ``` //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! # use async_std::prelude::*; //! # use async_std::stream; //! let mut v = stream::repeat(1u8).take(5); //! //! while let Some(x) = &v.next().await { //! println!("{}", x); //! } //! # //! # Ok(()) }) } //! ``` //! //! [`map`]: trait.Stream.html#method.map //! //! The two most common ways to evaluate a stream are to use a `while let` loop //! like this, or using the [`collect`] method to produce a new collection. //! //! [`collect`]: trait.Stream.html#method.collect //! //! # Infinity //! //! Streams do not have to be finite. As an example, a repeat stream is //! an infinite stream: //! //! ``` //! # use async_std::stream; //! let numbers = stream::repeat(1u8); //! ``` //! //! It is common to use the [`take`] stream adapter to turn an infinite //! stream into a finite one: //! //! ``` //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # //! # use async_std::prelude::*; //! # use async_std::stream; //! let numbers = stream::from_iter(0u8..); //! let mut five_numbers = numbers.take(5); //! //! while let Some(number) = five_numbers.next().await { //! println!("{}", number); //! } //! # //! # Ok(()) }) } //! ``` //! //! This will print the numbers `0` through `4`, each on their own line. //! //! Bear in mind that methods on infinite streams, even those for which a //! result can be determined mathematically in finite time, may not terminate. //! Specifically, methods such as [`min`], which in the general case require //! traversing every element in the stream, are likely not to return //! successfully for any infinite streams. //! //! ```ignore //! let ones = async_std::stream::repeat(1); //! let least = ones.min().await.unwrap(); // Oh no! An infinite loop! //! // `ones.min()` causes an infinite loop, so we won't reach this point! //! println!("The smallest number one is {}.", least); //! ``` //! //! [`std::iter`]: https://doc.rust-lang.org/std/iter/index.html //! [`take`]: trait.Stream.html#method.take //! [`min`]: trait.Stream.html#method.min pub use empty::{empty, Empty}; pub use from_fn::{from_fn, FromFn}; pub use from_iter::{from_iter, FromIter}; pub use once::{once, Once}; pub use repeat::{repeat, Repeat}; pub use repeat_with::{repeat_with, RepeatWith}; pub use stream::*; pub(crate) mod stream; mod empty; mod from_fn; mod from_iter; mod once; mod repeat; mod repeat_with; cfg_unstable! { mod double_ended_stream; mod exact_size_stream; mod extend; mod from_stream; mod fused_stream; mod interval; mod into_stream; mod pending; mod product; mod successors; mod sum; pub use double_ended_stream::DoubleEndedStream; pub use exact_size_stream::ExactSizeStream; pub use extend::{extend, Extend}; pub use from_stream::FromStream; pub use fused_stream::FusedStream; pub use interval::{interval, Interval}; pub use into_stream::IntoStream; pub use pending::{pending, Pending}; pub use product::Product; pub use stream::Merge; pub use successors::{successors, Successors}; pub use sum::Sum; } async-rs-async-std-57f61ae/src/stream/once.rs000066400000000000000000000024011476537407000211620ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; #[cfg(feature = "unstable")] use crate::stream::DoubleEndedStream; /// Creates a stream that yields a single item. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut s = stream::once(7); /// /// assert_eq!(s.next().await, Some(7)); /// assert_eq!(s.next().await, None); /// # /// # }) /// ``` pub fn once(t: T) -> Once { Once { value: Some(t) } } pin_project! { /// A stream that yields a single item. /// /// This stream is created by the [`once`] function. See its /// documentation for more. /// /// [`once`]: fn.once.html #[derive(Clone, Debug)] pub struct Once { value: Option, } } impl Stream for Once { type Item = T; fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(self.project().value.take()) } } #[cfg(feature = "unstable")] impl DoubleEndedStream for Once { fn poll_next_back(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(self.project().value.take()) } } async-rs-async-std-57f61ae/src/stream/pending.rs000066400000000000000000000026761476537407000217000ustar00rootroot00000000000000use core::marker::PhantomData; use core::pin::Pin; use core::task::{Context, Poll}; use crate::stream::{DoubleEndedStream, ExactSizeStream, FusedStream, Stream}; /// A stream that never returns any items. /// /// This stream is created by the [`pending`] function. See its /// documentation for more. /// /// [`pending`]: fn.pending.html #[derive(Debug)] pub struct Pending { _marker: PhantomData, } /// Creates a stream that never returns any items. /// /// The returned stream will always return `Pending` when polled. /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use std::time::Duration; /// /// use async_std::prelude::*; /// use async_std::stream; /// /// let dur = Duration::from_millis(100); /// let mut s = stream::pending::<()>().timeout(dur); /// /// let item = s.next().await; /// /// assert!(item.is_some()); /// assert!(item.unwrap().is_err()); /// /// # /// # }) /// ``` pub fn pending() -> Pending { Pending { _marker: PhantomData, } } impl Stream for Pending { type Item = T; fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Pending } } impl DoubleEndedStream for Pending { fn poll_next_back(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Pending } } impl FusedStream for Pending {} impl ExactSizeStream for Pending { fn len(&self) -> usize { 0 } } async-rs-async-std-57f61ae/src/stream/product.rs000066400000000000000000000040001476537407000217130ustar00rootroot00000000000000use core::pin::Pin; use core::future::Future; use crate::stream::Stream; /// Trait to represent types that can be created by multiplying the elements of a stream. /// /// This trait is used to implement the [`product`] method on streams. Types which /// implement the trait can be generated by the [`product`] method. Like /// [`FromStream`] this trait should rarely be called directly and instead /// interacted with through [`Stream::product`]. /// /// [`product`]: trait.Product.html#tymethod.product /// [`FromStream`]: trait.FromStream.html /// [`Stream::product`]: trait.Stream.html#method.product #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait Product: Sized { /// Method which takes a stream and generates `Self` from the elements by /// multiplying the items. fn product<'a, S>(stream: S) -> Pin + 'a>> where S: Stream + 'a; } use core::ops::Mul; use core::num::Wrapping; use crate::stream::stream::StreamExt; macro_rules! num_product { ($one:expr, $($a:ty)*) => ($( impl Product for $a { fn product<'a, S>(stream: S) -> Pin+ 'a>> where S: Stream + 'a, { Box::pin(async move { stream.fold($one, Mul::mul).await } ) } } impl<'a> Product<&'a $a> for $a { fn product<'b, S>(stream: S) -> Pin + 'b>> where S: Stream + 'b, { Box::pin(async move { stream.fold($one, Mul::mul).await } ) } } )*); } macro_rules! integer_product { ($($a:ty)*) => ( num_product!(1, $($a)*); num_product!(Wrapping(1), $(Wrapping<$a>)*); ); } macro_rules! float_product { ($($a:ty)*) => ( num_product!(1.0, $($a)*); ); } integer_product!{ i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } float_product!{ f32 f64 } async-rs-async-std-57f61ae/src/stream/repeat.rs000066400000000000000000000016721476537407000215270ustar00rootroot00000000000000use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; /// Creates a stream that yields the same item repeatedly. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut s = stream::repeat(7); /// /// assert_eq!(s.next().await, Some(7)); /// assert_eq!(s.next().await, Some(7)); /// # /// # }) /// ``` pub fn repeat(item: T) -> Repeat where T: Clone, { Repeat { item } } /// A stream that yields the same item repeatedly. /// /// This stream is created by the [`repeat`] function. See its /// documentation for more. /// /// [`repeat`]: fn.repeat.html #[derive(Clone, Debug)] pub struct Repeat { item: T, } impl Stream for Repeat { type Item = T; fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { Poll::Ready(Some(self.item.clone())) } } async-rs-async-std-57f61ae/src/stream/repeat_with.rs000066400000000000000000000034521476537407000225600ustar00rootroot00000000000000use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; /// A stream that repeats elements of type `T` endlessly by applying a provided closure. /// /// This stream is created by the [`repeat_with`] function. See its /// documentation for more. /// /// [`repeat_with`]: fn.repeat_with.html #[derive(Clone, Debug)] pub struct RepeatWith { f: F, } impl Unpin for RepeatWith {} /// Creates a new stream that repeats elements of type `A` endlessly by applying the provided closure. /// /// # Examples /// /// Basic usage: /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let s = stream::repeat_with(|| 1); /// /// pin_utils::pin_mut!(s); /// /// assert_eq!(s.next().await, Some(1)); /// assert_eq!(s.next().await, Some(1)); /// assert_eq!(s.next().await, Some(1)); /// assert_eq!(s.next().await, Some(1)); /// # }) /// ``` /// /// Going finite: /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut n = 1; /// let s = stream::repeat_with(|| { /// let item = n; /// n *= 2; /// item /// }) /// .take(4); /// /// pin_utils::pin_mut!(s); /// /// assert_eq!(s.next().await, Some(1)); /// assert_eq!(s.next().await, Some(2)); /// assert_eq!(s.next().await, Some(4)); /// assert_eq!(s.next().await, Some(8)); /// assert_eq!(s.next().await, None); /// # }) /// ``` pub fn repeat_with(repeater: F) -> RepeatWith where F: FnMut() -> T, { RepeatWith { f: repeater } } impl Stream for RepeatWith where F: FnMut() -> T, { type Item = T; fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { let item = (&mut self.f)(); Poll::Ready(Some(item)) } } async-rs-async-std-57f61ae/src/stream/stream/000077500000000000000000000000001476537407000211665ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/stream/stream/all.rs000066400000000000000000000025121476537407000223040ustar00rootroot00000000000000use core::marker::PhantomData; use core::pin::Pin; use core::future::Future; use crate::stream::Stream; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct AllFuture<'a, S, F, T> { pub(crate) stream: &'a mut S, pub(crate) f: F, pub(crate) _marker: PhantomData, } impl<'a, S, F, T> AllFuture<'a, S, F, T> { pub(crate) fn new(stream: &'a mut S, f: F) -> Self { Self { stream, f, _marker: PhantomData, } } } impl Unpin for AllFuture<'_, S, F, T> {} impl Future for AllFuture<'_, S, F, S::Item> where S: Stream + Unpin + Sized, F: FnMut(S::Item) -> bool, { type Output = bool; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); match next { Some(v) => { let result = (&mut self.f)(v); if result { // don't forget to wake this task again to pull the next item from stream cx.waker().wake_by_ref(); Poll::Pending } else { Poll::Ready(false) } } None => Poll::Ready(true), } } } async-rs-async-std-57f61ae/src/stream/stream/any.rs000066400000000000000000000025121476537407000223230ustar00rootroot00000000000000use core::marker::PhantomData; use core::pin::Pin; use core::future::Future; use crate::stream::Stream; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct AnyFuture<'a, S, F, T> { pub(crate) stream: &'a mut S, pub(crate) f: F, pub(crate) _marker: PhantomData, } impl<'a, S, F, T> AnyFuture<'a, S, F, T> { pub(crate) fn new(stream: &'a mut S, f: F) -> Self { Self { stream, f, _marker: PhantomData, } } } impl Unpin for AnyFuture<'_, S, F, T> {} impl Future for AnyFuture<'_, S, F, S::Item> where S: Stream + Unpin + Sized, F: FnMut(S::Item) -> bool, { type Output = bool; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); match next { Some(v) => { let result = (&mut self.f)(v); if result { Poll::Ready(true) } else { // don't forget to wake this task again to pull the next item from stream cx.waker().wake_by_ref(); Poll::Pending } } None => Poll::Ready(false), } } } async-rs-async-std-57f61ae/src/stream/stream/chain.rs000066400000000000000000000031031476537407000226130ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use super::fuse::Fuse; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that chains two streams one after another. /// /// This `struct` is created by the [`chain`] method on [`Stream`]. See its /// documentation for more. /// /// [`chain`]: trait.Stream.html#method.chain /// [`Stream`]: trait.Stream.html #[derive(Debug)] pub struct Chain { #[pin] first: Fuse, #[pin] second: Fuse, } } impl Chain { pub(super) fn new(first: S, second: U) -> Self { Self { first: first.fuse(), second: second.fuse(), } } } impl> Stream for Chain { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); if !this.first.done { let next = futures_core::ready!(this.first.as_mut().poll_next(cx)); if let Some(next) = next { return Poll::Ready(Some(next)); } } if !this.second.done { let next = futures_core::ready!(this.second.as_mut().poll_next(cx)); if let Some(next) = next { return Poll::Ready(Some(next)); } } if this.first.done && this.second.done { return Poll::Ready(None); } Poll::Pending } } async-rs-async-std-57f61ae/src/stream/stream/cloned.rs000066400000000000000000000013361476537407000230030ustar00rootroot00000000000000use crate::stream::Stream; use crate::task::{Context, Poll}; use pin_project_lite::pin_project; use core::pin::Pin; pin_project! { /// A stream that clones the elements of an underlying stream. #[derive(Debug)] pub struct Cloned { #[pin] stream: S, } } impl Cloned { pub(super) fn new(stream: S) -> Self { Self { stream } } } impl<'a, S, T: 'a> Stream for Cloned where S: Stream, T: Clone, { type Item = T; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); Poll::Ready(next.cloned()) } } async-rs-async-std-57f61ae/src/stream/stream/cmp.rs000066400000000000000000000055061476537407000223210ustar00rootroot00000000000000use core::cmp::Ordering; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use super::fuse::Fuse; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { // Lexicographically compares the elements of this `Stream` with those // of another using `Ord`. #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct CmpFuture { #[pin] l: Fuse, #[pin] r: Fuse, l_cache: Option, r_cache: Option, } } impl CmpFuture { pub(super) fn new(l: L, r: R) -> Self { Self { l: l.fuse(), r: r.fuse(), l_cache: None, r_cache: None, } } } impl Future for CmpFuture where L: Stream + Sized, R: Stream + Sized, L::Item: Ord, { type Output = Ordering; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { // Stream that completes earliest can be considered Less, etc let l_complete = this.l.done && this.l_cache.is_none(); let r_complete = this.r.done && this.r_cache.is_none(); if l_complete && r_complete { return Poll::Ready(Ordering::Equal); } else if l_complete { return Poll::Ready(Ordering::Less); } else if r_complete { return Poll::Ready(Ordering::Greater); } // Get next value if possible and necessary if !this.l.done && this.l_cache.is_none() { let l_next = futures_core::ready!(this.l.as_mut().poll_next(cx)); if let Some(item) = l_next { *this.l_cache = Some(item); } } if !this.r.done && this.r_cache.is_none() { let r_next = futures_core::ready!(this.r.as_mut().poll_next(cx)); if let Some(item) = r_next { *this.r_cache = Some(item); } } // Compare if both values are available. if this.l_cache.is_some() && this.r_cache.is_some() { let l_value = this.l_cache.take().unwrap(); let r_value = this.r_cache.take().unwrap(); let result = l_value.cmp(&r_value); if let Ordering::Equal = result { // Reset cache to prepare for next comparison *this.l_cache = None; *this.r_cache = None; } else { // Return non equal value return Poll::Ready(result); } } } } } async-rs-async-std-57f61ae/src/stream/stream/copied.rs000066400000000000000000000013351476537407000230010ustar00rootroot00000000000000use crate::stream::Stream; use crate::task::{Context, Poll}; use pin_project_lite::pin_project; use core::pin::Pin; pin_project! { /// A stream that copies the elements of an underlying stream. #[derive(Debug)] pub struct Copied { #[pin] stream: S, } } impl Copied { pub(super) fn new(stream: S) -> Self { Self { stream } } } impl<'a, S, T: 'a> Stream for Copied where S: Stream, T: Copy, { type Item = T; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); Poll::Ready(next.copied()) } } async-rs-async-std-57f61ae/src/stream/stream/count.rs000066400000000000000000000017671476537407000226770ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub struct CountFuture { #[pin] stream: S, count: usize, } } impl CountFuture { pub(crate) fn new(stream: S) -> Self { Self { stream, count: 0 } } } impl Future for CountFuture where S: Stream, { type Output = usize; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(_) => { cx.waker().wake_by_ref(); *this.count += 1; Poll::Pending } None => Poll::Ready(*this.count), } } } async-rs-async-std-57f61ae/src/stream/stream/cycle.rs000066400000000000000000000017221476537407000226350ustar00rootroot00000000000000use core::pin::Pin; use futures_core::ready; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that will repeatedly yield the same list of elements. #[derive(Debug)] pub struct Cycle { orig: S, #[pin] source: S, } } impl Cycle where S: Stream + Clone, { pub(crate) fn new(source: S) -> Self { Self { orig: source.clone(), source, } } } impl Stream for Cycle where S: Stream + Clone, { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); match ready!(this.source.as_mut().poll_next(cx)) { None => { this.source.set(this.orig.clone()); this.source.poll_next(cx) } item => Poll::Ready(item), } } } async-rs-async-std-57f61ae/src/stream/stream/delay.rs000066400000000000000000000017511476537407000226360ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use core::time::Duration; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; use crate::utils::{timer_after, Timer}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct Delay { #[pin] stream: S, #[pin] delay: Timer, delay_done: bool, } } impl Delay { pub(super) fn new(stream: S, dur: Duration) -> Self { Delay { stream, delay: timer_after(dur), delay_done: false, } } } impl Stream for Delay where S: Stream, { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); if !*this.delay_done { futures_core::ready!(this.delay.poll(cx)); *this.delay_done = true; } this.stream.poll_next(cx) } } async-rs-async-std-57f61ae/src/stream/stream/enumerate.rs000066400000000000000000000015361476537407000235260ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[derive(Debug)] pub struct Enumerate { #[pin] stream: S, i: usize, } } impl Enumerate { pub(super) fn new(stream: S) -> Self { Self { stream, i: 0 } } } impl Stream for Enumerate where S: Stream, { type Item = (usize, S::Item); fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(v) => { let ret = (*this.i, v); *this.i += 1; Poll::Ready(Some(ret)) } None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/stream/eq.rs000066400000000000000000000027061476537407000221460ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use super::fuse::Fuse; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { // Lexicographically compares the elements of this `Stream` with those // of another. #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct EqFuture { #[pin] l: Fuse, #[pin] r: Fuse, } } impl EqFuture where L::Item: PartialEq, { pub(super) fn new(l: L, r: R) -> Self { Self { l: l.fuse(), r: r.fuse(), } } } impl Future for EqFuture where L: Stream + Sized, R: Stream + Sized, L::Item: PartialEq, { type Output = bool; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { let l_val = futures_core::ready!(this.l.as_mut().poll_next(cx)); let r_val = futures_core::ready!(this.r.as_mut().poll_next(cx)); if this.l.done && this.r.done { return Poll::Ready(true); } match (l_val, r_val) { (Some(l), Some(r)) if l != r => { return Poll::Ready(false); } _ => {} } } } } async-rs-async-std-57f61ae/src/stream/stream/filter.rs000066400000000000000000000023661476537407000230300ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream to filter elements of another stream with a predicate. /// /// This `struct` is created by the [`filter`] method on [`Stream`]. See its /// documentation for more. /// /// [`filter`]: trait.Stream.html#method.filter /// [`Stream`]: trait.Stream.html #[derive(Debug)] pub struct Filter { #[pin] stream: S, predicate: P, } } impl Filter { pub(super) fn new(stream: S, predicate: P) -> Self { Self { stream, predicate, } } } impl Stream for Filter where S: Stream, P: FnMut(&S::Item) -> bool, { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(v) if (this.predicate)(&v) => Poll::Ready(Some(v)), Some(_) => { cx.waker().wake_by_ref(); Poll::Pending } None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/stream/filter_map.rs000066400000000000000000000017251476537407000236630ustar00rootroot00000000000000use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; use crate::stream::Stream; pin_project! { #[derive(Debug)] pub struct FilterMap { #[pin] stream: S, f: F, } } impl FilterMap { pub(crate) fn new(stream: S, f: F) -> Self { Self { stream, f } } } impl Stream for FilterMap where S: Stream, F: FnMut(S::Item) -> Option, { type Item = B; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(v) => match (this.f)(v) { Some(b) => Poll::Ready(Some(b)), None => { cx.waker().wake_by_ref(); Poll::Pending } }, None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/stream/find.rs000066400000000000000000000017441476537407000224620ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct FindFuture<'a, S, P> { stream: &'a mut S, p: P, } impl<'a, S, P> FindFuture<'a, S, P> { pub(super) fn new(stream: &'a mut S, p: P) -> Self { Self { stream, p } } } impl Unpin for FindFuture<'_, S, P> {} impl<'a, S, P> Future for FindFuture<'a, S, P> where S: Stream + Unpin + Sized, P: FnMut(&S::Item) -> bool, { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let item = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); match item { Some(v) if (&mut self.p)(&v) => Poll::Ready(Some(v)), Some(_) => { cx.waker().wake_by_ref(); Poll::Pending } None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/stream/find_map.rs000066400000000000000000000020531476537407000233110ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll}; use crate::stream::Stream; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct FindMapFuture<'a, S, F> { stream: &'a mut S, f: F, } impl<'a, S, F> FindMapFuture<'a, S, F> { pub(super) fn new(stream: &'a mut S, f: F) -> Self { Self { stream, f } } } impl Unpin for FindMapFuture<'_, S, F> {} impl<'a, S, B, F> Future for FindMapFuture<'a, S, F> where S: Stream + Unpin + Sized, F: FnMut(S::Item) -> Option, { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let item = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); match item { Some(v) => match (&mut self.f)(v) { Some(v) => Poll::Ready(Some(v)), None => { cx.waker().wake_by_ref(); Poll::Pending } }, None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/stream/flat_map.rs000066400000000000000000000033511476537407000233210ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::stream::map::Map; use crate::stream::stream::StreamExt; use crate::stream::{IntoStream, Stream}; use crate::task::{Context, Poll}; pin_project! { /// A stream that maps each element to a stream, and yields the elements of the produced /// streams. /// /// This `struct` is created by the [`flat_map`] method on [`Stream`]. See its /// documentation for more. /// /// [`flat_map`]: trait.Stream.html#method.flat_map /// [`Stream`]: trait.Stream.html pub struct FlatMap { #[pin] stream: Map, #[pin] inner_stream: Option, } } impl FlatMap where S: Stream, U: IntoStream, F: FnMut(S::Item) -> U, { pub(super) fn new(stream: S, f: F) -> Self { Self { stream: stream.map(f), inner_stream: None, } } } impl Stream for FlatMap where S: Stream, U: Stream, F: FnMut(S::Item) -> U, { type Item = U::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); loop { if let Some(inner) = this.inner_stream.as_mut().as_pin_mut() { match futures_core::ready!(inner.poll_next(cx)) { item @ Some(_) => return Poll::Ready(item), None => this.inner_stream.set(None), } } match futures_core::ready!(this.stream.as_mut().poll_next(cx)) { inner @ Some(_) => this.inner_stream.set(inner.map(IntoStream::into_stream)), None => return Poll::Ready(None), } } } } async-rs-async-std-57f61ae/src/stream/stream/flatten.rs000066400000000000000000000040471476537407000231760ustar00rootroot00000000000000use core::fmt; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::{IntoStream, Stream}; use crate::task::{Context, Poll}; pin_project! { /// A stream that flattens one level of nesting in an stream of things that can be turned into /// streams. /// /// This `struct` is created by the [`flatten`] method on [`Stream`]. See its /// documentation for more. /// /// [`flatten`]: trait.Stream.html#method.flatten /// [`Stream`]: trait.Stream.html pub struct Flatten where S: Stream, S::Item: IntoStream, { #[pin] stream: S, #[pin] inner_stream: Option<::IntoStream>, } } impl Flatten where S: Stream, S::Item: IntoStream, { pub(super) fn new(stream: S) -> Self { Self { stream, inner_stream: None, } } } impl Stream for Flatten where S: Stream, S::Item: IntoStream, U: Stream, { type Item = U::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); loop { if let Some(inner) = this.inner_stream.as_mut().as_pin_mut() { match futures_core::ready!(inner.poll_next(cx)) { item @ Some(_) => return Poll::Ready(item), None => this.inner_stream.set(None), } } match futures_core::ready!(this.stream.as_mut().poll_next(cx)) { inner @ Some(_) => this.inner_stream.set(inner.map(IntoStream::into_stream)), None => return Poll::Ready(None), } } } } impl fmt::Debug for Flatten where S: fmt::Debug + Stream, S::Item: IntoStream, U: fmt::Debug + Stream, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Flatten") .field("inner", &self.stream) .finish() } } async-rs-async-std-57f61ae/src/stream/stream/fold.rs000066400000000000000000000022051476537407000224570ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[derive(Debug)] pub struct FoldFuture { #[pin] stream: S, f: F, acc: Option, } } impl FoldFuture { pub(super) fn new(stream: S, init: B, f: F) -> Self { Self { stream, f, acc: Some(init), } } } impl Future for FoldFuture where S: Stream + Sized, F: FnMut(B, S::Item) -> B, { type Output = B; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); match next { Some(v) => { let old = this.acc.take().unwrap(); let new = (this.f)(old, v); *this.acc = Some(new); } None => return Poll::Ready(this.acc.take().unwrap()), } } } } async-rs-async-std-57f61ae/src/stream/stream/for_each.rs000066400000000000000000000016641476537407000233110ustar00rootroot00000000000000use core::pin::Pin; use core::future::Future; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct ForEachFuture { #[pin] stream: S, f: F, } } impl ForEachFuture { pub(super) fn new(stream: S, f: F) -> Self { Self { stream, f, } } } impl Future for ForEachFuture where S: Stream + Sized, F: FnMut(S::Item), { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); match next { Some(v) => (this.f)(v), None => return Poll::Ready(()), } } } } async-rs-async-std-57f61ae/src/stream/stream/fuse.rs000066400000000000000000000022271476537407000225010ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that yields `None` forever after the underlying stream yields `None` once. /// /// This `struct` is created by the [`fuse`] method on [`Stream`]. See its /// documentation for more. /// /// [`fuse`]: trait.Stream.html#method.fuse /// [`Stream`]: trait.Stream.html #[derive(Clone, Debug)] pub struct Fuse { #[pin] pub(crate) stream: S, pub(crate) done: bool, } } impl Fuse { pub(super) fn new(stream: S) -> Self { Self { stream, done: false, } } } impl Stream for Fuse { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); if *this.done { Poll::Ready(None) } else { let next = futures_core::ready!(this.stream.poll_next(cx)); if next.is_none() { *this.done = true; } Poll::Ready(next) } } } async-rs-async-std-57f61ae/src/stream/stream/ge.rs000066400000000000000000000023341476537407000221310ustar00rootroot00000000000000use core::cmp::Ordering; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use super::partial_cmp::PartialCmpFuture; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { // Determines if the elements of this `Stream` are lexicographically // greater than or equal to those of another. #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct GeFuture { #[pin] partial_cmp: PartialCmpFuture, } } impl GeFuture where L::Item: PartialOrd, { pub(super) fn new(l: L, r: R) -> Self { Self { partial_cmp: l.partial_cmp(r), } } } impl Future for GeFuture where L: Stream, R: Stream, L::Item: PartialOrd, { type Output = bool; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let result = futures_core::ready!(self.project().partial_cmp.poll(cx)); match result { Some(Ordering::Greater) | Some(Ordering::Equal) => Poll::Ready(true), _ => Poll::Ready(false), } } } async-rs-async-std-57f61ae/src/stream/stream/gt.rs000066400000000000000000000023101476537407000221420ustar00rootroot00000000000000use core::cmp::Ordering; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use super::partial_cmp::PartialCmpFuture; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { // Determines if the elements of this `Stream` are lexicographically // greater than those of another. #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct GtFuture { #[pin] partial_cmp: PartialCmpFuture, } } impl GtFuture where L::Item: PartialOrd, { pub(super) fn new(l: L, r: R) -> Self { Self { partial_cmp: l.partial_cmp(r), } } } impl Future for GtFuture where L: Stream + Sized, R: Stream + Sized, L::Item: PartialOrd, { type Output = bool; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let result = futures_core::ready!(self.project().partial_cmp.poll(cx)); match result { Some(Ordering::Greater) => Poll::Ready(true), _ => Poll::Ready(false), } } } async-rs-async-std-57f61ae/src/stream/stream/inspect.rs000066400000000000000000000021101476537407000231730ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that does something with each element of another stream. /// /// This `struct` is created by the [`inspect`] method on [`Stream`]. See its /// documentation for more. /// /// [`inspect`]: trait.Stream.html#method.inspect /// [`Stream`]: trait.Stream.html #[derive(Debug)] pub struct Inspect { #[pin] stream: S, f: F, } } impl Inspect { pub(super) fn new(stream: S, f: F) -> Self { Self { stream, f, } } } impl Stream for Inspect where S: Stream, F: FnMut(&S::Item), { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); Poll::Ready(next.map(|x| { (this.f)(&x); x })) } } async-rs-async-std-57f61ae/src/stream/stream/last.rs000066400000000000000000000017501476537407000225020ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct LastFuture { #[pin] stream: S, last: Option, } } impl LastFuture { pub(crate) fn new(stream: S) -> Self { Self { stream, last: None } } } impl Future for LastFuture where S: Stream + Unpin + Sized, S::Item: Copy, { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(new) => { cx.waker().wake_by_ref(); *this.last = Some(new); Poll::Pending } None => Poll::Ready(*this.last), } } } async-rs-async-std-57f61ae/src/stream/stream/le.rs000066400000000000000000000023431476537407000221360ustar00rootroot00000000000000use core::cmp::Ordering; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use super::partial_cmp::PartialCmpFuture; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// Determines if the elements of this `Stream` are lexicographically /// less or equal to those of another. #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct LeFuture { #[pin] partial_cmp: PartialCmpFuture, } } impl LeFuture where L::Item: PartialOrd, { pub(super) fn new(l: L, r: R) -> Self { Self { partial_cmp: l.partial_cmp(r), } } } impl Future for LeFuture where L: Stream + Sized, R: Stream + Sized, L::Item: PartialOrd, { type Output = bool; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let result = futures_core::ready!(self.project().partial_cmp.poll(cx)); match result { Some(Ordering::Less) | Some(Ordering::Equal) => Poll::Ready(true), _ => Poll::Ready(false), } } } async-rs-async-std-57f61ae/src/stream/stream/lt.rs000066400000000000000000000023021476537407000221500ustar00rootroot00000000000000use core::cmp::Ordering; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use super::partial_cmp::PartialCmpFuture; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { // Determines if the elements of this `Stream` are lexicographically // less than those of another. #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct LtFuture { #[pin] partial_cmp: PartialCmpFuture, } } impl LtFuture where L::Item: PartialOrd, { pub(super) fn new(l: L, r: R) -> Self { Self { partial_cmp: l.partial_cmp(r), } } } impl Future for LtFuture where L: Stream + Sized, R: Stream + Sized, L::Item: PartialOrd, { type Output = bool; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let result = futures_core::ready!(self.project().partial_cmp.poll(cx)); match result { Some(Ordering::Less) => Poll::Ready(true), _ => Poll::Ready(false), } } } async-rs-async-std-57f61ae/src/stream/stream/map.rs000066400000000000000000000014321476537407000223110ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that maps value of another stream with a function. #[derive(Debug)] pub struct Map { #[pin] stream: S, f: F, } } impl Map { pub(crate) fn new(stream: S, f: F) -> Self { Self { stream, f, } } } impl Stream for Map where S: Stream, F: FnMut(S::Item) -> B, { type Item = B; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); Poll::Ready(next.map(this.f)) } } async-rs-async-std-57f61ae/src/stream/stream/max.rs000066400000000000000000000024031476537407000223200ustar00rootroot00000000000000use core::cmp::{Ord, Ordering}; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct MaxFuture { #[pin] stream: S, max: Option, } } impl MaxFuture { pub(super) fn new(stream: S) -> Self { Self { stream, max: None } } } impl Future for MaxFuture where S: Stream, S::Item: Ord, { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(new) => { cx.waker().wake_by_ref(); match this.max.take() { None => *this.max = Some(new), Some(old) => match new.cmp(&old) { Ordering::Greater => *this.max = Some(new), _ => *this.max = Some(old), }, } Poll::Pending } None => Poll::Ready(this.max.take()), } } } async-rs-async-std-57f61ae/src/stream/stream/max_by.rs000066400000000000000000000026171476537407000230210ustar00rootroot00000000000000use core::cmp::Ordering; use core::pin::Pin; use core::future::Future; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct MaxByFuture { #[pin] stream: S, compare: F, max: Option, } } impl MaxByFuture { pub(super) fn new(stream: S, compare: F) -> Self { Self { stream, compare, max: None, } } } impl Future for MaxByFuture where S: Stream, F: FnMut(&S::Item, &S::Item) -> Ordering, { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(new) => { cx.waker().wake_by_ref(); match this.max.take() { None => *this.max = Some(new), Some(old) => match (this.compare)(&new, &old) { Ordering::Greater => *this.max = Some(new), _ => *this.max = Some(old), }, } Poll::Pending } None => Poll::Ready(this.max.take()), } } } async-rs-async-std-57f61ae/src/stream/stream/max_by_key.rs000066400000000000000000000031561476537407000236700ustar00rootroot00000000000000use core::cmp::Ordering; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct MaxByKeyFuture { #[pin] stream: S, max: Option<(T, T)>, key_by: K, } } impl MaxByKeyFuture { pub(super) fn new(stream: S, key_by: K) -> Self { Self { stream, max: None, key_by, } } } impl Future for MaxByKeyFuture where S: Stream, K: FnMut(&S::Item) -> S::Item, S::Item: Ord, { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { move |x| (f(&x), x) } let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(new) => { let (key, value) = key(this.key_by)(new); cx.waker().wake_by_ref(); match this.max.take() { None => *this.max = Some((key, value)), Some(old) => match key.cmp(&old.0) { Ordering::Greater => *this.max = Some((key, value)), _ => *this.max = Some(old), }, } Poll::Pending } None => Poll::Ready(this.max.take().map(|max| max.1)), } } } async-rs-async-std-57f61ae/src/stream/stream/merge.rs000066400000000000000000000034661476537407000226440ustar00rootroot00000000000000use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; use crate::stream::stream::StreamExt; use crate::stream::Fuse; use crate::stream::Stream; use crate::utils; pin_project! { /// A stream that merges two other streams into a single stream. /// /// This `struct` is created by the [`merge`] method on [`Stream`]. See its /// documentation for more. /// /// [`merge`]: trait.Stream.html#method.merge /// [`Stream`]: trait.Stream.html #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[derive(Debug)] pub struct Merge { #[pin] left: Fuse, #[pin] right: Fuse, } } impl Merge { pub(crate) fn new(left: L, right: R) -> Self { Self { left: left.fuse(), right: right.fuse(), } } } impl Stream for Merge where L: Stream, R: Stream, { type Item = T; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); if utils::random(2) == 0 { poll_next_in_order(this.left, this.right, cx) } else { poll_next_in_order(this.right, this.left, cx) } } } fn poll_next_in_order( first: Pin<&mut F>, second: Pin<&mut S>, cx: &mut Context<'_>, ) -> Poll> where F: Stream, S: Stream, { match first.poll_next(cx) { Poll::Ready(None) => second.poll_next(cx), Poll::Ready(item) => Poll::Ready(item), Poll::Pending => match second.poll_next(cx) { Poll::Ready(None) | Poll::Pending => Poll::Pending, Poll::Ready(item) => Poll::Ready(item), }, } } async-rs-async-std-57f61ae/src/stream/stream/min.rs000066400000000000000000000024001476537407000223130ustar00rootroot00000000000000use core::cmp::{Ord, Ordering}; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct MinFuture { #[pin] stream: S, min: Option, } } impl MinFuture { pub(super) fn new(stream: S) -> Self { Self { stream, min: None } } } impl Future for MinFuture where S: Stream, S::Item: Ord, { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(new) => { cx.waker().wake_by_ref(); match this.min.take() { None => *this.min = Some(new), Some(old) => match new.cmp(&old) { Ordering::Less => *this.min = Some(new), _ => *this.min = Some(old), }, } Poll::Pending } None => Poll::Ready(this.min.take()), } } } async-rs-async-std-57f61ae/src/stream/stream/min_by.rs000066400000000000000000000026511476537407000230150ustar00rootroot00000000000000use core::cmp::Ordering; use core::pin::Pin; use core::future::Future; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct MinByFuture { #[pin] stream: S, compare: F, min: Option, } } impl MinByFuture { pub(super) fn new(stream: S, compare: F) -> Self { Self { stream, compare, min: None, } } } impl Future for MinByFuture where S: Stream + Unpin + Sized, S::Item: Copy, F: FnMut(&S::Item, &S::Item) -> Ordering, { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(new) => { cx.waker().wake_by_ref(); match this.min.take() { None => *this.min = Some(new), Some(old) => match (this.compare)(&new, &old) { Ordering::Less => *this.min = Some(new), _ => *this.min = Some(old), }, } Poll::Pending } None => Poll::Ready(*this.min), } } } async-rs-async-std-57f61ae/src/stream/stream/min_by_key.rs000066400000000000000000000031531476537407000236630ustar00rootroot00000000000000use core::cmp::Ordering; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct MinByKeyFuture { #[pin] stream: S, min: Option<(T, T)>, key_by: K, } } impl MinByKeyFuture { pub(super) fn new(stream: S, key_by: K) -> Self { Self { stream, min: None, key_by, } } } impl Future for MinByKeyFuture where S: Stream, K: FnMut(&S::Item) -> S::Item, S::Item: Ord, { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { move |x| (f(&x), x) } let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(new) => { let (key, value) = key(this.key_by)(new); cx.waker().wake_by_ref(); match this.min.take() { None => *this.min = Some((key, value)), Some(old) => match key.cmp(&old.0) { Ordering::Less => *this.min = Some((key, value)), _ => *this.min = Some(old), }, } Poll::Pending } None => Poll::Ready(this.min.take().map(|min| min.1)), } } } async-rs-async-std-57f61ae/src/stream/stream/mod.rs000066400000000000000000001623131476537407000223210ustar00rootroot00000000000000//! Asynchronous iteration. //! //! This module is an async version of [`std::iter`]. //! //! [`std::iter`]: https://doc.rust-lang.org/std/iter/index.html //! //! # Examples //! //! ``` //! # async_std::task::block_on(async { //! # //! use async_std::prelude::*; //! use async_std::stream; //! //! let mut s = stream::repeat(9).take(3); //! //! while let Some(v) = s.next().await { //! assert_eq!(v, 9); //! } //! # //! # }) //! ``` mod all; mod any; mod chain; mod cloned; mod cmp; mod copied; mod cycle; mod enumerate; mod eq; mod filter; mod filter_map; mod find; mod find_map; mod fold; mod for_each; mod fuse; mod ge; mod gt; mod inspect; mod last; mod le; mod lt; mod map; mod max; mod max_by; mod max_by_key; mod min; mod min_by; mod min_by_key; mod ne; mod next; mod nth; mod partial_cmp; mod position; mod scan; mod skip; mod skip_while; mod step_by; mod take; mod take_while; mod try_fold; mod try_for_each; mod zip; use all::AllFuture; use any::AnyFuture; use cmp::CmpFuture; use cycle::Cycle; use enumerate::Enumerate; use eq::EqFuture; use filter_map::FilterMap; use find::FindFuture; use find_map::FindMapFuture; use fold::FoldFuture; use for_each::ForEachFuture; use ge::GeFuture; use gt::GtFuture; use last::LastFuture; use le::LeFuture; use lt::LtFuture; use max::MaxFuture; use max_by::MaxByFuture; use max_by_key::MaxByKeyFuture; use min::MinFuture; use min_by::MinByFuture; use min_by_key::MinByKeyFuture; use ne::NeFuture; use next::NextFuture; use nth::NthFuture; use partial_cmp::PartialCmpFuture; use position::PositionFuture; use try_fold::TryFoldFuture; use try_for_each::TryForEachFuture; pub use chain::Chain; pub use cloned::Cloned; pub use copied::Copied; pub use filter::Filter; pub use fuse::Fuse; pub use inspect::Inspect; pub use map::Map; pub use scan::Scan; pub use skip::Skip; pub use skip_while::SkipWhile; pub use step_by::StepBy; pub use take::Take; pub use take_while::TakeWhile; pub use zip::Zip; use core::cmp::Ordering; cfg_unstable! { use core::future::Future; use core::pin::Pin; use core::time::Duration; use crate::stream::into_stream::IntoStream; use crate::stream::{FromStream, Product, Sum}; use crate::stream::Extend; use count::CountFuture; use partition::PartitionFuture; use unzip::UnzipFuture; pub use merge::Merge; pub use flatten::Flatten; pub use flat_map::FlatMap; pub use timeout::{TimeoutError, Timeout}; pub use throttle::Throttle; pub use delay::Delay; mod count; mod merge; mod flatten; mod flat_map; mod partition; mod timeout; mod throttle; mod delay; mod unzip; } pub use futures_core::stream::Stream as Stream; #[doc = r#" Extension methods for [`Stream`]. [`Stream`]: ../stream/trait.Stream.html "#] pub trait StreamExt: Stream { #[doc = r#" Advances the stream and returns the next value. Returns [`None`] when iteration is finished. Individual stream implementations may choose to resume iteration, and so calling `next()` again may or may not eventually start returning more values. [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::once(7); assert_eq!(s.next().await, Some(7)); assert_eq!(s.next().await, None); # # }) } ``` "#] fn next(&mut self) -> NextFuture<'_, Self> where Self: Unpin, { NextFuture { stream: self } } #[doc = r#" Creates a stream that yields its first `n` elements. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::repeat(9).take(3); while let Some(v) = s.next().await { assert_eq!(v, 9); } # # }) } ``` "#] fn take(self, n: usize) -> Take where Self: Sized, { Take::new(self, n) } #[doc = r#" Creates a stream that yields elements based on a predicate. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1, 2, 3, 4]); let mut s = s.take_while(|x| x < &3 ); assert_eq!(s.next().await, Some(1)); assert_eq!(s.next().await, Some(2)); assert_eq!(s.next().await, None); # # }) } ``` "#] fn take_while

(self, predicate: P) -> TakeWhile where Self: Sized, P: FnMut(&Self::Item) -> bool, { TakeWhile::new(self, predicate) } #[doc = r#" Limit the amount of items yielded per timeslice in a stream. This stream does not drop any items, but will only limit the rate at which items pass through. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; use std::time::{Duration, Instant}; let start = Instant::now(); // emit value every 5 milliseconds let s = stream::interval(Duration::from_millis(5)).take(2); // throttle for 10 milliseconds let mut s = s.throttle(Duration::from_millis(10)); s.next().await; assert!(start.elapsed().as_millis() >= 5); s.next().await; assert!(start.elapsed().as_millis() >= 15); s.next().await; assert!(start.elapsed().as_millis() >= 25); # # }) } ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn throttle(self, d: Duration) -> Throttle where Self: Sized, { Throttle::new(self, d) } #[doc = r#" Creates a stream that yields each `step`th element. # Panics This method will panic if the given step is `0`. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![0u8, 1, 2, 3, 4]); let mut stepped = s.step_by(2); assert_eq!(stepped.next().await, Some(0)); assert_eq!(stepped.next().await, Some(2)); assert_eq!(stepped.next().await, Some(4)); assert_eq!(stepped.next().await, None); # # }) } ``` "#] fn step_by(self, step: usize) -> StepBy where Self: Sized, { StepBy::new(self, step) } #[doc = r#" Takes two streams and creates a new stream over both in sequence. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let first = stream::from_iter(vec![0u8, 1]); let second = stream::from_iter(vec![2, 3]); let mut c = first.chain(second); assert_eq!(c.next().await, Some(0)); assert_eq!(c.next().await, Some(1)); assert_eq!(c.next().await, Some(2)); assert_eq!(c.next().await, Some(3)); assert_eq!(c.next().await, None); # # }) } ``` "#] fn chain(self, other: U) -> Chain where Self: Sized, U: Stream + Sized, { Chain::new(self, other) } #[doc = r#" Creates an stream which copies all of its elements. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let v = stream::from_iter(vec![&1, &2, &3]); let mut v_cloned = v.cloned(); assert_eq!(v_cloned.next().await, Some(1)); assert_eq!(v_cloned.next().await, Some(2)); assert_eq!(v_cloned.next().await, Some(3)); assert_eq!(v_cloned.next().await, None); # # }) } ``` "#] fn cloned<'a, T>(self) -> Cloned where Self: Sized + Stream, T: Clone + 'a, { Cloned::new(self) } #[doc = r#" Creates an stream which copies all of its elements. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![&1, &2, &3]); let mut s_copied = s.copied(); assert_eq!(s_copied.next().await, Some(1)); assert_eq!(s_copied.next().await, Some(2)); assert_eq!(s_copied.next().await, Some(3)); assert_eq!(s_copied.next().await, None); # # }) } ``` "#] fn copied<'a, T>(self) -> Copied where Self: Sized + Stream, T: Copy + 'a, { Copied::new(self) } #[doc = r#" Creates a stream that yields the provided values infinitely and in order. # Examples Basic usage: ``` # async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::once(7).cycle(); assert_eq!(s.next().await, Some(7)); assert_eq!(s.next().await, Some(7)); assert_eq!(s.next().await, Some(7)); assert_eq!(s.next().await, Some(7)); assert_eq!(s.next().await, Some(7)); # # }) ``` "#] fn cycle(self) -> Cycle where Self: Clone + Sized, { Cycle::new(self) } #[doc = r#" Creates a stream that gives the current element's count as well as the next value. # Overflow behaviour. This combinator does no guarding against overflows. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec!['a', 'b', 'c']); let mut s = s.enumerate(); assert_eq!(s.next().await, Some((0, 'a'))); assert_eq!(s.next().await, Some((1, 'b'))); assert_eq!(s.next().await, Some((2, 'c'))); assert_eq!(s.next().await, None); # # }) } ``` "#] fn enumerate(self) -> Enumerate where Self: Sized, { Enumerate::new(self) } #[doc = r#" Creates a stream that is delayed before it starts yielding items. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; use std::time::{Duration, Instant}; let start = Instant::now(); let mut s = stream::from_iter(vec![0u8, 1, 2]).delay(Duration::from_millis(200)); assert_eq!(s.next().await, Some(0)); // The first time will take more than 200ms due to delay. assert!(start.elapsed().as_millis() >= 200); assert_eq!(s.next().await, Some(1)); // There will be no delay after the first time. assert!(start.elapsed().as_millis() < 400); assert_eq!(s.next().await, Some(2)); assert!(start.elapsed().as_millis() < 400); assert_eq!(s.next().await, None); assert!(start.elapsed().as_millis() < 400); # # }) } ``` "#] #[cfg(any(feature = "unstable", feature = "docs"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn delay(self, dur: std::time::Duration) -> Delay where Self: Sized, { Delay::new(self, dur) } #[doc = r#" Takes a closure and creates a stream that calls that closure on every element of this stream. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1, 2, 3]); let mut s = s.map(|x| 2 * x); assert_eq!(s.next().await, Some(2)); assert_eq!(s.next().await, Some(4)); assert_eq!(s.next().await, Some(6)); assert_eq!(s.next().await, None); # # }) } ``` "#] fn map(self, f: F) -> Map where Self: Sized, F: FnMut(Self::Item) -> B, { Map::new(self, f) } #[doc = r#" A combinator that does something with each element in the stream, passing the value on. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1, 2, 3, 4, 5]); let sum = s .inspect(|x| println!("about to filter {}", x)) .filter(|x| x % 2 == 0) .inspect(|x| println!("made it through filter: {}", x)) .fold(0, |sum, i| sum + i) .await; assert_eq!(sum, 6); # # }) } ``` "#] fn inspect(self, f: F) -> Inspect where Self: Sized, F: FnMut(&Self::Item), { Inspect::new(self, f) } #[doc = r#" Returns the last element of the stream. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1, 2, 3]); let last = s.last().await; assert_eq!(last, Some(3)); # # }) } ``` An empty stream will return `None`: ``` # fn main() { async_std::task::block_on(async { # use async_std::stream; use crate::async_std::prelude::*; let s = stream::empty::<()>(); let last = s.last().await; assert_eq!(last, None); # # }) } ``` "#] fn last( self, ) -> LastFuture where Self: Sized, { LastFuture::new(self) } #[doc = r#" Creates a stream which ends after the first `None`. After a stream returns `None`, future calls may or may not yield `Some(T)` again. `fuse()` adapts an iterator, ensuring that after a `None` is given, it will always return `None` forever. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::once(1).fuse(); assert_eq!(s.next().await, Some(1)); assert_eq!(s.next().await, None); assert_eq!(s.next().await, None); # # }) } ``` "#] fn fuse(self) -> Fuse where Self: Sized, { Fuse::new(self) } #[doc = r#" Creates a stream that uses a predicate to determine if an element should be yielded. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1, 2, 3, 4]); let mut s = s.filter(|i| i % 2 == 0); assert_eq!(s.next().await, Some(2)); assert_eq!(s.next().await, Some(4)); assert_eq!(s.next().await, None); # # }) } ``` "#] fn filter

(self, predicate: P) -> Filter where Self: Sized, P: FnMut(&Self::Item) -> bool, { Filter::new(self, predicate) } #[doc= r#" Creates an stream that works like map, but flattens nested structure. # Examples Basic usage: ``` # async_std::task::block_on(async { use async_std::prelude::*; use async_std::stream; let words = stream::from_iter(&["alpha", "beta", "gamma"]); let merged: String = words .flat_map(|s| stream::from_iter(s.chars())) .collect().await; assert_eq!(merged, "alphabetagamma"); let d3 = stream::from_iter(&[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]); let d1: Vec<_> = d3 .flat_map(|item| stream::from_iter(item)) .flat_map(|item| stream::from_iter(item)) .collect().await; assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]); # }); ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn flat_map(self, f: F) -> FlatMap where Self: Sized, U: IntoStream, F: FnMut(Self::Item) -> U, { FlatMap::new(self, f) } #[doc = r#" Creates an stream that flattens nested structure. # Examples Basic usage: ``` # async_std::task::block_on(async { use async_std::prelude::*; use async_std::stream; let inner1 = stream::from_iter(vec![1u8,2,3]); let inner2 = stream::from_iter(vec![4u8,5,6]); let s = stream::from_iter(vec![inner1, inner2]); let v: Vec<_> = s.flatten().collect().await; assert_eq!(v, vec![1,2,3,4,5,6]); # }); "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn flatten(self) -> Flatten where Self: Sized, Self::Item: IntoStream, { Flatten::new(self) } #[doc = r#" Both filters and maps a stream. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec!["1", "lol", "3", "NaN", "5"]); let mut parsed = s.filter_map(|a| a.parse::().ok()); let one = parsed.next().await; assert_eq!(one, Some(1)); let three = parsed.next().await; assert_eq!(three, Some(3)); let five = parsed.next().await; assert_eq!(five, Some(5)); let end = parsed.next().await; assert_eq!(end, None); # # }) } ``` "#] fn filter_map(self, f: F) -> FilterMap where Self: Sized, F: FnMut(Self::Item) -> Option, { FilterMap::new(self, f) } #[doc = r#" Returns the element that gives the minimum value with respect to the specified key function. If several elements are equally minimum, the first element is returned. If the stream is empty, `None` is returned. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![-1isize, 2, -3]); let min = s.clone().min_by_key(|x| x.abs()).await; assert_eq!(min, Some(-1)); let min = stream::empty::().min_by_key(|x| x.abs()).await; assert_eq!(min, None); # # }) } ``` "#] fn min_by_key( self, key_by: F, ) -> MinByKeyFuture where Self: Sized, B: Ord, F: FnMut(&Self::Item) -> B, { MinByKeyFuture::new(self, key_by) } #[doc = r#" Returns the element that gives the maximum value with respect to the specified key function. If several elements are equally maximum, the first element is returned. If the stream is empty, `None` is returned. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![-3_i32, 0, 1, 5, -10]); let max = s.clone().max_by_key(|x| x.abs()).await; assert_eq!(max, Some(-10)); let max = stream::empty::().max_by_key(|x| x.abs()).await; assert_eq!(max, None); # # }) } ``` "#] fn max_by_key( self, key_by: F, ) -> MaxByKeyFuture where Self: Sized, B: Ord, F: FnMut(&Self::Item) -> B, { MaxByKeyFuture::new(self, key_by) } #[doc = r#" Returns the element that gives the minimum value with respect to the specified comparison function. If several elements are equally minimum, the first element is returned. If the stream is empty, `None` is returned. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1u8, 2, 3]); let min = s.clone().min_by(|x, y| x.cmp(y)).await; assert_eq!(min, Some(1)); let min = s.min_by(|x, y| y.cmp(x)).await; assert_eq!(min, Some(3)); let min = stream::empty::().min_by(|x, y| x.cmp(y)).await; assert_eq!(min, None); # # }) } ``` "#] fn min_by( self, compare: F, ) -> MinByFuture where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { MinByFuture::new(self, compare) } #[doc = r#" Returns the element that gives the maximum value. If several elements are equally maximum, the first element is returned. If the stream is empty, `None` is returned. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1usize, 2, 3]); let max = s.clone().max().await; assert_eq!(max, Some(3)); let max = stream::empty::().max().await; assert_eq!(max, None); # # }) } ``` "#] fn max( self, ) -> MaxFuture where Self: Sized, Self::Item: Ord, { MaxFuture::new(self) } #[doc = r#" Returns the element that gives the minimum value. If several elements are equally minimum, the first element is returned. If the stream is empty, `None` is returned. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1usize, 2, 3]); let min = s.clone().min().await; assert_eq!(min, Some(1)); let min = stream::empty::().min().await; assert_eq!(min, None); # # }) } ``` "#] fn min( self, ) -> MinFuture where Self: Sized, Self::Item: Ord, { MinFuture::new(self) } #[doc = r#" Returns the element that gives the maximum value with respect to the specified comparison function. If several elements are equally maximum, the first element is returned. If the stream is empty, `None` is returned. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1u8, 2, 3]); let max = s.clone().max_by(|x, y| x.cmp(y)).await; assert_eq!(max, Some(3)); let max = s.max_by(|x, y| y.cmp(x)).await; assert_eq!(max, Some(1)); let max = stream::empty::().max_by(|x, y| x.cmp(y)).await; assert_eq!(max, None); # # }) } ``` "#] fn max_by( self, compare: F, ) -> MaxByFuture where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { MaxByFuture::new(self, compare) } #[doc = r#" Returns the nth element of the stream. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::from_iter(vec![1u8, 2, 3]); let second = s.nth(1).await; assert_eq!(second, Some(2)); # # }) } ``` Calling `nth()` multiple times: ``` # fn main() { async_std::task::block_on(async { # use async_std::stream; use async_std::prelude::*; let mut s = stream::from_iter(vec![1u8, 2, 3]); let second = s.nth(0).await; assert_eq!(second, Some(1)); let second = s.nth(0).await; assert_eq!(second, Some(2)); # # }) } ``` Returning `None` if the stream finished before returning `n` elements: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::from_iter(vec![1u8, 2, 3]); let fourth = s.nth(4).await; assert_eq!(fourth, None); # # }) } ``` "#] fn nth( &mut self, n: usize, ) -> NthFuture<'_, Self> where Self: Unpin + Sized, { NthFuture::new(self, n) } #[doc = r#" Tests if every element of the stream matches a predicate. `all()` takes a closure that returns `true` or `false`. It applies this closure to each element of the stream, and if they all return `true`, then so does `all()`. If any of them return `false`, it returns `false`. `all()` is short-circuiting; in other words, it will stop processing as soon as it finds a `false`, given that no matter what else happens, the result will also be `false`. An empty stream returns `true`. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::repeat::(42).take(3); assert!(s.all(|x| x == 42).await); # # }) } ``` Empty stream: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::empty::(); assert!(s.all(|_| false).await); # # }) } ``` "#] #[inline] fn all( &mut self, f: F, ) -> AllFuture<'_, Self, F, Self::Item> where Self: Unpin + Sized, F: FnMut(Self::Item) -> bool, { AllFuture::new(self, f) } #[doc = r#" Searches for an element in a stream that satisfies a predicate. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::from_iter(vec![1u8, 2, 3]); let res = s.find(|x| *x == 2).await; assert_eq!(res, Some(2)); # # }) } ``` Resuming after a first find: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s= stream::from_iter(vec![1, 2, 3]); let res = s.find(|x| *x == 2).await; assert_eq!(res, Some(2)); let next = s.next().await; assert_eq!(next, Some(3)); # # }) } ``` "#] fn find

( &mut self, p: P, ) -> FindFuture<'_, Self, P> where Self: Unpin + Sized, P: FnMut(&Self::Item) -> bool, { FindFuture::new(self, p) } #[doc = r#" Applies function to the elements of stream and returns the first non-none result. ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::from_iter(vec!["lol", "NaN", "2", "5"]); let first_number = s.find_map(|s| s.parse().ok()).await; assert_eq!(first_number, Some(2)); # # }) } ``` "#] fn find_map( &mut self, f: F, ) -> FindMapFuture<'_, Self, F> where Self: Unpin + Sized, F: FnMut(Self::Item) -> Option, { FindMapFuture::new(self, f) } #[doc = r#" A combinator that applies a function to every element in a stream producing a single, final value. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1u8, 2, 3]); let sum = s.fold(0, |acc, x| acc + x).await; assert_eq!(sum, 6); # # }) } ``` "#] fn fold( self, init: B, f: F, ) -> FoldFuture where Self: Sized, F: FnMut(B, Self::Item) -> B, { FoldFuture::new(self, init, f) } #[doc = r#" A combinator that applies a function to every element in a stream creating two collections from it. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let (even, odd): (Vec, Vec) = stream::from_iter(vec![1, 2, 3]) .partition(|&n| n % 2 == 0).await; assert_eq!(even, vec![2]); assert_eq!(odd, vec![1, 3]); # # }) } ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn partition( self, f: F, ) -> PartitionFuture where Self: Sized, F: FnMut(&Self::Item) -> bool, B: Default + Extend, { PartitionFuture::new(self, f) } #[doc = r#" Call a closure on each element of the stream. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; use std::sync::mpsc::channel; let (tx, rx) = channel(); let s = stream::from_iter(vec![1usize, 2, 3]); let sum = s.for_each(move |x| tx.clone().send(x).unwrap()).await; let v: Vec<_> = rx.iter().collect(); assert_eq!(v, vec![1, 2, 3]); # # }) } ``` "#] fn for_each( self, f: F, ) -> ForEachFuture where Self: Sized, F: FnMut(Self::Item), { ForEachFuture::new(self, f) } #[doc = r#" Tests if any element of the stream matches a predicate. `any()` takes a closure that returns `true` or `false`. It applies this closure to each element of the stream, and if any of them return `true`, then so does `any()`. If they all return `false`, it returns `false`. `any()` is short-circuiting; in other words, it will stop processing as soon as it finds a `true`, given that no matter what else happens, the result will also be `true`. An empty stream returns `false`. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::repeat::(42).take(3); assert!(s.any(|x| x == 42).await); # # }) } ``` Empty stream: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::empty::(); assert!(!s.any(|_| false).await); # # }) } ``` "#] #[inline] fn any( &mut self, f: F, ) -> AnyFuture<'_, Self, F, Self::Item> where Self: Unpin + Sized, F: FnMut(Self::Item) -> bool, { AnyFuture::new(self, f) } #[doc = r#" Borrows an stream, rather than consuming it. This is useful to allow applying stream adaptors while still retaining ownership of the original stream. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let a = vec![1isize, 2, 3]; let stream = stream::from_iter(a); let sum: isize = stream.take(5).sum().await; assert_eq!(sum, 6); // if we try to use stream again, it won't work. The following line // gives error: use of moved value: `stream` // assert_eq!(stream.next(), None); // let's try that again let a = vec![1isize, 2, 3]; let mut stream = stream::from_iter(a); // instead, we add in a .by_ref() let sum: isize = stream.by_ref().take(2).sum().await; assert_eq!(sum, 3); // now this is just fine: assert_eq!(stream.next().await, Some(3)); assert_eq!(stream.next().await, None); # # }) } ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn by_ref(&mut self) -> &mut Self { self } #[doc = r#" A stream adaptor similar to [`fold`] that holds internal state and produces a new stream. [`fold`]: #method.fold `scan()` takes two arguments: an initial value which seeds the internal state, and a closure with two arguments, the first being a mutable reference to the internal state and the second a stream element. The closure can assign to the internal state to share state between iterations. On iteration, the closure will be applied to each element of the stream and the return value from the closure, an `Option`, is yielded by the stream. ## Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1isize, 2, 3]); let mut s = s.scan(1, |state, x| { *state = *state * x; Some(-*state) }); assert_eq!(s.next().await, Some(-1)); assert_eq!(s.next().await, Some(-2)); assert_eq!(s.next().await, Some(-6)); assert_eq!(s.next().await, None); # # }) } ``` "#] #[inline] fn scan(self, initial_state: St, f: F) -> Scan where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option, { Scan::new(self, initial_state, f) } #[doc = r#" Combinator that `skip`s elements based on a predicate. Takes a closure argument. It will call this closure on every element in the stream and ignore elements until it returns `false`. After `false` is returned, `SkipWhile`'s job is over and all further elements in the stream are yielded. ## Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let a = stream::from_iter(vec![-1i32, 0, 1]); let mut s = a.skip_while(|x| x.is_negative()); assert_eq!(s.next().await, Some(0)); assert_eq!(s.next().await, Some(1)); assert_eq!(s.next().await, None); # # }) } ``` "#] fn skip_while

(self, predicate: P) -> SkipWhile where Self: Sized, P: FnMut(&Self::Item) -> bool, { SkipWhile::new(self, predicate) } #[doc = r#" Creates a combinator that skips the first `n` elements. ## Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1u8, 2, 3]); let mut skipped = s.skip(2); assert_eq!(skipped.next().await, Some(3)); assert_eq!(skipped.next().await, None); # # }) } ``` "#] fn skip(self, n: usize) -> Skip where Self: Sized, { Skip::new(self, n) } #[doc=r#" Await a stream or times out after a duration of time. If you want to await an I/O future consider using [`io::timeout`](../io/fn.timeout.html) instead. # Examples ``` # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use std::time::Duration; use async_std::stream; use async_std::prelude::*; let mut s = stream::repeat(1).take(3).timeout(Duration::from_secs(1)); while let Some(v) = s.next().await { assert_eq!(v, Ok(1)); } // when timeout let mut s = stream::pending::<()>().timeout(Duration::from_millis(10)); match s.next().await { Some(item) => assert!(item.is_err()), None => panic!() }; # # Ok(()) }) } ``` "#] #[cfg(any(feature = "unstable", feature = "docs"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn timeout(self, dur: Duration) -> Timeout where Self: Stream + Sized, { Timeout::new(self, dur) } #[doc = r#" A combinator that applies a function as long as it returns successfully, producing a single, final value. Immediately returns the error when the function returns unsuccessfully. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let mut s = stream::from_iter(vec![1usize, 2, 3]); let sum = s.try_fold(0, |acc, v| { if (acc+v) % 2 == 1 { Ok(v+3) } else { Err("fail") } }).await; assert_eq!(sum, Err("fail")); # # }) } ``` "#] fn try_fold( &mut self, init: T, f: F, ) -> TryFoldFuture<'_, Self, F, T> where Self: Unpin + Sized, F: FnMut(B, Self::Item) -> Result, { TryFoldFuture::new(self, init, f) } #[doc = r#" Applies a falliable function to each element in a stream, stopping at first error and returning it. # Examples ``` # fn main() { async_std::task::block_on(async { # use std::sync::mpsc::channel; use async_std::prelude::*; use async_std::stream; let (tx, rx) = channel(); let mut s = stream::from_iter(vec![1u8, 2, 3]); let s = s.try_for_each(|v| { if v % 2 == 1 { tx.clone().send(v).unwrap(); Ok(()) } else { Err("even") } }); let res = s.await; drop(tx); let values: Vec<_> = rx.iter().collect(); assert_eq!(values, vec![1]); assert_eq!(res, Err("even")); # # }) } ``` "#] fn try_for_each( &mut self, f: F, ) -> TryForEachFuture<'_, Self, F> where Self: Unpin + Sized, F: FnMut(Self::Item) -> Result<(), E>, { TryForEachFuture::new(self, f) } #[doc = r#" 'Zips up' two streams into a single stream of pairs. `zip()` returns a new stream that will iterate over two other streams, returning a tuple where the first element comes from the first stream, and the second element comes from the second stream. In other words, it zips two streams together, into a single one. If either stream returns [`None`], [`poll_next`] from the zipped stream will return [`None`]. If the first stream returns [`None`], `zip` will short-circuit and `poll_next` will not be called on the second stream. [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None [`poll_next`]: #tymethod.poll_next ## Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let l = stream::from_iter(vec![1u8, 2, 3]); let r = stream::from_iter(vec![4u8, 5, 6, 7]); let mut s = l.zip(r); assert_eq!(s.next().await, Some((1, 4))); assert_eq!(s.next().await, Some((2, 5))); assert_eq!(s.next().await, Some((3, 6))); assert_eq!(s.next().await, None); # # }) } ``` "#] #[inline] fn zip(self, other: U) -> Zip where Self: Sized, U: Stream, { Zip::new(self, other) } #[doc = r#" Converts an stream of pairs into a pair of containers. `unzip()` consumes an entire stream of pairs, producing two collections: one from the left elements of the pairs, and one from the right elements. This function is, in some sense, the opposite of [`zip`]. [`zip`]: trait.Stream.html#method.zip # Example ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![(1,2), (3,4)]); let (left, right): (Vec<_>, Vec<_>) = s.unzip().await; assert_eq!(left, [1, 3]); assert_eq!(right, [2, 4]); # # }) } ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn unzip(self) -> UnzipFuture where FromA: Default + Extend, FromB: Default + Extend, Self: Stream + Sized, { UnzipFuture::new(self) } #[doc = r#" Transforms a stream into a collection. `collect()` can take anything streamable, and turn it into a relevant collection. This is one of the more powerful methods in the async standard library, used in a variety of contexts. The most basic pattern in which `collect()` is used is to turn one collection into another. You take a collection, call [`into_stream`] on it, do a bunch of transformations, and then `collect()` at the end. Because `collect()` is so general, it can cause problems with type inference. As such, `collect()` is one of the few times you'll see the syntax affectionately known as the 'turbofish': `::<>`. This helps the inference algorithm understand specifically which collection you're trying to collect into. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::repeat(9u8).take(3); let buf: Vec = s.collect().await; assert_eq!(buf, vec![9; 3]); // You can also collect streams of Result values // into any collection that implements FromStream let s = stream::repeat(Ok(9)).take(3); // We are using Vec here, but other collections // are supported as well let buf: Result, ()> = s.collect().await; assert_eq!(buf, Ok(vec![9; 3])); // The stream will stop on the first Err and // return that instead let s = stream::repeat(Err(5)).take(3); let buf: Result, u8> = s.collect().await; assert_eq!(buf, Err(5)); # # }) } ``` [`into_stream`]: trait.IntoStream.html#tymethod.into_stream "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn collect<'a, B>( self, ) -> Pin + 'a + Send>> where Self: Sized + 'a + Send, B: FromStream, Self::Item: Send, { FromStream::from_stream(self) } #[doc = r#" Combines multiple streams into a single stream of all their outputs. Items are yielded as soon as they're received, and the stream continues yield until both streams have been exhausted. The output ordering between streams is not guaranteed. # Examples ``` # async_std::task::block_on(async { use async_std::prelude::*; use async_std::stream::{self, FromStream}; let a = stream::once(1u8); let b = stream::once(2u8); let c = stream::once(3u8); let s = a.merge(b).merge(c); let mut lst = Vec::from_stream(s).await; lst.sort_unstable(); assert_eq!(&lst, &[1u8, 2u8, 3u8]); # }); ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn merge(self, other: U) -> Merge where Self: Sized, U: Stream + Sized, { Merge::new(self, other) } #[doc = r#" Lexicographically compares the elements of this `Stream` with those of another. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; use std::cmp::Ordering; let s1 = stream::from_iter(vec![1]); let s2 = stream::from_iter(vec![1, 2]); let s3 = stream::from_iter(vec![1, 2, 3]); let s4 = stream::from_iter(vec![1, 2, 4]); assert_eq!(s1.clone().partial_cmp(s1.clone()).await, Some(Ordering::Equal)); assert_eq!(s1.clone().partial_cmp(s2.clone()).await, Some(Ordering::Less)); assert_eq!(s2.clone().partial_cmp(s1.clone()).await, Some(Ordering::Greater)); assert_eq!(s3.clone().partial_cmp(s4.clone()).await, Some(Ordering::Less)); assert_eq!(s4.clone().partial_cmp(s3.clone()).await, Some(Ordering::Greater)); # # }) } ``` "#] fn partial_cmp( self, other: S ) -> PartialCmpFuture where Self: Sized + Stream, S: Stream, ::Item: PartialOrd, { PartialCmpFuture::new(self, other) } #[doc = r#" Searches for an element in a Stream that satisfies a predicate, returning its index. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![1usize, 2, 3]); let res = s.clone().position(|x| x == 1).await; assert_eq!(res, Some(0)); let res = s.clone().position(|x| x == 2).await; assert_eq!(res, Some(1)); let res = s.clone().position(|x| x == 3).await; assert_eq!(res, Some(2)); let res = s.clone().position(|x| x == 4).await; assert_eq!(res, None); # # }) } ``` "#] fn position

( &mut self, predicate: P, ) -> PositionFuture<'_, Self, P> where Self: Unpin + Sized, P: FnMut(Self::Item) -> bool, { PositionFuture::new(self, predicate) } #[doc = r#" Lexicographically compares the elements of this `Stream` with those of another using 'Ord'. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; use std::cmp::Ordering; let s1 = stream::from_iter(vec![1]); let s2 = stream::from_iter(vec![1, 2]); let s3 = stream::from_iter(vec![1, 2, 3]); let s4 = stream::from_iter(vec![1, 2, 4]); assert_eq!(s1.clone().cmp(s1.clone()).await, Ordering::Equal); assert_eq!(s1.clone().cmp(s2.clone()).await, Ordering::Less); assert_eq!(s2.clone().cmp(s1.clone()).await, Ordering::Greater); assert_eq!(s3.clone().cmp(s4.clone()).await, Ordering::Less); assert_eq!(s4.clone().cmp(s3.clone()).await, Ordering::Greater); # # }) } ``` "#] fn cmp( self, other: S ) -> CmpFuture where Self: Sized + Stream, S: Stream, ::Item: Ord { CmpFuture::new(self, other) } #[doc = r#" Counts the number of elements in the stream. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s1 = stream::from_iter(vec![0]); let s2 = stream::from_iter(vec![1, 2, 3]); assert_eq!(s1.count().await, 1); assert_eq!(s2.count().await, 3); # # }) } ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn count(self) -> CountFuture where Self: Sized, { CountFuture::new(self) } #[doc = r#" Determines if the elements of this `Stream` are lexicographically not equal to those of another. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let single = stream::from_iter(vec![1usize]); let single_ne = stream::from_iter(vec![10usize]); let multi = stream::from_iter(vec![1usize,2]); let multi_ne = stream::from_iter(vec![1usize,5]); assert_eq!(single.clone().ne(single.clone()).await, false); assert_eq!(single_ne.clone().ne(single.clone()).await, true); assert_eq!(multi.clone().ne(single_ne.clone()).await, true); assert_eq!(multi_ne.clone().ne(multi.clone()).await, true); # # }) } ``` "#] fn ne( self, other: S ) -> NeFuture where Self: Sized, S: Sized + Stream, ::Item: PartialEq, { NeFuture::new(self, other) } #[doc = r#" Determines if the elements of this `Stream` are lexicographically greater than or equal to those of another. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let single = stream::from_iter(vec![1]); let single_gt = stream::from_iter(vec![10]); let multi = stream::from_iter(vec![1,2]); let multi_gt = stream::from_iter(vec![1,5]); assert_eq!(single.clone().ge(single.clone()).await, true); assert_eq!(single_gt.clone().ge(single.clone()).await, true); assert_eq!(multi.clone().ge(single_gt.clone()).await, false); assert_eq!(multi_gt.clone().ge(multi.clone()).await, true); # # }) } ``` "#] fn ge( self, other: S ) -> GeFuture where Self: Sized + Stream, S: Stream, ::Item: PartialOrd, { GeFuture::new(self, other) } #[doc = r#" Determines if the elements of this `Stream` are lexicographically equal to those of another. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let single = stream::from_iter(vec![1]); let single_eq = stream::from_iter(vec![10]); let multi = stream::from_iter(vec![1,2]); let multi_eq = stream::from_iter(vec![1,5]); assert_eq!(single.clone().eq(single.clone()).await, true); assert_eq!(single_eq.clone().eq(single.clone()).await, false); assert_eq!(multi.clone().eq(single_eq.clone()).await, false); assert_eq!(multi_eq.clone().eq(multi.clone()).await, false); # # }) } ``` "#] fn eq( self, other: S ) -> EqFuture where Self: Sized + Stream, S: Sized + Stream, ::Item: PartialEq, { EqFuture::new(self, other) } #[doc = r#" Determines if the elements of this `Stream` are lexicographically greater than those of another. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let single = stream::from_iter(vec![1]); let single_gt = stream::from_iter(vec![10]); let multi = stream::from_iter(vec![1,2]); let multi_gt = stream::from_iter(vec![1,5]); assert_eq!(single.clone().gt(single.clone()).await, false); assert_eq!(single_gt.clone().gt(single.clone()).await, true); assert_eq!(multi.clone().gt(single_gt.clone()).await, false); assert_eq!(multi_gt.clone().gt(multi.clone()).await, true); # # }) } ``` "#] fn gt( self, other: S ) -> GtFuture where Self: Sized + Stream, S: Stream, ::Item: PartialOrd, { GtFuture::new(self, other) } #[doc = r#" Determines if the elements of this `Stream` are lexicographically less or equal to those of another. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let single = stream::from_iter(vec![1]); let single_gt = stream::from_iter(vec![10]); let multi = stream::from_iter(vec![1,2]); let multi_gt = stream::from_iter(vec![1,5]); assert_eq!(single.clone().le(single.clone()).await, true); assert_eq!(single.clone().le(single_gt.clone()).await, true); assert_eq!(multi.clone().le(single_gt.clone()).await, true); assert_eq!(multi_gt.clone().le(multi.clone()).await, false); # # }) } ``` "#] fn le( self, other: S ) -> LeFuture where Self: Sized + Stream, S: Stream, ::Item: PartialOrd, { LeFuture::new(self, other) } #[doc = r#" Determines if the elements of this `Stream` are lexicographically less than those of another. # Examples ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let single = stream::from_iter(vec![1]); let single_gt = stream::from_iter(vec![10]); let multi = stream::from_iter(vec![1,2]); let multi_gt = stream::from_iter(vec![1,5]); assert_eq!(single.clone().lt(single.clone()).await, false); assert_eq!(single.clone().lt(single_gt.clone()).await, true); assert_eq!(multi.clone().lt(single_gt.clone()).await, true); assert_eq!(multi_gt.clone().lt(multi.clone()).await, false); # # }) } ``` "#] fn lt( self, other: S ) -> LtFuture where Self: Sized + Stream, S: Stream, ::Item: PartialOrd, { LtFuture::new(self, other) } #[doc = r#" Sums the elements of a stream. Takes each element, adds them together, and returns the result. An empty streams returns the zero value of the type. # Panics When calling `sum()` and a primitive integer type is being returned, this method will panic if the computation overflows and debug assertions are enabled. # Examples Basic usage: ``` # fn main() { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(vec![0u8, 1, 2, 3, 4]); let sum: u8 = s.sum().await; assert_eq!(sum, 10); # # }) } ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn sum<'a, S>( self, ) -> Pin + 'a>> where Self: Sized + Stream + 'a, S: Sum, { Sum::sum(self) } #[doc = r#" Multiplies all elements of the stream. An empty stream returns the one value of the type. # Panics When calling `product()` and a primitive integer type is being returned, method will panic if the computation overflows and debug assertions are enabled. # Examples This example calculates the factorial of n (i.e. the product of the numbers from 1 to n, inclusive): ``` # fn main() { async_std::task::block_on(async { # async fn factorial(n: u32) -> u32 { use async_std::prelude::*; use async_std::stream; let s = stream::from_iter(1..=n); s.product().await } assert_eq!(factorial(0).await, 1); assert_eq!(factorial(1).await, 1); assert_eq!(factorial(5).await, 120); # # }) } ``` "#] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn product<'a, P>( self, ) -> Pin + 'a>> where Self: Sized + Stream + 'a, P: Product, { Product::product(self) } } impl StreamExt for T {} async-rs-async-std-57f61ae/src/stream/stream/ne.rs000066400000000000000000000027651476537407000221500ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use super::fuse::Fuse; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { // Lexicographically compares the elements of this `Stream` with those // of another. #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct NeFuture { #[pin] l: Fuse, #[pin] r: Fuse, } } impl NeFuture where L::Item: PartialEq, { pub(super) fn new(l: L, r: R) -> Self { Self { l: l.fuse(), r: r.fuse(), } } } impl Future for NeFuture where L: Stream + Sized, R: Stream + Sized, L::Item: PartialEq, { type Output = bool; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { let l_val = futures_core::ready!(this.l.as_mut().poll_next(cx)); let r_val = futures_core::ready!(this.r.as_mut().poll_next(cx)); if this.l.done || this.r.done { return Poll::Ready(false); } match (l_val, r_val) { (Some(l), Some(r)) if l == r => { continue; } _ => { return Poll::Ready(true); } } } } } async-rs-async-std-57f61ae/src/stream/stream/next.rs000066400000000000000000000007521476537407000225160ustar00rootroot00000000000000use core::pin::Pin; use core::future::Future; use crate::stream::Stream; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct NextFuture<'a, T: Unpin + ?Sized> { pub(crate) stream: &'a mut T, } impl Future for NextFuture<'_, T> { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { Pin::new(&mut *self.stream).poll_next(cx) } } async-rs-async-std-57f61ae/src/stream/stream/nth.rs000066400000000000000000000017721476537407000223340ustar00rootroot00000000000000use core::pin::Pin; use core::task::{Context, Poll}; use core::future::Future; use crate::stream::Stream; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct NthFuture<'a, S> { stream: &'a mut S, n: usize, } impl Unpin for NthFuture<'_, S> {} impl<'a, S> NthFuture<'a, S> { pub(crate) fn new(stream: &'a mut S, n: usize) -> Self { Self { stream, n } } } impl<'a, S> Future for NthFuture<'a, S> where S: Stream + Unpin + Sized, { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx)); match next { Some(v) => match self.n { 0 => Poll::Ready(Some(v)), _ => { self.n -= 1; cx.waker().wake_by_ref(); Poll::Pending } }, None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/stream/partial_cmp.rs000066400000000000000000000056541476537407000240410ustar00rootroot00000000000000use core::cmp::Ordering; use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use super::fuse::Fuse; use crate::stream::stream::StreamExt; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { // Lexicographically compares the elements of this `Stream` with those // of another. #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct PartialCmpFuture { #[pin] l: Fuse, #[pin] r: Fuse, l_cache: Option, r_cache: Option, } } impl PartialCmpFuture { pub(super) fn new(l: L, r: R) -> Self { Self { l: l.fuse(), r: r.fuse(), l_cache: None, r_cache: None, } } } impl Future for PartialCmpFuture where L: Stream + Sized, R: Stream + Sized, L::Item: PartialOrd, { type Output = Option; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { // Short circuit logic // Stream that completes earliest can be considered Less, etc let l_complete = this.l.done && this.l_cache.is_none(); let r_complete = this.r.done && this.r_cache.is_none(); if l_complete && r_complete { return Poll::Ready(Some(Ordering::Equal)); } else if l_complete { return Poll::Ready(Some(Ordering::Less)); } else if r_complete { return Poll::Ready(Some(Ordering::Greater)); } // Get next value if possible and necessary if !this.l.done && this.l_cache.is_none() { let l_next = futures_core::ready!(this.l.as_mut().poll_next(cx)); if let Some(item) = l_next { *this.l_cache = Some(item); } } if !this.r.done && this.r_cache.is_none() { let r_next = futures_core::ready!(this.r.as_mut().poll_next(cx)); if let Some(item) = r_next { *this.r_cache = Some(item); } } // Compare if both values are available. if this.l_cache.is_some() && this.r_cache.is_some() { let l_value = this.l_cache.as_mut().take().unwrap(); let r_value = this.r_cache.as_mut().take().unwrap(); let result = l_value.partial_cmp(&r_value); if let Some(Ordering::Equal) = result { // Reset cache to prepare for next comparison *this.l_cache = None; *this.r_cache = None; } else { // Return non equal value return Poll::Ready(result); } } } } } async-rs-async-std-57f61ae/src/stream/stream/partition.rs000066400000000000000000000026511476537407000235510ustar00rootroot00000000000000use pin_project_lite::pin_project; use core::default::Default; use core::future::Future; use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[derive(Debug)] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub struct PartitionFuture { #[pin] stream: S, f: F, res: Option<(B, B)>, } } impl PartitionFuture { pub(super) fn new(stream: S, f: F) -> Self { Self { stream, f, res: Some((B::default(), B::default())), } } } impl Future for PartitionFuture where S: Stream + Sized, F: FnMut(&S::Item) -> bool, B: Default + Extend, { type Output = (B, B); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); match next { Some(v) => { let res = this.res.as_mut().unwrap(); if (this.f)(&v) { res.0.extend(Some(v)) } else { res.1.extend(Some(v)) } } None => return Poll::Ready(this.res.take().unwrap()), } } } } async-rs-async-std-57f61ae/src/stream/stream/position.rs000066400000000000000000000022741476537407000234050ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct PositionFuture<'a, S, P> { stream: &'a mut S, predicate: P, index: usize, } impl<'a, S, P> Unpin for PositionFuture<'a, S, P> {} impl<'a, S, P> PositionFuture<'a, S, P> { pub(super) fn new(stream: &'a mut S, predicate: P) -> Self { Self { stream, predicate, index: 0, } } } impl<'a, S, P> Future for PositionFuture<'a, S, P> where S: Stream + Unpin, P: FnMut(S::Item) -> bool, { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let next = futures_core::ready!(Pin::new(&mut self.stream).poll_next(cx)); match next { Some(v) => { if (&mut self.predicate)(v) { Poll::Ready(Some(self.index)) } else { cx.waker().wake_by_ref(); self.index += 1; Poll::Pending } } None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/stream/scan.rs000066400000000000000000000023101476537407000224540ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream to maintain state while polling another stream. /// /// This `struct` is created by the [`scan`] method on [`Stream`]. See its /// documentation for more. /// /// [`scan`]: trait.Stream.html#method.scan /// [`Stream`]: trait.Stream.html #[derive(Debug)] pub struct Scan { #[pin] stream: S, state_f: (St, F), } } impl Scan { pub(crate) fn new(stream: S, initial_state: St, f: F) -> Self { Self { stream, state_f: (initial_state, f), } } } impl Stream for Scan where S: Stream, F: FnMut(&mut St, S::Item) -> Option, { type Item = B; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); let poll_result = this.stream.as_mut().poll_next(cx); poll_result.map(|item| { item.and_then(|item| { let (state, f) = this.state_f; f(state, item) }) }) } } async-rs-async-std-57f61ae/src/stream/stream/skip.rs000066400000000000000000000022421476537407000225020ustar00rootroot00000000000000use core::pin::Pin; use core::task::{Context, Poll}; use pin_project_lite::pin_project; use crate::stream::Stream; pin_project! { /// A stream to skip first n elements of another stream. /// /// This `struct` is created by the [`skip`] method on [`Stream`]. See its /// documentation for more. /// /// [`skip`]: trait.Stream.html#method.skip /// [`Stream`]: trait.Stream.html #[derive(Debug)] pub struct Skip { #[pin] stream: S, n: usize, } } impl Skip { pub(crate) fn new(stream: S, n: usize) -> Self { Self { stream, n } } } impl Stream for Skip where S: Stream, { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); match next { Some(v) => match *this.n { 0 => return Poll::Ready(Some(v)), _ => *this.n -= 1, }, None => return Poll::Ready(None), } } } } async-rs-async-std-57f61ae/src/stream/stream/skip_while.rs000066400000000000000000000030171476537407000236730ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream to skip elements of another stream based on a predicate. /// /// This `struct` is created by the [`skip_while`] method on [`Stream`]. See its /// documentation for more. /// /// [`skip_while`]: trait.Stream.html#method.skip_while /// [`Stream`]: trait.Stream.html #[derive(Debug)] pub struct SkipWhile { #[pin] stream: S, predicate: Option

, } } impl SkipWhile { pub(crate) fn new(stream: S, predicate: P) -> Self { Self { stream, predicate: Some(predicate), } } } impl Stream for SkipWhile where S: Stream, P: FnMut(&S::Item) -> bool, { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); match next { Some(v) => match this.predicate { Some(p) => { if !p(&v) { *this.predicate = None; return Poll::Ready(Some(v)); } } None => return Poll::Ready(Some(v)), }, None => return Poll::Ready(None), } } } } async-rs-async-std-57f61ae/src/stream/stream/step_by.rs000066400000000000000000000026101476537407000232000ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that steps a given amount of elements of another stream. /// /// This `struct` is created by the [`step_by`] method on [`Stream`]. See its /// documentation for more. /// /// [`step_by`]: trait.Stream.html#method.step_by /// [`Stream`]: trait.Stream.html #[derive(Debug)] pub struct StepBy { #[pin] stream: S, step: usize, i: usize, } } impl StepBy { pub(crate) fn new(stream: S, step: usize) -> Self { Self { stream, step: step.checked_sub(1).unwrap(), i: 0, } } } impl Stream for StepBy where S: Stream, { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); match next { Some(v) => match this.i { 0 => { *this.i = *this.step; return Poll::Ready(Some(v)); } _ => *this.i -= 1, }, None => return Poll::Ready(None), } } } } async-rs-async-std-57f61ae/src/stream/stream/take.rs000066400000000000000000000023231476537407000224600ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that yields the first `n` items of another stream. /// /// This `struct` is created by the [`take`] method on [`Stream`]. See its /// documentation for more. /// /// [`take`]: trait.Stream.html#method.take /// [`Stream`]: trait.Stream.html #[derive(Clone, Debug)] pub struct Take { #[pin] pub(crate) stream: S, pub(crate) remaining: usize, } } impl Take { pub(super) fn new(stream: S, remaining: usize) -> Self { Self { stream, remaining, } } } impl Stream for Take { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); if *this.remaining == 0 { Poll::Ready(None) } else { let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(_) => *this.remaining -= 1, None => *this.remaining = 0, } Poll::Ready(next) } } } async-rs-async-std-57f61ae/src/stream/stream/take_while.rs000066400000000000000000000024261476537407000236540ustar00rootroot00000000000000use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that yields elements based on a predicate. /// /// This `struct` is created by the [`take_while`] method on [`Stream`]. See its /// documentation for more. /// /// [`take_while`]: trait.Stream.html#method.take_while /// [`Stream`]: trait.Stream.html #[derive(Debug)] pub struct TakeWhile { #[pin] stream: S, predicate: P, } } impl TakeWhile { pub(super) fn new(stream: S, predicate: P) -> Self { Self { stream, predicate, } } } impl Stream for TakeWhile where S: Stream, P: FnMut(&S::Item) -> bool, { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let next = futures_core::ready!(this.stream.poll_next(cx)); match next { Some(v) => { if (this.predicate)(&v) { Poll::Ready(Some(v)) } else { Poll::Ready(None) } } None => Poll::Ready(None), } } } async-rs-async-std-57f61ae/src/stream/stream/throttle.rs000066400000000000000000000034121476537407000234010ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use std::time::Duration; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; use crate::utils::{timer_after, Timer}; pin_project! { /// A stream that only yields one element once every `duration`. /// /// This `struct` is created by the [`throttle`] method on [`Stream`]. See its /// documentation for more. /// /// [`throttle`]: trait.Stream.html#method.throttle /// [`Stream`]: trait.Stream.html #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct Throttle { #[pin] stream: S, duration: Duration, #[pin] blocked: bool, #[pin] delay: Timer, } } impl Throttle { pub(super) fn new(stream: S, duration: Duration) -> Self { Self { stream, duration, blocked: false, delay: timer_after(Duration::default()), } } } impl Stream for Throttle { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); if *this.blocked { let d = this.delay.as_mut(); if d.poll(cx).is_ready() { *this.blocked = false; } else { return Poll::Pending; } } match this.stream.poll_next(cx) { Poll::Pending => Poll::Pending, Poll::Ready(None) => Poll::Ready(None), Poll::Ready(Some(v)) => { *this.blocked = true; let _ = std::mem::replace(&mut *this.delay, timer_after(*this.duration)); Poll::Ready(Some(v)) } } } } async-rs-async-std-57f61ae/src/stream/stream/timeout.rs000066400000000000000000000033441476537407000232260ustar00rootroot00000000000000use std::error::Error; use std::fmt; use std::future::Future; use std::pin::Pin; use std::time::Duration; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; use crate::utils::{timer_after, Timer}; pin_project! { /// A stream with timeout time set #[derive(Debug)] pub struct Timeout { #[pin] stream: S, #[pin] delay: Timer, duration: Duration, } } impl Timeout { pub(crate) fn new(stream: S, dur: Duration) -> Self { let delay = timer_after(dur); Self { stream, delay, duration: dur } } } impl Stream for Timeout { type Item = Result; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); let r = match this.stream.poll_next(cx) { Poll::Ready(Some(v)) => Poll::Ready(Some(Ok(v))), Poll::Ready(None) => Poll::Ready(None), Poll::Pending => match this.delay.as_mut().poll(cx) { Poll::Ready(_) => Poll::Ready(Some(Err(TimeoutError { _private: () }))), Poll::Pending => return Poll::Pending, }, }; *this.delay.as_mut() = timer_after(*this.duration); r } } /// An error returned when a stream times out. #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg(any(feature = "unstable", feature = "docs"))] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct TimeoutError { _private: (), } impl Error for TimeoutError {} impl fmt::Display for TimeoutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "stream has timed out".fmt(f) } } async-rs-async-std-57f61ae/src/stream/stream/try_fold.rs000066400000000000000000000024741476537407000233650ustar00rootroot00000000000000use core::pin::Pin; use crate::future::Future; use crate::stream::Stream; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct TryFoldFuture<'a, S, F, T> { stream: &'a mut S, f: F, acc: Option, } impl<'a, S, F, T> Unpin for TryFoldFuture<'a, S, F, T> {} impl<'a, S, F, T> TryFoldFuture<'a, S, F, T> { pub(super) fn new(stream: &'a mut S, init: T, f: F) -> Self { Self { stream, f, acc: Some(init), } } } impl<'a, S, F, T, E> Future for TryFoldFuture<'a, S, F, T> where S: Stream + Unpin, F: FnMut(T, S::Item) -> Result, { type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { loop { let next = futures_core::ready!(Pin::new(&mut self.stream).poll_next(cx)); match next { Some(v) => { let old = self.acc.take().unwrap(); let new = (&mut self.f)(old, v); match new { Ok(o) => self.acc = Some(o), Err(e) => return Poll::Ready(Err(e)), } } None => return Poll::Ready(Ok(self.acc.take().unwrap())), } } } } async-rs-async-std-57f61ae/src/stream/stream/try_for_each.rs000066400000000000000000000021151476537407000241770ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct TryForEachFuture<'a, S, F> { stream: &'a mut S, f: F, } impl<'a, S, F> Unpin for TryForEachFuture<'a, S, F> {} impl<'a, S, F> TryForEachFuture<'a, S, F> { pub(crate) fn new(stream: &'a mut S, f: F) -> Self { Self { stream, f } } } impl<'a, S, F, E> Future for TryForEachFuture<'a, S, F> where S: Stream + Unpin, F: FnMut(S::Item) -> Result<(), E>, { type Output = Result<(), E>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { loop { let item = futures_core::ready!(Pin::new(&mut self.stream).poll_next(cx)); match item { None => return Poll::Ready(Ok(())), Some(v) => { let res = (&mut self.f)(v); if let Err(e) = res { return Poll::Ready(Err(e)); } } } } } } async-rs-async-std-57f61ae/src/stream/stream/unzip.rs000066400000000000000000000026121476537407000227020ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { #[derive(Clone, Debug)] #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub struct UnzipFuture { #[pin] stream: S, res: Option<(FromA, FromB)>, } } impl UnzipFuture where FromA: Default, FromB: Default, { pub(super) fn new(stream: S) -> Self { UnzipFuture { stream, res: Some((FromA::default(), FromB::default())), } } } impl Future for UnzipFuture where S: Stream, FromA: Default + Extend, FromB: Default + Extend, { type Output = (FromA, FromB); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); loop { let next = futures_core::ready!(this.stream.as_mut().poll_next(cx)); match next { Some((a, b)) => { let res = this.res.as_mut().unwrap(); res.0.extend(Some(a)); res.1.extend(Some(b)); } None => return Poll::Ready(this.res.take().unwrap()), } } } } async-rs-async-std-57f61ae/src/stream/stream/zip.rs000066400000000000000000000033611476537407000223410ustar00rootroot00000000000000use core::fmt; use core::pin::Pin; use pin_project_lite::pin_project; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream that takes items from two other streams simultaneously. /// /// This `struct` is created by the [`zip`] method on [`Stream`]. See its /// documentation for more. /// /// [`zip`]: trait.Stream.html#method.zip /// [`Stream`]: trait.Stream.html pub struct Zip { item_slot: Option, #[pin] first: A, #[pin] second: B, } } impl fmt::Debug for Zip { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Zip") .field("first", &self.first) .field("second", &self.second) .finish() } } impl Zip { pub(crate) fn new(first: A, second: B) -> Self { Self { item_slot: None, first, second, } } } impl Stream for Zip { type Item = (A::Item, B::Item); fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); if this.item_slot.is_none() { match this.first.poll_next(cx) { Poll::Pending => return Poll::Pending, Poll::Ready(None) => return Poll::Ready(None), Poll::Ready(Some(item)) => *this.item_slot = Some(item), } } let second_item = futures_core::ready!(this.second.poll_next(cx)); let first_item = this.item_slot.take().unwrap(); Poll::Ready(second_item.map(|second_item| (first_item, second_item))) } } async-rs-async-std-57f61ae/src/stream/successors.rs000066400000000000000000000036341476537407000224430ustar00rootroot00000000000000use core::mem; use core::pin::Pin; use crate::stream::Stream; use crate::task::{Context, Poll}; use pin_project_lite::pin_project; /// Creates a new stream where to produce each new element a closure is called with the previous /// value. /// /// # Examples /// /// ``` /// # fn main() { async_std::task::block_on(async { /// # /// use async_std::prelude::*; /// use async_std::stream; /// /// let mut s = stream::successors(Some(22), |&val| Some(val + 1)); /// /// assert_eq!(s.next().await, Some(22)); /// assert_eq!(s.next().await, Some(23)); /// assert_eq!(s.next().await, Some(24)); /// assert_eq!(s.next().await, Some(25)); /// /// # /// # }) } /// ``` #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub fn successors(first: Option, succ: F) -> Successors where F: FnMut(&T) -> Option, { Successors { succ, slot: first } } pin_project! { /// A stream that yields elements by calling an async closure with the previous value as an /// argument /// /// This stream is constructed by [`successors`] function /// /// [`successors`]: fn.successors.html #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[derive(Debug)] pub struct Successors where F: FnMut(&T) -> Option { succ: F, slot: Option, } } impl Stream for Successors where F: FnMut(&T) -> Option, { type Item = T; fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { let this = self.project(); if this.slot.is_none() { return Poll::Ready(None); } let mut next = (this.succ)(&this.slot.as_ref().unwrap()); // 'swapping' here means 'slot' will hold the next value and next will be th one from the previous iteration mem::swap(this.slot, &mut next); Poll::Ready(next) } } async-rs-async-std-57f61ae/src/stream/sum.rs000066400000000000000000000036351476537407000210540ustar00rootroot00000000000000use core::future::Future; use core::pin::Pin; use crate::stream::Stream; /// Trait to represent types that can be created by summing up a stream. /// /// This trait is used to implement the [`sum`] method on streams. Types which /// implement the trait can be generated by the [`sum`] method. Like /// [`FromStream`] this trait should rarely be called directly and instead /// interacted with through [`Stream::sum`]. /// /// [`sum`]: trait.Sum.html#tymethod.sum /// [`FromStream`]: trait.FromStream.html /// [`Stream::sum`]: trait.Stream.html#method.sum #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait Sum: Sized { /// Method which takes a stream and generates `Self` from the elements by /// "summing up" the items. fn sum<'a, S>(stream: S) -> Pin + 'a>> where S: Stream + 'a; } use crate::stream::stream::StreamExt; use core::num::Wrapping; use core::ops::Add; macro_rules! num_sum { ($zero:expr, $($a:ty)*) => ($( impl Sum for $a { fn sum<'a, S>(stream: S) -> Pin+ 'a>> where S: Stream + 'a, { Box::pin(async move { stream.fold($zero, Add::add).await } ) } } impl<'a> Sum<&'a $a> for $a { fn sum<'b, S>(stream: S) -> Pin + 'b>> where S: Stream + 'b, { Box::pin(async move { stream.fold($zero, Add::add).await } ) } } )*); } macro_rules! integer_sum { ($($a:ty)*) => ( num_sum!(0, $($a)*); num_sum!(Wrapping(0), $(Wrapping<$a>)*); ); } macro_rules! float_sum { ($($a:ty)*) => ( num_sum!(0.0, $($a)*); ); } integer_sum! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } float_sum! { f32 f64 } async-rs-async-std-57f61ae/src/string/000077500000000000000000000000001476537407000177065ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/string/extend.rs000066400000000000000000000051341476537407000215460ustar00rootroot00000000000000use std::borrow::Cow; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend for String { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); self.reserve(stream.size_hint().0); Box::pin(async move { pin_utils::pin_mut!(stream); while let Some(item) = stream.next().await { self.push(item); } }) } } impl<'b> stream::Extend<&'b char> for String { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { pin_utils::pin_mut!(stream); while let Some(item) = stream.next().await { self.push(*item); } }) } } impl<'b> stream::Extend<&'b str> for String { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { pin_utils::pin_mut!(stream); while let Some(item) = stream.next().await { self.push_str(item); } }) } } impl stream::Extend for String { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { pin_utils::pin_mut!(stream); while let Some(item) = stream.next().await { self.push_str(&item); } }) } } impl<'b> stream::Extend> for String { fn extend<'a, S: IntoStream> + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { pin_utils::pin_mut!(stream); while let Some(item) = stream.next().await { self.push_str(&item); } }) } } async-rs-async-std-57f61ae/src/string/from_stream.rs000066400000000000000000000045351476537407000226010ustar00rootroot00000000000000use std::borrow::Cow; use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream for String { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = String::new(); stream::extend(&mut out, stream).await; out }) } } impl<'b> FromStream<&'b char> for String { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = String::new(); stream::extend(&mut out, stream).await; out }) } } impl<'b> FromStream<&'b str> for String { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = String::new(); stream::extend(&mut out, stream).await; out }) } } impl FromStream for String { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = String::new(); stream::extend(&mut out, stream).await; out }) } } impl<'b> FromStream> for String { #[inline] fn from_stream<'a, S: IntoStream> + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = String::new(); stream::extend(&mut out, stream).await; out }) } } async-rs-async-std-57f61ae/src/string/mod.rs000066400000000000000000000002751476537407000210370ustar00rootroot00000000000000//! The Rust core string library //! //! This library provides a UTF-8 encoded, growable string. mod extend; mod from_stream; #[allow(unused)] #[doc(inline)] pub use std::string::String; async-rs-async-std-57f61ae/src/sync/000077500000000000000000000000001476537407000173545ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/sync/condvar.rs000066400000000000000000000300601476537407000213550ustar00rootroot00000000000000use std::fmt; use std::pin::Pin; use std::time::Duration; use super::MutexGuard; use crate::future::{timeout, Future}; use crate::sync::WakerSet; use crate::task::{Context, Poll}; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct WaitTimeoutResult(bool); /// A type indicating whether a timed wait on a condition variable returned due to a time out or /// not impl WaitTimeoutResult { /// Returns `true` if the wait was known to have timed out. pub fn timed_out(self) -> bool { self.0 } } /// A Condition Variable /// /// This type is an async version of [`std::sync::Condvar`]. /// /// [`std::sync::Condvar`]: https://doc.rust-lang.org/std/sync/struct.Condvar.html /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use std::sync::Arc; /// /// use async_std::sync::{Mutex, Condvar}; /// use async_std::task; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// /// // Inside of our lock, spawn a new thread, and then wait for it to start. /// task::spawn(async move { /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().await; /// *started = true; /// // We notify the condvar that the value has changed. /// cvar.notify_one(); /// }); /// /// // Wait for the thread to start up. /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().await; /// while !*started { /// started = cvar.wait(started).await; /// } /// /// # }) /// ``` pub struct Condvar { wakers: WakerSet, } unsafe impl Send for Condvar {} unsafe impl Sync for Condvar {} impl Default for Condvar { fn default() -> Self { Condvar::new() } } impl Condvar { /// Creates a new condition variable /// /// # Examples /// /// ``` /// use async_std::sync::Condvar; /// /// let cvar = Condvar::new(); /// ``` pub fn new() -> Self { Condvar { wakers: WakerSet::new(), } } /// Blocks the current task until this condition variable receives a notification. /// /// Unlike the std equivalent, this does not check that a single mutex is used at runtime. /// However, as a best practice avoid using with multiple mutexes. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// use std::sync::Arc; /// /// use async_std::sync::{Mutex, Condvar}; /// use async_std::task; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// /// task::spawn(async move { /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().await; /// *started = true; /// // We notify the condvar that the value has changed. /// cvar.notify_one(); /// }); /// /// // Wait for the thread to start up. /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().await; /// while !*started { /// started = cvar.wait(started).await; /// } /// # }) /// ``` #[allow(clippy::needless_lifetimes)] pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> { let mutex = MutexGuard::source(&guard); self.await_notify(guard).await; mutex.lock().await } fn await_notify<'a, T>(&self, guard: MutexGuard<'a, T>) -> AwaitNotify<'_, 'a, T> { AwaitNotify { cond: self, guard: Some(guard), key: None, } } /// Blocks the current task until this condition variable receives a notification and the /// required condition is met. Spurious wakeups are ignored and this function will only /// return once the condition has been met. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use std::sync::Arc; /// /// use async_std::sync::{Mutex, Condvar}; /// use async_std::task; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// /// task::spawn(async move { /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().await; /// *started = true; /// // We notify the condvar that the value has changed. /// cvar.notify_one(); /// }); /// /// // Wait for the thread to start up. /// let (lock, cvar) = &*pair; /// // As long as the value inside the `Mutex` is `false`, we wait. /// let _guard = cvar.wait_until(lock.lock().await, |started| { *started }).await; /// # /// # }) /// ``` #[allow(clippy::needless_lifetimes)] pub async fn wait_until<'a, T, F>( &self, mut guard: MutexGuard<'a, T>, mut condition: F, ) -> MutexGuard<'a, T> where F: FnMut(&mut T) -> bool, { while !condition(&mut *guard) { guard = self.wait(guard).await; } guard } /// Waits on this condition variable for a notification, timing out after a specified duration. /// /// For these reasons `Condvar::wait_timeout_until` is recommended in most cases. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use std::sync::Arc; /// use std::time::Duration; /// /// use async_std::sync::{Mutex, Condvar}; /// use async_std::task; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// /// task::spawn(async move { /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().await; /// *started = true; /// // We notify the condvar that the value has changed. /// cvar.notify_one(); /// }); /// /// // wait for the thread to start up /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().await; /// loop { /// let result = cvar.wait_timeout(started, Duration::from_millis(10)).await; /// started = result.0; /// if *started == true { /// // We received the notification and the value has been updated, we can leave. /// break /// } /// } /// # /// # }) /// ``` #[allow(clippy::needless_lifetimes)] pub async fn wait_timeout<'a, T>( &self, guard: MutexGuard<'a, T>, dur: Duration, ) -> (MutexGuard<'a, T>, WaitTimeoutResult) { let mutex = MutexGuard::source(&guard); match timeout(dur, self.wait(guard)).await { Ok(guard) => (guard, WaitTimeoutResult(false)), Err(_) => (mutex.lock().await, WaitTimeoutResult(true)), } } /// Waits on this condition variable for a notification, timing out after a specified duration. /// Spurious wakes will not cause this function to return. /// /// # Examples /// ``` /// # async_std::task::block_on(async { /// use std::sync::Arc; /// use std::time::Duration; /// /// use async_std::sync::{Mutex, Condvar}; /// use async_std::task; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// /// task::spawn(async move { /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().await; /// *started = true; /// // We notify the condvar that the value has changed. /// cvar.notify_one(); /// }); /// /// // wait for the thread to start up /// let (lock, cvar) = &*pair; /// let result = cvar.wait_timeout_until( /// lock.lock().await, /// Duration::from_millis(100), /// |&mut started| started, /// ).await; /// if result.1.timed_out() { /// // timed-out without the condition ever evaluating to true. /// } /// // access the locked mutex via result.0 /// # }); /// ``` #[allow(clippy::needless_lifetimes)] pub async fn wait_timeout_until<'a, T, F>( &self, guard: MutexGuard<'a, T>, dur: Duration, condition: F, ) -> (MutexGuard<'a, T>, WaitTimeoutResult) where F: FnMut(&mut T) -> bool, { let mutex = MutexGuard::source(&guard); match timeout(dur, self.wait_until(guard, condition)).await { Ok(guard) => (guard, WaitTimeoutResult(false)), Err(_) => (mutex.lock().await, WaitTimeoutResult(true)), } } /// Wakes up one blocked task on this condvar. /// /// # Examples /// /// ``` /// # fn main() { async_std::task::block_on(async { /// use std::sync::Arc; /// /// use async_std::sync::{Mutex, Condvar}; /// use async_std::task; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// /// task::spawn(async move { /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().await; /// *started = true; /// // We notify the condvar that the value has changed. /// cvar.notify_one(); /// }); /// /// // Wait for the thread to start up. /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().await; /// while !*started { /// started = cvar.wait(started).await; /// } /// # }) } /// ``` pub fn notify_one(&self) { self.wakers.notify_one(); } /// Wakes up all blocked tasks on this condvar. /// /// # Examples /// ``` /// # fn main() { async_std::task::block_on(async { /// # /// use std::sync::Arc; /// /// use async_std::sync::{Mutex, Condvar}; /// use async_std::task; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// /// task::spawn(async move { /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().await; /// *started = true; /// // We notify the condvar that the value has changed. /// cvar.notify_all(); /// }); /// /// // Wait for the thread to start up. /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().await; /// // As long as the value inside the `Mutex` is `false`, we wait. /// while !*started { /// started = cvar.wait(started).await; /// } /// # /// # }) } /// ``` pub fn notify_all(&self) { self.wakers.notify_all(); } } impl fmt::Debug for Condvar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Condvar { .. }") } } /// A future that waits for another task to notify the condition variable. /// /// This is an internal future that `wait` and `wait_until` await on. struct AwaitNotify<'a, 'b, T> { /// The condition variable that we are waiting on cond: &'a Condvar, /// The lock used with `cond`. /// This will be released the first time the future is polled, /// after registering the context to be notified. guard: Option>, /// A key into the conditions variable's `WakerSet`. /// This is set to the index of the `Waker` for the context each time /// the future is polled and not completed. key: Option, } impl<'a, 'b, T> Future for AwaitNotify<'a, 'b, T> { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match self.guard.take() { Some(_) => { self.key = Some(self.cond.wakers.insert(cx)); // the guard is dropped when we return, which frees the lock Poll::Pending } None => { if let Some(key) = self.key { if self.cond.wakers.remove_if_notified(key, cx) { self.key = None; Poll::Ready(()) } else { Poll::Pending } } else { // This should only happen if it is polled twice after receiving a notification Poll::Ready(()) } } } } } impl<'a, 'b, T> Drop for AwaitNotify<'a, 'b, T> { fn drop(&mut self) { if let Some(key) = self.key { self.cond.wakers.cancel(key); } } } async-rs-async-std-57f61ae/src/sync/mod.rs000066400000000000000000000156401476537407000205070ustar00rootroot00000000000000//! Synchronization primitives. //! //! This module is an async version of [`std::sync`]. //! //! [`std::sync`]: https://doc.rust-lang.org/std/sync/index.html //! //! ## The need for synchronization //! //! async-std's sync primitives are scheduler-aware, making it possible to //! `.await` their operations - for example the locking of a [`Mutex`]. //! //! Conceptually, a Rust program is a series of operations which will //! be executed on a computer. The timeline of events happening in the //! program is consistent with the order of the operations in the code. //! //! Consider the following code, operating on some global static variables: //! //! ``` //! static mut A: u32 = 0; //! static mut B: u32 = 0; //! static mut C: u32 = 0; //! //! fn main() { //! unsafe { //! A = 3; //! B = 4; //! A = A + B; //! C = B; //! println!("{} {} {}", A, B, C); //! C = A; //! } //! } //! ``` //! //! It appears as if some variables stored in memory are changed, an addition //! is performed, result is stored in `A` and the variable `C` is //! modified twice. //! //! When only a single thread is involved, the results are as expected: //! the line `7 4 4` gets printed. //! //! As for what happens behind the scenes, when optimizations are enabled the //! final generated machine code might look very different from the code: //! //! - The first store to `C` might be moved before the store to `A` or `B`, //! _as if_ we had written `C = 4; A = 3; B = 4`. //! //! - Assignment of `A + B` to `A` might be removed, since the sum can be stored //! in a temporary location until it gets printed, with the global variable //! never getting updated. //! //! - The final result could be determined just by looking at the code //! at compile time, so [constant folding] might turn the whole //! block into a simple `println!("7 4 4")`. //! //! The compiler is allowed to perform any combination of these //! optimizations, as long as the final optimized code, when executed, //! produces the same results as the one without optimizations. //! //! Due to the [concurrency] involved in modern computers, assumptions //! about the program's execution order are often wrong. Access to //! global variables can lead to nondeterministic results, **even if** //! compiler optimizations are disabled, and it is **still possible** //! to introduce synchronization bugs. //! //! Note that thanks to Rust's safety guarantees, accessing global (static) //! variables requires `unsafe` code, assuming we don't use any of the //! synchronization primitives in this module. //! //! [constant folding]: https://en.wikipedia.org/wiki/Constant_folding //! [concurrency]: https://en.wikipedia.org/wiki/Concurrency_(computer_science) //! //! ## Out-of-order execution //! //! Instructions can execute in a different order from the one we define, due to //! various reasons: //! //! - The **compiler** reordering instructions: If the compiler can issue an //! instruction at an earlier point, it will try to do so. For example, it //! might hoist memory loads at the top of a code block, so that the CPU can //! start [prefetching] the values from memory. //! //! In single-threaded scenarios, this can cause issues when writing //! signal handlers or certain kinds of low-level code. //! Use [compiler fences] to prevent this reordering. //! //! - A **single processor** executing instructions [out-of-order]: //! Modern CPUs are capable of [superscalar] execution, //! i.e., multiple instructions might be executing at the same time, //! even though the machine code describes a sequential process. //! //! This kind of reordering is handled transparently by the CPU. //! //! - A **multiprocessor** system executing multiple hardware threads //! at the same time: In multi-threaded scenarios, you can use two //! kinds of primitives to deal with synchronization: //! - [memory fences] to ensure memory accesses are made visible to //! other CPUs in the right order. //! - [atomic operations] to ensure simultaneous access to the same //! memory location doesn't lead to undefined behavior. //! //! [prefetching]: https://en.wikipedia.org/wiki/Cache_prefetching //! [compiler fences]: https://doc.rust-lang.org/std/sync/atomic/fn.compiler_fence.html //! [out-of-order]: https://en.wikipedia.org/wiki/Out-of-order_execution //! [superscalar]: https://en.wikipedia.org/wiki/Superscalar_processor //! [memory fences]: https://doc.rust-lang.org/std/sync/atomic/fn.fence.html //! [atomic operations]: https://doc.rust-lang.org/std/sync/atomic/index.html //! //! ## Higher-level synchronization objects //! //! Most of the low-level synchronization primitives are quite error-prone and //! inconvenient to use, which is why async-std also exposes some //! higher-level synchronization objects. //! //! These abstractions can be built out of lower-level primitives. //! For efficiency, the sync objects in async-std are usually //! implemented with help from the scheduler, which is //! able to reschedule the tasks while they are blocked on acquiring //! a lock. //! //! The following is an overview of the available synchronization //! objects: //! //! - [`Arc`]: Atomically Reference-Counted pointer, which can be used //! in multithreaded environments to prolong the lifetime of some //! data until all the threads have finished using it. //! //! - [`Barrier`]: Ensures multiple threads will wait for each other //! to reach a point in the program, before continuing execution all //! together. //! //! - [`Mutex`]: Mutual exclusion mechanism, which ensures that at //! most one task at a time is able to access some data. //! //! - [`RwLock`]: Provides a mutual exclusion mechanism which allows //! multiple readers at the same time, while allowing only one //! writer at a time. In some cases, this can be more efficient than //! a mutex. //! //! If you're looking for channels, check out //! [`async_std::channel`][crate::channel]. //! //! [`Arc`]: struct.Arc.html //! [`Barrier`]: struct.Barrier.html //! [`channel`]: fn.channel.html //! [`Mutex`]: struct.Mutex.html //! [`RwLock`]: struct.RwLock.html //! //! # Examples //! //! Spawn a task that updates an integer protected by a mutex: //! //! ``` //! # async_std::task::block_on(async { //! # //! use async_std::sync::{Arc, Mutex}; //! use async_std::task; //! //! let m1 = Arc::new(Mutex::new(0)); //! let m2 = m1.clone(); //! //! task::spawn(async move { //! *m2.lock().await = 1; //! }) //! .await; //! //! assert_eq!(*m1.lock().await, 1); //! # //! # }) //! ``` #![allow(clippy::needless_doctest_main)] #[doc(inline)] pub use std::sync::{Arc, Weak}; #[doc(inline)] pub use async_lock::{Mutex, MutexGuard, MutexGuardArc}; #[doc(inline)] pub use async_lock::{RwLock, RwLockReadGuard, RwLockUpgradableReadGuard, RwLockWriteGuard}; cfg_unstable! { pub use async_lock::{Barrier, BarrierWaitResult}; pub use condvar::Condvar; pub(crate) use waker_set::WakerSet; mod condvar; pub(crate) mod waker_set; } async-rs-async-std-57f61ae/src/sync/waker_set.rs000066400000000000000000000151331476537407000217110ustar00rootroot00000000000000//! A common utility for building synchronization primitives. //! //! When an async operation is blocked, it needs to register itself somewhere so that it can be //! notified later on. The `WakerSet` type helps with keeping track of such async operations and //! notifying them when they may make progress. use std::cell::UnsafeCell; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::task::{Context, Waker}; use crossbeam_utils::Backoff; use slab::Slab; /// Set when the entry list is locked. #[allow(clippy::identity_op)] const LOCKED: usize = 1 << 0; /// Set when there is at least one entry that has already been notified. const NOTIFIED: usize = 1 << 1; /// Set when there is at least one notifiable entry. const NOTIFIABLE: usize = 1 << 2; /// Inner representation of `WakerSet`. struct Inner { /// A list of entries in the set. /// /// Each entry has an optional waker associated with the task that is executing the operation. /// If the waker is set to `None`, that means the task has been woken up but hasn't removed /// itself from the `WakerSet` yet. /// /// The key of each entry is its index in the `Slab`. entries: Slab>, /// The number of notifiable entries. notifiable: usize, } /// A set holding wakers. pub struct WakerSet { /// Holds three bits: `LOCKED`, `NOTIFY_ONE`, and `NOTIFY_ALL`. flag: AtomicUsize, /// A set holding wakers. inner: UnsafeCell, } impl WakerSet { /// Creates a new `WakerSet`. #[inline] pub fn new() -> WakerSet { WakerSet { flag: AtomicUsize::new(0), inner: UnsafeCell::new(Inner { entries: Slab::new(), notifiable: 0, }), } } /// Inserts a waker for a blocked operation and returns a key associated with it. #[cold] pub fn insert(&self, cx: &Context<'_>) -> usize { let w = cx.waker().clone(); let mut inner = self.lock(); let key = inner.entries.insert(Some(w)); inner.notifiable += 1; key } /// If the waker for this key is still waiting for a notification, then update /// the waker for the entry, and return false. If the waker has been notified, /// treat the entry as completed and return true. #[cfg(feature = "unstable")] pub fn remove_if_notified(&self, key: usize, cx: &Context<'_>) -> bool { let mut inner = self.lock(); match &mut inner.entries[key] { None => { inner.entries.remove(key); true } Some(w) => { // We were never woken, so update instead if !w.will_wake(cx.waker()) { *w = cx.waker().clone(); } false } } } /// Removes the waker of a cancelled operation. /// /// Returns `true` if another blocked operation from the set was notified. #[cold] pub fn cancel(&self, key: usize) -> bool { let mut inner = self.lock(); match inner.entries.remove(key) { Some(_) => inner.notifiable -= 1, None => { // The operation was cancelled and notified so notify another operation instead. for (_, opt_waker) in inner.entries.iter_mut() { // If there is no waker in this entry, that means it was already woken. if let Some(w) = opt_waker.take() { w.wake(); inner.notifiable -= 1; return true; } } } } false } /// Notifies one additional blocked operation. /// /// Returns `true` if an operation was notified. #[inline] #[cfg(feature = "unstable")] pub fn notify_one(&self) -> bool { // Use `SeqCst` ordering to synchronize with `Lock::drop()`. if self.flag.load(Ordering::SeqCst) & NOTIFIABLE != 0 { self.notify(Notify::One) } else { false } } /// Notifies all blocked operations. /// /// Returns `true` if at least one operation was notified. #[inline] pub fn notify_all(&self) -> bool { // Use `SeqCst` ordering to synchronize with `Lock::drop()`. if self.flag.load(Ordering::SeqCst) & NOTIFIABLE != 0 { self.notify(Notify::All) } else { false } } /// Notifies blocked operations, either one or all of them. /// /// Returns `true` if at least one operation was notified. #[cold] fn notify(&self, n: Notify) -> bool { let inner = &mut *self.lock(); let mut notified = false; for (_, opt_waker) in inner.entries.iter_mut() { // If there is no waker in this entry, that means it was already woken. if let Some(w) = opt_waker.take() { w.wake(); inner.notifiable -= 1; notified = true; if n == Notify::One { break; } } if n == Notify::Any { break; } } notified } /// Locks the list of entries. fn lock(&self) -> Lock<'_> { let backoff = Backoff::new(); while self.flag.fetch_or(LOCKED, Ordering::Acquire) & LOCKED != 0 { backoff.snooze(); } Lock { waker_set: self } } } /// A guard holding a `WakerSet` locked. struct Lock<'a> { waker_set: &'a WakerSet, } impl Drop for Lock<'_> { #[inline] fn drop(&mut self) { let mut flag = 0; // Set the `NOTIFIED` flag if there is at least one notified entry. if self.entries.len() - self.notifiable > 0 { flag |= NOTIFIED; } // Set the `NOTIFIABLE` flag if there is at least one notifiable entry. if self.notifiable > 0 { flag |= NOTIFIABLE; } // Use `SeqCst` ordering to synchronize with `WakerSet::lock_to_notify()`. self.waker_set.flag.store(flag, Ordering::SeqCst); } } impl Deref for Lock<'_> { type Target = Inner; #[inline] fn deref(&self) -> &Inner { unsafe { &*self.waker_set.inner.get() } } } impl DerefMut for Lock<'_> { #[inline] fn deref_mut(&mut self) -> &mut Inner { unsafe { &mut *self.waker_set.inner.get() } } } /// Notification strategy. #[derive(Clone, Copy, Eq, PartialEq)] enum Notify { /// Make sure at least one entry is notified. Any, /// Notify one additional entry. One, /// Notify all entries. All, } async-rs-async-std-57f61ae/src/task/000077500000000000000000000000001476537407000173425ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/task/block_on.rs000066400000000000000000000017771476537407000215120ustar00rootroot00000000000000use std::future::Future; use crate::task::Builder; /// Spawns a task and blocks the current thread on its result. /// /// Calling this function is similar to [spawning] a thread and immediately [joining] it, except an /// asynchronous task will be spawned. /// /// See also: [`task::spawn_blocking`]. /// /// [`task::spawn_blocking`]: fn.spawn_blocking.html /// /// [spawning]: https://doc.rust-lang.org/std/thread/fn.spawn.html /// [joining]: https://doc.rust-lang.org/std/thread/struct.JoinHandle.html#method.join /// /// # Examples /// /// ```no_run /// use async_std::task; /// /// task::block_on(async { /// println!("Hello, world!"); /// }) /// ``` #[cfg(not(target_os = "unknown"))] pub fn block_on(future: F) -> T where F: Future, { Builder::new().blocking(future) } /// Spawns a task and waits for it to finish. #[cfg(target_os = "unknown")] pub fn block_on(future: F) where F: Future + 'static, T: 'static, { Builder::new().local(future).unwrap(); } async-rs-async-std-57f61ae/src/task/builder.rs000066400000000000000000000136341476537407000213450ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll}; use pin_project_lite::pin_project; use crate::io; use crate::task::{JoinHandle, Task, TaskLocalsWrapper}; /// Task builder that configures the settings of a new task. #[derive(Debug, Default)] pub struct Builder { pub(crate) name: Option, } impl Builder { /// Creates a new builder. #[inline] pub fn new() -> Builder { Builder { name: None } } /// Configures the name of the task. #[inline] pub fn name(mut self, name: String) -> Builder { self.name = Some(name); self } fn build(self, future: F) -> SupportTaskLocals where F: Future, { let name = self.name.map(Arc::new); // Create a new task handle. let task = Task::new(name); #[cfg(not(target_os = "unknown"))] once_cell::sync::Lazy::force(&crate::rt::RUNTIME); let tag = TaskLocalsWrapper::new(task); SupportTaskLocals { tag, future } } /// Spawns a task with the configured settings. #[cfg(not(target_os = "unknown"))] pub fn spawn(self, future: F) -> io::Result> where F: Future + Send + 'static, T: Send + 'static, { let wrapped = self.build(future); kv_log_macro::trace!("spawn", { task_id: wrapped.tag.id().0, parent_task_id: TaskLocalsWrapper::get_current(|t| t.id().0).unwrap_or(0), }); let task = wrapped.tag.task().clone(); let handle = async_global_executor::spawn(wrapped); Ok(JoinHandle::new(handle, task)) } /// Spawns a task locally with the configured settings. #[cfg(all(not(target_os = "unknown"), feature = "unstable"))] pub fn local(self, future: F) -> io::Result> where F: Future + 'static, T: 'static, { let wrapped = self.build(future); kv_log_macro::trace!("spawn_local", { task_id: wrapped.tag.id().0, parent_task_id: TaskLocalsWrapper::get_current(|t| t.id().0).unwrap_or(0), }); let task = wrapped.tag.task().clone(); let handle = async_global_executor::spawn_local(wrapped); Ok(JoinHandle::new(handle, task)) } /// Spawns a task locally with the configured settings. #[cfg(all(target_arch = "wasm32", feature = "unstable"))] pub fn local(self, future: F) -> io::Result> where F: Future + 'static, T: 'static, { use futures_channel::oneshot::channel; let (sender, receiver) = channel(); let wrapped = self.build(async move { let res = future.await; let _ = sender.send(res); }); kv_log_macro::trace!("spawn_local", { task_id: wrapped.tag.id().0, parent_task_id: TaskLocalsWrapper::get_current(|t| t.id().0).unwrap_or(0), }); let task = wrapped.tag.task().clone(); wasm_bindgen_futures::spawn_local(wrapped); Ok(JoinHandle::new(receiver, task)) } /// Spawns a task locally with the configured settings. #[cfg(all(target_arch = "wasm32", not(feature = "unstable")))] pub(crate) fn local(self, future: F) -> io::Result> where F: Future + 'static, T: 'static, { use futures_channel::oneshot::channel; let (sender, receiver) = channel(); let wrapped = self.build(async move { let res = future.await; let _ = sender.send(res); }); kv_log_macro::trace!("spawn_local", { task_id: wrapped.tag.id().0, parent_task_id: TaskLocalsWrapper::get_current(|t| t.id().0).unwrap_or(0), }); let task = wrapped.tag.task().clone(); wasm_bindgen_futures::spawn_local(wrapped); Ok(JoinHandle::new(receiver, task)) } /// Spawns a task with the configured settings, blocking on its execution. #[cfg(not(target_os = "unknown"))] pub fn blocking(self, future: F) -> T where F: Future, { use std::cell::Cell; let wrapped = self.build(future); // Log this `block_on` operation. kv_log_macro::trace!("block_on", { task_id: wrapped.tag.id().0, parent_task_id: TaskLocalsWrapper::get_current(|t| t.id().0).unwrap_or(0), }); thread_local! { /// Tracks the number of nested block_on calls. static NUM_NESTED_BLOCKING: Cell = Cell::new(0); } // Run the future as a task. NUM_NESTED_BLOCKING.with(|num_nested_blocking| { let count = num_nested_blocking.get(); let should_run = count == 0; // increase the count num_nested_blocking.replace(count + 1); unsafe { TaskLocalsWrapper::set_current(&wrapped.tag, || { let res = if should_run { // The first call should run the executor async_global_executor::block_on(wrapped) } else { futures_lite::future::block_on(wrapped) }; num_nested_blocking.replace(num_nested_blocking.get() - 1); res }) } }) } } pin_project! { /// Wrapper to add support for task locals. struct SupportTaskLocals { tag: TaskLocalsWrapper, #[pin] future: F, } } impl Future for SupportTaskLocals { type Output = F::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { unsafe { TaskLocalsWrapper::set_current(&self.tag, || { let this = self.project(); this.future.poll(cx) }) } } } async-rs-async-std-57f61ae/src/task/current.rs000066400000000000000000000024251476537407000213750ustar00rootroot00000000000000use crate::task::{Task, TaskLocalsWrapper}; /// Returns a handle to the current task. /// /// # Panics /// /// This function will panic if not called within the context of a task created by [`block_on`], /// [`spawn`], or [`Builder::spawn`]. /// /// [`block_on`]: fn.block_on.html /// [`spawn`]: fn.spawn.html /// [`Builder::spawn`]: struct.Builder.html#method.spawn /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::task; /// /// println!("The name of this task is {:?}", task::current().name()); /// # /// # }) /// ``` pub fn current() -> Task { try_current().expect("`task::current()` called outside the context of a task") } /// Returns a handle to the current task if called within the context of a task created by [`block_on`], /// [`spawn`], or [`Builder::spawn`], otherwise returns `None`. /// /// [`block_on`]: fn.block_on.html /// [`spawn`]: fn.spawn.html /// [`Builder::spawn`]: struct.Builder.html#method.spawn /// /// # Examples /// /// ``` /// use async_std::task; /// /// match task::try_current() { /// Some(t) => println!("The name of this task is {:?}", t.name()), /// None => println!("Not inside a task!"), /// } /// ``` pub fn try_current() -> Option { TaskLocalsWrapper::get_current(|t| t.task().clone()) }async-rs-async-std-57f61ae/src/task/join_handle.rs000066400000000000000000000046741476537407000221750ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use crate::task::{Context, Poll, Task}; /// A handle that awaits the result of a task. /// /// Dropping a [`JoinHandle`] will detach the task, meaning that there is no longer /// a handle to the task and no way to `join` on it. /// /// Created when a task is [spawned]. /// /// [spawned]: fn.spawn.html #[derive(Debug)] pub struct JoinHandle { handle: Option>, task: Task, } #[cfg(not(target_os = "unknown"))] type InnerHandle = async_global_executor::Task; #[cfg(target_arch = "wasm32")] type InnerHandle = futures_channel::oneshot::Receiver; impl JoinHandle { /// Creates a new `JoinHandle`. pub(crate) fn new(inner: InnerHandle, task: Task) -> JoinHandle { JoinHandle { handle: Some(inner), task, } } /// Returns a handle to the underlying task. /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::task; /// /// let handle = task::spawn(async { /// 1 + 2 /// }); /// println!("id = {}", handle.task().id()); /// # /// # }) pub fn task(&self) -> &Task { &self.task } /// Cancel this task. #[cfg(not(target_os = "unknown"))] pub async fn cancel(mut self) -> Option { let handle = self.handle.take().unwrap(); handle.cancel().await } /// Cancel this task. #[cfg(target_arch = "wasm32")] pub async fn cancel(mut self) -> Option { let mut handle = self.handle.take().unwrap(); handle.close(); handle.await.ok() } } #[cfg(not(target_os = "unknown"))] impl Drop for JoinHandle { fn drop(&mut self) { if let Some(handle) = self.handle.take() { handle.detach(); } } } impl Future for JoinHandle { type Output = T; #[cfg(not(target_os = "unknown"))] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { Pin::new(&mut self.handle.as_mut().unwrap()).poll(cx) } #[cfg(target_arch = "wasm32")] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match Pin::new(&mut self.handle.as_mut().unwrap()).poll(cx) { Poll::Ready(Ok(t)) => Poll::Ready(t), Poll::Ready(Err(_)) => unreachable!("channel must not be canceled"), Poll::Pending => Poll::Pending, } } } async-rs-async-std-57f61ae/src/task/mod.rs000066400000000000000000000133221476537407000204700ustar00rootroot00000000000000//! Types and traits for working with asynchronous tasks. //! //! This module is similar to [`std::thread`], except it uses asynchronous tasks in place of //! threads. //! //! [`std::thread`]: https://doc.rust-lang.org/std/thread //! //! ## The task model //! //! An executing asynchronous Rust program consists of a collection of native OS threads, on top of //! which multiple stackless coroutines are multiplexed. We refer to these as "tasks". Tasks can //! be named, and provide some built-in support for synchronization. //! //! Communication between tasks can be done through channels, Rust's message-passing types, along //! with [other forms of tasks synchronization](../sync/index.html) and shared-memory data //! structures. In particular, types that are guaranteed to be threadsafe are easily shared between //! tasks using the atomically-reference-counted container, [`Arc`]. //! //! Fatal logic errors in Rust cause *thread panic*, during which a thread will unwind the stack, //! running destructors and freeing owned resources. If a panic occurs inside a task, there is no //! meaningful way of recovering, so the panic will propagate through any thread boundaries all the //! way to the root task. This is also known as a "panic = abort" model. //! //! ## Spawning a task //! //! A new task can be spawned using the [`task::spawn`][`spawn`] function: //! //! ```no_run //! use async_std::task; //! //! task::spawn(async { //! // some work here //! }); //! ``` //! //! In this example, the spawned task is "detached" from the current task. This means that it can //! outlive its parent (the task that spawned it), unless this parent is the root task. //! //! The root task can also wait on the completion of the child task; a call to [`spawn`] produces a //! [`JoinHandle`], which implements `Future` and can be `await`ed: //! //! ``` //! use async_std::task; //! //! # async_std::task::block_on(async { //! # //! let child = task::spawn(async { //! // some work here //! }); //! // some work here //! let res = child.await; //! # //! # }) //! ``` //! //! The `await` operator returns the final value produced by the child task. //! //! ## Configuring tasks //! //! A new task can be configured before it is spawned via the [`Builder`] type, //! which currently allows you to set the name for the child task: //! //! ``` //! # #![allow(unused_must_use)] //! use async_std::task; //! //! # async_std::task::block_on(async { //! # //! task::Builder::new().name("child1".to_string()).spawn(async { //! println!("Hello, world!"); //! }); //! # //! # }) //! ``` //! //! ## The `Task` type //! //! Tasks are represented via the [`Task`] type, which you can get in one of //! two ways: //! //! * By spawning a new task, e.g., using the [`task::spawn`][`spawn`] //! function, and calling [`task`][`JoinHandle::task`] on the [`JoinHandle`]. //! * By requesting the current task, using the [`task::current`] function. //! //! ## Task-local storage //! //! This module also provides an implementation of task-local storage for Rust //! programs. Task-local storage is a method of storing data into a global //! variable that each task in the program will have its own copy of. //! Tasks do not share this data, so accesses do not need to be synchronized. //! //! A task-local key owns the value it contains and will destroy the value when the //! task exits. It is created with the [`task_local!`] macro and can contain any //! value that is `'static` (no borrowed pointers). It provides an accessor function, //! [`with`], that yields a shared reference to the value to the specified //! closure. Task-local keys allow only shared access to values, as there would be no //! way to guarantee uniqueness if mutable borrows were allowed. //! //! ## Naming tasks //! //! Tasks are able to have associated names for identification purposes. By default, spawned //! tasks are unnamed. To specify a name for a task, build the task with [`Builder`] and pass //! the desired task name to [`Builder::name`]. To retrieve the task name from within the //! task, use [`Task::name`]. //! //! [`Arc`]: ../sync/struct.Arc.html //! [`spawn`]: fn.spawn.html //! [`JoinHandle`]: struct.JoinHandle.html //! [`JoinHandle::task`]: struct.JoinHandle.html#method.task //! [`join`]: struct.JoinHandle.html#method.join //! [`panic!`]: https://doc.rust-lang.org/std/macro.panic.html //! [`Builder`]: struct.Builder.html //! [`Builder::name`]: struct.Builder.html#method.name //! [`task::current`]: fn.current.html //! [`Task`]: struct.Task.html //! [`Task::name`]: struct.Task.html#method.name //! [`task_local!`]: ../macro.task_local.html //! [`with`]: struct.LocalKey.html#method.with cfg_alloc! { #[doc(inline)] pub use core::task::{Context, Poll, Waker}; pub use ready::ready; mod ready; } cfg_std! { pub use yield_now::yield_now; mod yield_now; } cfg_default! { pub use block_on::block_on; pub use builder::Builder; pub use current::{current, try_current}; pub use task::Task; pub use task_id::TaskId; pub use join_handle::JoinHandle; pub use sleep::sleep; #[cfg(not(target_os = "unknown"))] pub use spawn::spawn; pub use task_local::{AccessError, LocalKey}; pub(crate) use task_local::LocalsMap; pub(crate) use task_locals_wrapper::TaskLocalsWrapper; mod block_on; mod builder; mod current; mod join_handle; mod sleep; #[cfg(not(target_os = "unknown"))] mod spawn; #[cfg(not(target_os = "unknown"))] mod spawn_blocking; mod task; mod task_id; mod task_local; mod task_locals_wrapper; #[cfg(not(target_os = "unknown"))] pub use spawn_blocking::spawn_blocking; } cfg_unstable! { #[cfg(feature = "default")] pub use spawn_local::spawn_local; #[cfg(feature = "default")] mod spawn_local; } async-rs-async-std-57f61ae/src/task/ready.rs000066400000000000000000000002371476537407000210160ustar00rootroot00000000000000/// Extracts the successful type of a `Poll`. /// /// This macro bakes in propagation of `Pending` signals by returning early. pub use futures_core::ready; async-rs-async-std-57f61ae/src/task/sleep.rs000066400000000000000000000014031476537407000210160ustar00rootroot00000000000000use std::time::Duration; use crate::future; use crate::io; /// Sleeps for the specified amount of time. /// /// This function might sleep for slightly longer than the specified duration but never less. /// /// This function is an async version of [`std::thread::sleep`]. /// /// [`std::thread::sleep`]: https://doc.rust-lang.org/std/thread/fn.sleep.html /// /// See also: [`stream::interval`]. /// /// [`stream::interval`]: ../stream/fn.interval.html /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use std::time::Duration; /// /// use async_std::task; /// /// task::sleep(Duration::from_secs(1)).await; /// # /// # }) /// ``` pub async fn sleep(dur: Duration) { let _: io::Result<()> = io::timeout(dur, future::pending()).await; } async-rs-async-std-57f61ae/src/task/spawn.rs000066400000000000000000000012371476537407000210430ustar00rootroot00000000000000use std::future::Future; use crate::task::{Builder, JoinHandle}; /// Spawns a task. /// /// This function is similar to [`std::thread::spawn`], except it spawns an asynchronous task. /// /// [`std::thread`]: https://doc.rust-lang.org/std/thread/fn.spawn.html /// /// # Examples /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::task; /// /// let handle = task::spawn(async { /// 1 + 2 /// }); /// /// assert_eq!(handle.await, 3); /// # /// # }) /// ``` pub fn spawn(future: F) -> JoinHandle where F: Future + Send + 'static, T: Send + 'static, { Builder::new().spawn(future).expect("cannot spawn task") } async-rs-async-std-57f61ae/src/task/spawn_blocking.rs000066400000000000000000000015101476537407000227050ustar00rootroot00000000000000use crate::task::{self, JoinHandle}; /// Spawns a blocking task. /// /// The task will be spawned onto a thread pool specifically dedicated to blocking tasks. This /// is useful to prevent long-running synchronous operations from blocking the main futures /// executor. /// /// See also: [`task::block_on`], [`task::spawn`]. /// /// [`task::block_on`]: fn.block_on.html /// [`task::spawn`]: fn.spawn.html /// /// # Examples /// /// Basic usage: /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::task; /// /// task::spawn_blocking(|| { /// println!("long-running task here"); /// }) /// .await; /// # /// # }) /// ``` #[inline] pub fn spawn_blocking(f: F) -> JoinHandle where F: FnOnce() -> T + Send + 'static, T: Send + 'static, { task::spawn(async_global_executor::spawn_blocking(f)) } async-rs-async-std-57f61ae/src/task/spawn_local.rs000066400000000000000000000011541476537407000222130ustar00rootroot00000000000000use std::future::Future; use crate::task::{Builder, JoinHandle}; /// Spawns a task onto the thread-local executor. /// /// # Examples /// /// ``` /// # #[cfg(feature = "unstable")] /// # async_std::task::block_on(async { /// # /// use async_std::task; /// /// let handle = task::spawn_local(async { /// 1 + 2 /// }); /// /// assert_eq!(handle.await, 3); /// # /// # }) /// ``` #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[inline] pub fn spawn_local(future: F) -> JoinHandle where F: Future + 'static, T: 'static, { Builder::new().local(future).expect("cannot spawn task") } async-rs-async-std-57f61ae/src/task/task.rs000066400000000000000000000020341476537407000206510ustar00rootroot00000000000000use std::fmt; use std::sync::Arc; use crate::task::TaskId; /// A handle to a task. #[derive(Clone)] pub struct Task { /// The task ID. id: TaskId, /// The optional task name. name: Option>, } impl Task { /// Creates a new task handle. #[inline] pub(crate) fn new(name: Option>) -> Task { Task { id: TaskId::generate(), name, } } /// Gets the task's unique identifier. #[inline] pub fn id(&self) -> TaskId { self.id } /// Returns the name of this task. /// /// The name is configured by [`Builder::name`] before spawning. /// /// [`Builder::name`]: struct.Builder.html#method.name pub fn name(&self) -> Option<&str> { self.name.as_ref().map(|s| s.as_str()) } } impl fmt::Debug for Task { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Task") .field("id", &self.id()) .field("name", &self.name()) .finish() } } async-rs-async-std-57f61ae/src/task/task_id.rs000066400000000000000000000015551476537407000213340ustar00rootroot00000000000000use std::fmt; use std::sync::atomic::{AtomicUsize, Ordering}; /// A unique identifier for a task. /// /// # Examples /// /// ``` /// use async_std::task; /// /// task::block_on(async { /// println!("id = {:?}", task::current().id()); /// }) /// ``` #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] pub struct TaskId(pub(crate) usize); impl TaskId { /// Generates a new `TaskId`. pub(crate) fn generate() -> TaskId { // TODO: find a good version to emulate u64 atomics on 32 bit systems. static COUNTER: AtomicUsize = AtomicUsize::new(1); let id = COUNTER.fetch_add(1, Ordering::Relaxed); if id > usize::max_value() / 2 { std::process::abort(); } TaskId(id) } } impl fmt::Display for TaskId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) } } async-rs-async-std-57f61ae/src/task/task_local.rs000066400000000000000000000145131476537407000220300ustar00rootroot00000000000000use std::cell::UnsafeCell; use std::error::Error; use std::fmt; use std::sync::atomic::{AtomicU32, Ordering}; use crate::task::TaskLocalsWrapper; /// The key for accessing a task-local value. /// /// Every task-local value is lazily initialized on first access and destroyed when the task /// completes. #[derive(Debug)] pub struct LocalKey { #[doc(hidden)] pub __init: fn() -> T, #[doc(hidden)] pub __key: AtomicU32, } impl LocalKey { /// Gets a reference to the task-local value with this key. /// /// The passed closure receives a reference to the task-local value. /// /// The task-local value will be lazily initialized if this task has not accessed it before. /// /// # Panics /// /// This function will panic if not called within the context of a task created by /// [`block_on`], [`spawn`], or [`Builder::spawn`]. /// /// [`block_on`]: fn.block_on.html /// [`spawn`]: fn.spawn.html /// [`Builder::spawn`]: struct.Builder.html#method.spawn /// /// # Examples /// /// ``` /// # /// use std::cell::Cell; /// /// use async_std::task; /// use async_std::prelude::*; /// /// task_local! { /// static NUMBER: Cell = Cell::new(5); /// } /// /// task::block_on(async { /// let v = NUMBER.with(|c| c.get()); /// assert_eq!(v, 5); /// }); /// ``` pub fn with(&'static self, f: F) -> R where F: FnOnce(&T) -> R, { self.try_with(f) .expect("`LocalKey::with` called outside the context of a task") } /// Attempts to get a reference to the task-local value with this key. /// /// The passed closure receives a reference to the task-local value. /// /// The task-local value will be lazily initialized if this task has not accessed it before. /// /// This function returns an error if not called within the context of a task created by /// [`block_on`], [`spawn`], or [`Builder::spawn`]. /// /// [`block_on`]: fn.block_on.html /// [`spawn`]: fn.spawn.html /// [`Builder::spawn`]: struct.Builder.html#method.spawn /// /// # Examples /// /// ``` /// # /// use std::cell::Cell; /// /// use async_std::task; /// use async_std::prelude::*; /// /// task_local! { /// static VAL: Cell = Cell::new(5); /// } /// /// task::block_on(async { /// let v = VAL.try_with(|c| c.get()); /// assert_eq!(v, Ok(5)); /// }); /// /// // Returns an error because not called within the context of a task. /// assert!(VAL.try_with(|c| c.get()).is_err()); /// ``` pub fn try_with(&'static self, f: F) -> Result where F: FnOnce(&T) -> R, { TaskLocalsWrapper::get_current(|task| unsafe { // Prepare the numeric key, initialization function, and the map of task-locals. let key = self.key(); let init = || Box::new((self.__init)()) as Box; // Get the value in the map of task-locals, or initialize and insert one. let value: *const dyn Send = task.locals().get_or_insert(key, init); // Call the closure with the value passed as an argument. f(&*(value as *const T)) }) .ok_or(AccessError { _private: () }) } /// Returns the numeric key associated with this task-local. #[inline] fn key(&self) -> u32 { #[cold] fn init(key: &AtomicU32) -> u32 { static COUNTER: AtomicU32 = AtomicU32::new(1); let counter = COUNTER.fetch_add(1, Ordering::Relaxed); if counter > u32::max_value() / 2 { std::process::abort(); } match key.compare_exchange(0, counter, Ordering::AcqRel, Ordering::Acquire) { Ok(_) => counter, Err(k) => k, } } match self.__key.load(Ordering::Acquire) { 0 => init(&self.__key), k => k, } } } /// An error returned by [`LocalKey::try_with`]. /// /// [`LocalKey::try_with`]: struct.LocalKey.html#method.try_with #[derive(Clone, Copy, Eq, PartialEq)] pub struct AccessError { _private: (), } impl fmt::Debug for AccessError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("AccessError").finish() } } impl fmt::Display for AccessError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "already destroyed or called outside the context of a task".fmt(f) } } impl Error for AccessError {} /// A key-value entry in a map of task-locals. struct Entry { /// Key identifying the task-local variable. key: u32, /// Value stored in this entry. value: Box, } /// A map that holds task-locals. pub(crate) struct LocalsMap { /// A list of key-value entries sorted by the key. entries: UnsafeCell>>, } impl LocalsMap { /// Creates an empty map of task-locals. pub fn new() -> LocalsMap { LocalsMap { entries: UnsafeCell::new(Some(Vec::new())), } } /// Returns a task-local value associated with `key` or inserts one constructed by `init`. #[inline] pub fn get_or_insert(&self, key: u32, init: impl FnOnce() -> Box) -> &dyn Send { match unsafe { (*self.entries.get()).as_mut() } { None => panic!("can't access task-locals while the task is being dropped"), Some(entries) => { let index = match entries.binary_search_by_key(&key, |e| e.key) { Ok(i) => i, Err(i) => { let value = init(); entries.insert(i, Entry { key, value }); i } }; &*entries[index].value } } } /// Clears the map and drops all task-locals. /// /// This method is only safe to call at the end of the task. pub unsafe fn clear(&self) { // Since destructors may attempt to access task-locals, we musnt't hold a mutable reference // to the `Vec` while dropping them. Instead, we first take the `Vec` out and then drop it. let entries = (*self.entries.get()).take(); drop(entries); } } async-rs-async-std-57f61ae/src/task/task_locals_wrapper.rs000066400000000000000000000040561476537407000237540ustar00rootroot00000000000000use std::cell::Cell; use std::ptr; use crate::task::{LocalsMap, Task, TaskId}; use crate::utils::abort_on_panic; thread_local! { /// A pointer to the currently running task. static CURRENT: Cell<*const TaskLocalsWrapper> = Cell::new(ptr::null_mut()); } /// A wrapper to store task local data. pub(crate) struct TaskLocalsWrapper { /// The actual task details. task: Task, /// The map holding task-local values. locals: LocalsMap, } impl TaskLocalsWrapper { /// Creates a new task handle. /// /// If the task is unnamed, the inner representation of the task will be lazily allocated on /// demand. #[inline] pub(crate) fn new(task: Task) -> Self { Self { task, locals: LocalsMap::new(), } } /// Gets the task's unique identifier. #[inline] pub fn id(&self) -> TaskId { self.task.id() } /// Returns a reference to the inner `Task`. pub(crate) fn task(&self) -> &Task { &self.task } /// Returns the map holding task-local values. pub(crate) fn locals(&self) -> &LocalsMap { &self.locals } /// Set a reference to the current task. pub(crate) unsafe fn set_current(task: *const TaskLocalsWrapper, f: F) -> R where F: FnOnce() -> R, { CURRENT.with(|current| { let old_task = current.replace(task); defer! { current.set(old_task); } f() }) } /// Gets a reference to the current task. pub(crate) fn get_current(f: F) -> Option where F: FnOnce(&TaskLocalsWrapper) -> R, { let res = CURRENT.try_with(|current| unsafe { current.get().as_ref().map(f) }); match res { Ok(Some(val)) => Some(val), Ok(None) | Err(_) => None, } } } impl Drop for TaskLocalsWrapper { fn drop(&mut self) { // Abort the process if dropping task-locals panics. abort_on_panic(|| { unsafe { self.locals.clear() }; }); } } async-rs-async-std-57f61ae/src/task/yield_now.rs000066400000000000000000000023501476537407000217010ustar00rootroot00000000000000use std::future::Future; use std::pin::Pin; use crate::task::{Context, Poll}; /// Cooperatively gives up a timeslice to the task scheduler. /// /// Calling this function will move the currently executing future to the back /// of the execution queue, making room for other futures to execute. This is /// especially useful after running CPU-intensive operations inside a future. /// /// See also [`task::spawn_blocking`]. /// /// [`task::spawn_blocking`]: fn.spawn_blocking.html /// /// # Examples /// /// Basic usage: /// /// ``` /// # async_std::task::block_on(async { /// # /// use async_std::task; /// /// task::yield_now().await; /// # /// # }) /// ``` #[inline] pub async fn yield_now() { YieldNow(false).await } struct YieldNow(bool); impl Future for YieldNow { type Output = (); // The futures executor is implemented as a FIFO queue, so all this future // does is re-schedule the future back to the end of the queue, giving room // for other futures to progress. fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if !self.0 { self.0 = true; cx.waker().wake_by_ref(); Poll::Pending } else { Poll::Ready(()) } } } async-rs-async-std-57f61ae/src/unit/000077500000000000000000000000001476537407000173575ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/unit/extend.rs000066400000000000000000000010021476537407000212050ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend<()> for () { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); Box::pin(async move { pin_utils::pin_mut!(stream); while let Some(_) = stream.next().await {} }) } } async-rs-async-std-57f61ae/src/unit/from_stream.rs000066400000000000000000000006021476537407000222410ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{FromStream, IntoStream}; impl FromStream<()> for () { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { Box::pin(stream.into_stream().for_each(drop)) } } async-rs-async-std-57f61ae/src/unit/mod.rs000066400000000000000000000003221476537407000205010ustar00rootroot00000000000000//! The Rust primitive `()` type, sometimes called "unit" or "nil". //! //! This module provides types and implementations for working //! asynchronously with values of type `()`. mod from_stream; mod extend; async-rs-async-std-57f61ae/src/utils.rs000066400000000000000000000130701476537407000201070ustar00rootroot00000000000000/// Calls a function and aborts if it panics. /// /// This is useful in unsafe code where we can't recover from panics. #[cfg(feature = "default")] #[inline] pub fn abort_on_panic(f: impl FnOnce() -> T) -> T { struct Bomb; impl Drop for Bomb { fn drop(&mut self) { std::process::abort(); } } let bomb = Bomb; let t = f(); std::mem::forget(bomb); t } /// Generates a random number in `0..n`. #[cfg(feature = "unstable")] pub fn random(n: u32) -> u32 { use std::cell::Cell; use std::num::Wrapping; thread_local! { static RNG: Cell> = { // Take the address of a local value as seed. let mut x = 0i32; let r = &mut x; let addr = r as *mut i32 as usize; Cell::new(Wrapping(addr as u32)) } } RNG.with(|rng| { // This is the 32-bit variant of Xorshift. // // Source: https://en.wikipedia.org/wiki/Xorshift let mut x = rng.get(); x ^= x << 13; x ^= x >> 17; x ^= x << 5; rng.set(x); // This is a fast alternative to `x % n`. // // Author: Daniel Lemire // Source: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ ((u64::from(x.0)).wrapping_mul(u64::from(n)) >> 32) as u32 }) } /// Add additional context to errors #[cfg(feature = "std")] pub(crate) trait Context { fn context(self, message: impl Fn() -> String) -> Self; } #[cfg(all( not(target_os = "unknown"), any(feature = "default", feature = "unstable") ))] mod timer { pub type Timer = async_io::Timer; } #[cfg(any(feature = "unstable", feature = "default"))] pub(crate) fn timer_after(dur: std::time::Duration) -> timer::Timer { Timer::after(dur) } #[cfg(any(all(target_arch = "wasm32", feature = "default"),))] mod timer { use std::pin::Pin; use std::task::Poll; use gloo_timers::future::TimeoutFuture; #[derive(Debug)] pub(crate) struct Timer(TimeoutFuture); impl Timer { pub(crate) fn after(dur: std::time::Duration) -> Self { // Round up to the nearest millisecond. let mut timeout_ms = dur.as_millis() as u32; if std::time::Duration::from_millis(timeout_ms as u64) < dur { timeout_ms += 1; } Timer(TimeoutFuture::new(timeout_ms)) } } impl std::future::Future for Timer { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { match Pin::new(&mut self.0).poll(cx) { Poll::Pending => Poll::Pending, Poll::Ready(_) => Poll::Ready(()), } } } } #[cfg(any(feature = "unstable", feature = "default"))] pub(crate) use timer::*; /// Defers evaluation of a block of code until the end of the scope. #[cfg(feature = "default")] #[doc(hidden)] macro_rules! defer { ($($body:tt)*) => { let _guard = { pub struct Guard(Option); impl Drop for Guard { fn drop(&mut self) { (self.0).take().map(|f| f()); } } Guard(Some(|| { let _ = { $($body)* }; })) }; }; } /// Declares unstable items. #[doc(hidden)] macro_rules! cfg_unstable { ($($item:item)*) => { $( #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] $item )* } } /// Declares unstable and default items. #[doc(hidden)] macro_rules! cfg_unstable_default { ($($item:item)*) => { $( #[cfg(all(feature = "default", feature = "unstable"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] $item )* } } /// Declares Unix-specific items. #[doc(hidden)] #[allow(unused_macros)] macro_rules! cfg_unix { ($($item:item)*) => { $( #[cfg(any(unix, feature = "docs"))] $item )* } } /// Declares Windows-specific items. #[doc(hidden)] #[allow(unused_macros)] macro_rules! cfg_windows { ($($item:item)*) => { $( #[cfg(any(windows, feature = "docs"))] $item )* } } /// Declares items when the "docs" feature is enabled. #[doc(hidden)] #[allow(unused_macros)] macro_rules! cfg_docs { ($($item:item)*) => { $( #[cfg(feature = "docs")] $item )* } } /// Declares items when the "docs" feature is disabled. #[doc(hidden)] #[allow(unused_macros)] macro_rules! cfg_not_docs { ($($item:item)*) => { $( #[cfg(not(feature = "docs"))] $item )* } } /// Declares std items. #[allow(unused_macros)] #[doc(hidden)] macro_rules! cfg_std { ($($item:item)*) => { $( #[cfg(feature = "std")] $item )* } } /// Declares no-std items. #[allow(unused_macros)] #[doc(hidden)] macro_rules! cfg_alloc { ($($item:item)*) => { $( #[cfg(feature = "alloc")] $item )* } } /// Declares default items. #[allow(unused_macros)] #[doc(hidden)] macro_rules! cfg_default { ($($item:item)*) => { $( #[cfg(feature = "default")] $item )* } } /// Declares items that use I/O safety. #[allow(unused_macros)] #[doc(hidden)] macro_rules! cfg_io_safety { ($($item:item)*) => { $( #[cfg(feature = "io_safety")] $item )* } } async-rs-async-std-57f61ae/src/vec/000077500000000000000000000000001476537407000171555ustar00rootroot00000000000000async-rs-async-std-57f61ae/src/vec/extend.rs000066400000000000000000000007561476537407000210220ustar00rootroot00000000000000use std::pin::Pin; use crate::prelude::*; use crate::stream::{self, IntoStream}; impl stream::Extend for Vec { fn extend<'a, S: IntoStream + 'a>( &'a mut self, stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send, { let stream = stream.into_stream(); self.reserve(stream.size_hint().0); Box::pin(stream.for_each(move |item| self.push(item))) } } async-rs-async-std-57f61ae/src/vec/from_stream.rs000066400000000000000000000042321476537407000220420ustar00rootroot00000000000000use std::borrow::Cow; use std::pin::Pin; use std::rc::Rc; use std::sync::Arc; use crate::prelude::*; use crate::stream::{self, FromStream, IntoStream}; impl FromStream for Vec { #[inline] fn from_stream<'a, S: IntoStream>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: 'a + Send, { let stream = stream.into_stream(); Box::pin(async move { let mut out = vec![]; stream::extend(&mut out, stream).await; out }) } } impl<'b, T: Clone + Send> FromStream for Cow<'b, [T]> { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send { let stream = stream.into_stream(); Box::pin(async move { Cow::Owned(FromStream::from_stream(stream).await) }) } } impl FromStream for Box<[T]> { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send { let stream = stream.into_stream(); Box::pin(async move { Vec::from_stream(stream).await.into_boxed_slice() }) } } impl FromStream for Rc<[T]> { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send { let stream = stream.into_stream(); Box::pin(async move { Vec::from_stream(stream).await.into() }) } } impl FromStream for Arc<[T]> { #[inline] fn from_stream<'a, S: IntoStream + 'a>( stream: S, ) -> Pin + 'a + Send>> where ::IntoStream: Send { let stream = stream.into_stream(); Box::pin(async move { Vec::from_stream(stream).await.into() }) } } async-rs-async-std-57f61ae/src/vec/mod.rs000066400000000000000000000003601476537407000203010ustar00rootroot00000000000000//! The Rust core allocation and collections library //! //! This library provides smart pointers and collections for managing //! heap-allocated values. mod extend; mod from_stream; #[allow(unused)] #[doc(inline)] pub use std::vec::Vec; async-rs-async-std-57f61ae/tests/000077500000000000000000000000001476537407000167535ustar00rootroot00000000000000async-rs-async-std-57f61ae/tests/addr.rs000066400000000000000000000050671476537407000202430ustar00rootroot00000000000000#![cfg(not(target_os = "unknown"))] use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use async_std::net::ToSocketAddrs; use async_std::task; fn blocking_resolve(a: A) -> Result, String> where A: ToSocketAddrs, A::Iter: Send, { let socket_addrs = task::block_on(a.to_socket_addrs()); match socket_addrs { Ok(a) => Ok(a.collect()), Err(e) => Err(e.to_string()), } } #[test] fn to_socket_addr_ipaddr_u16() { let a = Ipv4Addr::new(77, 88, 21, 11); let p = 12345; let e = SocketAddr::V4(SocketAddrV4::new(a, p)); assert_eq!(Ok(vec![e]), blocking_resolve((a, p))); } #[test] fn to_socket_addr_str_u16() { let a = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 24352)); assert_eq!(Ok(vec![a]), blocking_resolve(("77.88.21.11", 24352))); let a = SocketAddr::V6(SocketAddrV6::new( Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0, )); assert_eq!(Ok(vec![a]), blocking_resolve(("2a02:6b8:0:1::1", 53))); let a = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 23924)); #[cfg(not(target_env = "sgx"))] assert!(blocking_resolve(("localhost", 23924)).unwrap().contains(&a)); #[cfg(target_env = "sgx")] let _ = a; } #[test] fn to_socket_addr_str() { let a = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 24352)); assert_eq!(Ok(vec![a]), blocking_resolve("77.88.21.11:24352")); let a = SocketAddr::V6(SocketAddrV6::new( Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0, )); assert_eq!(Ok(vec![a]), blocking_resolve("[2a02:6b8:0:1::1]:53")); let a = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 23924)); #[cfg(not(target_env = "sgx"))] assert!(blocking_resolve("localhost:23924").unwrap().contains(&a)); #[cfg(target_env = "sgx")] let _ = a; } #[test] fn to_socket_addr_string() { let a = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 24352)); let s: &str = "77.88.21.11:24352"; assert_eq!(Ok(vec![a]), blocking_resolve(s)); let s: &String = &"77.88.21.11:24352".to_string(); assert_eq!(Ok(vec![a]), blocking_resolve(s)); let s: String = "77.88.21.11:24352".to_string(); assert_eq!(Ok(vec![a]), blocking_resolve(s)); } // FIXME: figure out why this fails on openbsd and fix it #[test] #[cfg(not(any(windows, target_os = "openbsd")))] fn to_socket_addr_str_bad() { assert!(blocking_resolve("1200::AB00:1234::2552:7777:1313:34300").is_err()); } async-rs-async-std-57f61ae/tests/block_on.rs000066400000000000000000000032621476537407000211120ustar00rootroot00000000000000#![cfg(not(target_os = "unknown"))] use async_std::{future::ready, task::block_on}; #[test] fn smoke() { let res = block_on(async { 1 + 2 }); assert_eq!(res, 3); } #[test] #[should_panic = "boom"] fn panic() { block_on(async { // This panic should get propagated into the parent thread. panic!("boom"); }); } #[cfg(feature = "unstable")] #[test] fn nested_block_on_local() { use async_std::task::spawn_local; let x = block_on(async { let a = block_on(async { block_on(async { ready(3).await }) }); let b = spawn_local(async { block_on(async { ready(2).await }) }).await; let c = block_on(async { block_on(async { ready(1).await }) }); a + b + c }); assert_eq!(x, 3 + 2 + 1); let y = block_on(async { let a = block_on(async { block_on(async { ready(3).await }) }); let b = spawn_local(async { block_on(async { ready(2).await }) }).await; let c = block_on(async { block_on(async { ready(1).await }) }); a + b + c }); assert_eq!(y, 3 + 2 + 1); } #[test] fn nested_block_on() { let x = block_on(async { let a = block_on(async { block_on(async { ready(3).await }) }); let b = block_on(async { block_on(async { ready(2).await }) }); let c = block_on(async { block_on(async { ready(1).await }) }); a + b + c }); assert_eq!(x, 3 + 2 + 1); let y = block_on(async { let a = block_on(async { block_on(async { ready(3).await }) }); let b = block_on(async { block_on(async { ready(2).await }) }); let c = block_on(async { block_on(async { ready(1).await }) }); a + b + c }); assert_eq!(y, 3 + 2 + 1); } async-rs-async-std-57f61ae/tests/buf_writer.rs000066400000000000000000000054051476537407000214750ustar00rootroot00000000000000use async_std::io::{self, BufWriter, SeekFrom}; use async_std::prelude::*; use async_std::task; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn test_buffered_writer() { #![allow(clippy::cognitive_complexity)] task::block_on(async { let inner: Vec = Vec::new(); let mut writer = BufWriter::>::with_capacity(2, inner); writer.write(&[0, 1]).await.unwrap(); assert!(writer.buffer().is_empty()); assert_eq!(*writer.get_ref(), [0, 1]); writer.write(&[2]).await.unwrap(); assert_eq!(writer.buffer(), [2]); assert_eq!(*writer.get_ref(), [0, 1]); writer.write(&[3]).await.unwrap(); assert_eq!(writer.buffer(), [2, 3]); assert_eq!(*writer.get_ref(), [0, 1]); writer.flush().await.unwrap(); assert!(writer.buffer().is_empty()); assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); writer.write(&[4]).await.unwrap(); writer.write(&[5]).await.unwrap(); assert_eq!(writer.buffer(), [4, 5]); assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); writer.write(&[6]).await.unwrap(); assert_eq!(writer.buffer(), [6]); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]); writer.write(&[7, 8]).await.unwrap(); assert!(writer.buffer().is_empty()); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]); writer.write(&[9, 10, 11]).await.unwrap(); assert!(writer.buffer().is_empty()); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); writer.flush().await.unwrap(); assert!(writer.buffer().is_empty()); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn test_buffered_writer_inner_into_inner_flushes() { task::block_on(async { let mut w = BufWriter::with_capacity(3, Vec::::new()); w.write(&[0, 1]).await.unwrap(); assert!(w.get_ref().is_empty()); let w = w.into_inner().await.unwrap(); assert_eq!(w, [0, 1]); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn test_buffered_writer_seek() { task::block_on(async { let mut w = BufWriter::with_capacity(3, io::Cursor::new(Vec::new())); w.write_all(&[0, 1, 2, 3, 4, 5]).await.unwrap(); w.write_all(&[6, 7]).await.unwrap(); assert_eq!(w.seek(SeekFrom::Current(0)).await.ok(), Some(8)); assert_eq!(&w.get_ref().get_ref()[..], &[0, 1, 2, 3, 4, 5, 6, 7][..]); assert_eq!(w.seek(SeekFrom::Start(2)).await.ok(), Some(2)); }) } async-rs-async-std-57f61ae/tests/channel.rs000066400000000000000000000224061476537407000207350ustar00rootroot00000000000000use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::time::Duration; use async_std::channel::bounded as channel; use async_std::task; use rand::{Rng, SeedableRng}; #[cfg(not(target_os = "unknown"))] use async_std::task::spawn; #[cfg(target_os = "unknown")] use async_std::task::spawn_local as spawn; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); fn ms(ms: u64) -> Duration { Duration::from_millis(ms) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn smoke() { task::block_on(async { let (s, r) = channel(1); s.send(7).await.unwrap(); assert_eq!(r.recv().await.unwrap(), 7); s.send(8).await.unwrap(); assert_eq!(r.recv().await.unwrap(), 8); drop(s); assert!(r.recv().await.is_err()); }); task::block_on(async { let (s, r) = channel(10); drop(r); assert!(s.send(1).await.is_err()); }); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn capacity() { for i in 1..10 { let (s, r) = channel::<()>(i); assert_eq!(s.capacity().unwrap(), i); assert_eq!(r.capacity().unwrap(), i); } } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn len_empty_full() { #![allow(clippy::cognitive_complexity)] task::block_on(async { let (s, r) = channel(2); assert_eq!(s.len(), 0); assert_eq!(s.is_empty(), true); assert_eq!(s.is_full(), false); assert_eq!(r.len(), 0); assert_eq!(r.is_empty(), true); assert_eq!(r.is_full(), false); s.send(()).await.unwrap(); assert_eq!(s.len(), 1); assert_eq!(s.is_empty(), false); assert_eq!(s.is_full(), false); assert_eq!(r.len(), 1); assert_eq!(r.is_empty(), false); assert_eq!(r.is_full(), false); s.send(()).await.unwrap(); assert_eq!(s.len(), 2); assert_eq!(s.is_empty(), false); assert_eq!(s.is_full(), true); assert_eq!(r.len(), 2); assert_eq!(r.is_empty(), false); assert_eq!(r.is_full(), true); let _ = r.recv().await; assert_eq!(s.len(), 1); assert_eq!(s.is_empty(), false); assert_eq!(s.is_full(), false); assert_eq!(r.len(), 1); assert_eq!(r.is_empty(), false); assert_eq!(r.is_full(), false); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn recv() { task::block_on(async { let (s, r) = channel(100); spawn(async move { assert_eq!(r.recv().await.unwrap(), 7); task::sleep(ms(1000)).await; assert_eq!(r.recv().await.unwrap(), 8); task::sleep(ms(1000)).await; assert_eq!(r.recv().await.unwrap(), 9); assert!(r.recv().await.is_err()); }); task::sleep(ms(1500)).await; s.send(7).await.unwrap(); s.send(8).await.unwrap(); s.send(9).await.unwrap(); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn send() { task::block_on(async { let (s, r) = channel(1); spawn(async move { s.send(7).await.unwrap(); task::sleep(ms(1000)).await; s.send(8).await.unwrap(); task::sleep(ms(1000)).await; s.send(9).await.unwrap(); task::sleep(ms(1000)).await; s.send(10).await.unwrap(); }); task::sleep(ms(1500)).await; assert_eq!(r.recv().await.unwrap(), 7); assert_eq!(r.recv().await.unwrap(), 8); assert_eq!(r.recv().await.unwrap(), 9); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn recv_after_disconnect() { task::block_on(async { let (s, r) = channel(100); s.send(1).await.unwrap(); s.send(2).await.unwrap(); s.send(3).await.unwrap(); drop(s); assert_eq!(r.recv().await.unwrap(), 1); assert_eq!(r.recv().await.unwrap(), 2); assert_eq!(r.recv().await.unwrap(), 3); assert!(r.recv().await.is_err()); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn len() { const COUNT: usize = 25_000; const CAP: usize = 1000; task::block_on(async { let (s, r) = channel(CAP); assert_eq!(s.len(), 0); assert_eq!(r.len(), 0); for _ in 0..CAP / 10 { for i in 0..50 { s.send(i).await.unwrap(); assert_eq!(s.len(), i + 1); } for i in 0..50 { let _ = r.recv().await; assert_eq!(r.len(), 50 - i - 1); } } assert_eq!(s.len(), 0); assert_eq!(r.len(), 0); for i in 0..CAP { s.send(i).await.unwrap(); assert_eq!(s.len(), i + 1); } for _ in 0..CAP { r.recv().await.unwrap(); } assert_eq!(s.len(), 0); assert_eq!(r.len(), 0); let child = spawn({ let r = r.clone(); async move { for i in 0..COUNT { assert_eq!(r.recv().await.unwrap(), i); let len = r.len(); assert!(len <= CAP); } } }); for i in 0..COUNT { s.send(i).await.unwrap(); let len = s.len(); assert!(len <= CAP); } child.await; assert_eq!(s.len(), 0); assert_eq!(r.len(), 0); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn disconnect_wakes_receiver() { task::block_on(async { let (s, r) = channel::<()>(1); let child = spawn(async move { assert!(r.recv().await.is_err()); }); task::sleep(ms(1000)).await; drop(s); child.await; }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn spsc() { const COUNT: usize = 100_000; task::block_on(async { let (s, r) = channel(3); let child = spawn(async move { for i in 0..COUNT { assert_eq!(r.recv().await.unwrap(), i); } assert!(r.recv().await.is_err()); }); for i in 0..COUNT { s.send(i).await.unwrap(); } drop(s); child.await; }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn mpmc() { const COUNT: usize = 25_000; const TASKS: usize = 4; task::block_on(async { let (s, r) = channel::(3); let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::>(); let v = Arc::new(v); let mut tasks = Vec::new(); for _ in 0..TASKS { let r = r.clone(); let v = v.clone(); tasks.push(spawn(async move { for _ in 0..COUNT { let n = r.recv().await.unwrap(); v[n].fetch_add(1, Ordering::SeqCst); } })); } for _ in 0..TASKS { let s = s.clone(); tasks.push(spawn(async move { for i in 0..COUNT { s.send(i).await.unwrap(); } })); } for t in tasks { t.await; } for c in v.iter() { assert_eq!(c.load(Ordering::SeqCst), TASKS); } }); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn oneshot() { const COUNT: usize = 10_000; task::block_on(async { for _ in 0..COUNT { let (s, r) = channel(1); let c1 = spawn(async move { r.recv().await.unwrap() }); let c2 = spawn(async move { s.send(0).await.unwrap() }); c1.await; c2.await; } }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn drops() { const RUNS: usize = 100; static DROPS: AtomicUsize = AtomicUsize::new(0); #[derive(Debug, PartialEq)] struct DropCounter; impl Drop for DropCounter { fn drop(&mut self) { DROPS.fetch_add(1, Ordering::SeqCst); } } for _ in 0..RUNS { let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0); task::block_on(async move { let steps = rng.gen_range(0..10_000); let additional = rng.gen_range(0..50); DROPS.store(0, Ordering::SeqCst); let (s, r) = channel::(50); let child = spawn({ let r = r.clone(); async move { for _ in 0..steps { r.recv().await.unwrap(); } } }); for _ in 0..steps { s.send(DropCounter).await.unwrap(); } child.await; for _ in 0..additional { s.send(DropCounter).await.unwrap(); } assert_eq!(DROPS.load(Ordering::SeqCst), steps); drop(s); drop(r); assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional); }) } } async-rs-async-std-57f61ae/tests/collect.rs000066400000000000000000000006431476537407000207510ustar00rootroot00000000000000#[cfg(feature = "unstable")] #[test] fn test_send() { use async_std::prelude::*; use async_std::{stream, task}; task::block_on(async { fn test_send_trait(_: &T) {} let stream = stream::repeat(1u8).take(10); test_send_trait(&stream); let fut = stream.collect::>(); // This line triggers a compilation error test_send_trait(&fut); }); } async-rs-async-std-57f61ae/tests/condvar.rs000066400000000000000000000054401476537407000207600ustar00rootroot00000000000000#![cfg(feature = "unstable")] use std::sync::Arc; use std::time::Duration; use async_std::sync::{Condvar, Mutex}; use async_std::task::{self, JoinHandle}; #[cfg(not(target_os = "unknown"))] use async_std::task::spawn; #[cfg(target_os = "unknown")] use async_std::task::spawn_local as spawn; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn wait_timeout_with_lock() { task::block_on(async { let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair2 = pair.clone(); spawn(async move { let (m, c) = &*pair2; let _g = m.lock().await; task::sleep(Duration::from_millis(200)).await; c.notify_one(); }); let (m, c) = &*pair; let (_, wait_result) = c .wait_timeout(m.lock().await, Duration::from_millis(50)) .await; assert!(wait_result.timed_out()); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn wait_timeout_without_lock() { task::block_on(async { let m = Mutex::new(false); let c = Condvar::new(); let (_, wait_result) = c .wait_timeout(m.lock().await, Duration::from_millis(10)) .await; assert!(wait_result.timed_out()); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn wait_timeout_until_timed_out() { task::block_on(async { let m = Mutex::new(false); let c = Condvar::new(); let (_, wait_result) = c .wait_timeout_until(m.lock().await, Duration::from_millis(100), |&mut started| { started }) .await; assert!(wait_result.timed_out()); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn notify_all() { task::block_on(async { let mut tasks: Vec> = Vec::new(); let pair = Arc::new((Mutex::new(0u32), Condvar::new())); for _ in 0..10 { let pair = pair.clone(); tasks.push(spawn(async move { let (m, c) = &*pair; let mut count = m.lock().await; while *count == 0 { count = c.wait(count).await; } *count += 1; })); } // Give some time for tasks to start up task::sleep(Duration::from_millis(50)).await; let (m, c) = &*pair; { let mut count = m.lock().await; *count += 1; c.notify_all(); } for t in tasks { t.await; } let count = m.lock().await; assert_eq!(11, *count); }) } async-rs-async-std-57f61ae/tests/io_copy.rs000066400000000000000000000035401476537407000207640ustar00rootroot00000000000000use std::{ io::Result, pin::Pin, task::{Context, Poll}, }; struct ReaderThatPanicsAfterEof { read_count: usize, has_sent_eof: bool, max_read: usize, } impl async_std::io::Read for ReaderThatPanicsAfterEof { fn poll_read( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { if self.has_sent_eof { panic!("this should be unreachable because we should not poll after eof (Ready(Ok(0)))") } else if self.read_count >= self.max_read { self.has_sent_eof = true; Poll::Ready(Ok(0)) } else { self.read_count += 1; Poll::Ready(Ok(buf.len())) } } } struct WriterThatTakesAWhileToFlush { max_flush: usize, flush_count: usize, } impl async_std::io::Write for WriterThatTakesAWhileToFlush { fn poll_write(self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &[u8]) -> Poll> { Poll::Ready(Ok(buf.len())) } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.flush_count += 1; if self.flush_count >= self.max_flush { Poll::Ready(Ok(())) } else { cx.waker().wake_by_ref(); Poll::Pending } } fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } } #[test] fn io_copy_does_not_poll_after_eof() { async_std::task::block_on(async { let mut reader = ReaderThatPanicsAfterEof { has_sent_eof: false, max_read: 10, read_count: 0, }; let mut writer = WriterThatTakesAWhileToFlush { flush_count: 0, max_flush: 10, }; assert!(async_std::io::copy(&mut reader, &mut writer).await.is_ok()); }) } async-rs-async-std-57f61ae/tests/io_timeout.rs000066400000000000000000000023451476537407000215020ustar00rootroot00000000000000use std::time::Duration; use async_std::io; use async_std::task; #[test] #[should_panic(expected = "timed out")] #[cfg(not(any( target_os = "unknown", target_arch = "arm", target_arch = "mips", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "x86", )))] // stdin tests fail when running through cross fn io_timeout_timedout() { task::block_on(async { io::timeout(Duration::from_secs(1), async { let stdin = io::stdin(); let mut line = String::new(); let _n = stdin.read_line(&mut line).await?; Ok(()) }) .await .unwrap(); // We should panic with a timeout error }); } #[test] #[should_panic(expected = "My custom error")] fn io_timeout_future_err() { task::block_on(async { io::timeout(Duration::from_secs(1), async { Err::<(), io::Error>(io::Error::new(io::ErrorKind::Other, "My custom error")) }) .await .unwrap(); // We should panic with our own error }); } #[test] fn io_timeout_future_ok() { task::block_on(async { io::timeout(Duration::from_secs(1), async { Ok(()) }) .await .unwrap(); // We shouldn't panic at all }); } async-rs-async-std-57f61ae/tests/mutex.rs000066400000000000000000000037541476537407000204740ustar00rootroot00000000000000use std::sync::Arc; use async_std::prelude::*; use async_std::sync::Mutex; use async_std::task; use futures::channel::mpsc; #[cfg(not(target_os = "unknown"))] use async_std::task::spawn; #[cfg(target_os = "unknown")] use async_std::task::spawn_local as spawn; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn smoke() { task::block_on(async { let m = Mutex::new(()); drop(m.lock().await); drop(m.lock().await); }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn try_lock() { let m = Mutex::new(()); *m.try_lock().unwrap() = (); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn into_inner() { let m = Mutex::new(10); assert_eq!(m.into_inner(), 10); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn get_mut() { let mut m = Mutex::new(10); *m.get_mut() = 20; assert_eq!(m.into_inner(), 20); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn contention() { task::block_on(async { let (tx, mut rx) = mpsc::unbounded(); let tx = Arc::new(tx); let mutex = Arc::new(Mutex::new(0)); let num_tasks = 10000; let mut handles = Vec::new(); for _ in 0..num_tasks { let tx = tx.clone(); let mutex = mutex.clone(); handles.push(spawn(async move { let mut lock = mutex.lock().await; *lock += 1; tx.unbounded_send(()).unwrap(); drop(lock); })); } for _ in 0..num_tasks { rx.next().await.unwrap(); } for handle in handles.into_iter() { handle.await; } dbg!("wait"); let lock = mutex.lock().await; assert_eq!(num_tasks, *lock); }); } async-rs-async-std-57f61ae/tests/rwlock.rs000066400000000000000000000120121476537407000206160ustar00rootroot00000000000000use std::cell::Cell; use std::num::Wrapping; use std::pin::Pin; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::task::{Context, Poll}; use async_std::prelude::*; use async_std::sync::RwLock; use async_std::task; use futures::channel::mpsc; #[cfg(not(target_os = "unknown"))] use async_std::task::spawn; #[cfg(target_os = "unknown")] use async_std::task::spawn_local as spawn; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); /// Generates a random number in `0..n`. pub fn random(n: u32) -> u32 { thread_local! { static RNG: Cell> = Cell::new(Wrapping(1_406_868_647)); } RNG.with(|rng| { // This is the 32-bit variant of Xorshift. // // Source: https://en.wikipedia.org/wiki/Xorshift let mut x = rng.get(); x ^= x << 13; x ^= x >> 17; x ^= x << 5; rng.set(x); // This is a fast alternative to `x % n`. // // Author: Daniel Lemire // Source: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ ((x.0 as u64).wrapping_mul(n as u64) >> 32) as u32 }) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn smoke() { task::block_on(async { let lock = RwLock::new(()); drop(lock.read().await); drop(lock.write().await); drop((lock.read().await, lock.read().await)); drop(lock.write().await); }); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn try_write() { task::block_on(async { let lock = RwLock::new(0isize); let read_guard = lock.read().await; assert!(lock.try_write().is_none()); drop(read_guard); }); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn into_inner() { let lock = RwLock::new(10); assert_eq!(lock.into_inner(), 10); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn into_inner_and_drop() { struct Counter(Arc); impl Drop for Counter { fn drop(&mut self) { self.0.fetch_add(1, Ordering::SeqCst); } } let cnt = Arc::new(AtomicUsize::new(0)); let lock = RwLock::new(Counter(cnt.clone())); assert_eq!(cnt.load(Ordering::SeqCst), 0); { let _inner = lock.into_inner(); assert_eq!(cnt.load(Ordering::SeqCst), 0); } assert_eq!(cnt.load(Ordering::SeqCst), 1); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn get_mut() { let mut lock = RwLock::new(10); *lock.get_mut() = 20; assert_eq!(lock.into_inner(), 20); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn contention() { const N: u32 = 10; const M: usize = 1000; let (tx, mut rx) = mpsc::unbounded(); let tx = Arc::new(tx); let rw = Arc::new(RwLock::new(())); // Spawn N tasks that randomly acquire the lock M times. for _ in 0..N { let tx = tx.clone(); let rw = rw.clone(); spawn(async move { for _ in 0..M { if random(N) == 0 { drop(rw.write().await); } else { drop(rw.read().await); } } tx.unbounded_send(()).unwrap(); }); } task::block_on(async move { for _ in 0..N { rx.next().await.unwrap(); } }); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn writer_and_readers() { #[derive(Default)] struct Yield(Cell); impl Future for Yield { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if self.0.get() { Poll::Ready(()) } else { self.0.set(true); cx.waker().wake_by_ref(); Poll::Pending } } } let lock = Arc::new(RwLock::new(0i32)); let (tx, mut rx) = mpsc::unbounded(); // Spawn a writer task. spawn({ let lock = lock.clone(); async move { let mut lock = lock.write().await; for _ in 0..10 { let tmp = *lock; *lock = -1; Yield::default().await; *lock = tmp + 1; } tx.unbounded_send(()).unwrap(); } }); // Readers try to catch the writer in the act. let mut readers = Vec::new(); for _ in 0..5 { let lock = lock.clone(); readers.push(spawn(async move { let lock = lock.read().await; assert!(*lock >= 0); })); } task::block_on(async move { // Wait for readers to pass their asserts. for r in readers { r.await; } // Wait for writer to finish. rx.next().await.unwrap(); let lock = lock.read().await; assert_eq!(*lock, 10); }); } async-rs-async-std-57f61ae/tests/stream.rs000066400000000000000000000105331476537407000206160ustar00rootroot00000000000000use std::convert::identity; use std::marker::Unpin; use std::pin::Pin; use std::task::{Context, Poll}; use pin_project_lite::pin_project; use async_std::channel::bounded as channel; use async_std::prelude::*; use async_std::stream; use async_std::task; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); #[cfg(not(target_os = "unknown"))] use async_std::task::spawn; #[cfg(target_os = "unknown")] use async_std::task::spawn_local as spawn; #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] /// Checks that streams are merged fully even if one of the components /// experiences delay. fn merging_delayed_streams_work() { let (sender, receiver) = channel::(10); let mut s = receiver.merge(stream::empty()); let t = spawn(async move { let mut xs = Vec::new(); while let Some(x) = s.next().await { xs.push(x); } xs }); task::block_on(async move { task::sleep(std::time::Duration::from_millis(500)).await; sender.send(92).await.unwrap(); drop(sender); let xs = t.await; assert_eq!(xs, vec![92]) }); let (sender, receiver) = channel::(10); let mut s = stream::empty().merge(receiver); let t = spawn(async move { let mut xs = Vec::new(); while let Some(x) = s.next().await { xs.push(x); } xs }); task::block_on(async move { task::sleep(std::time::Duration::from_millis(500)).await; sender.send(92).await.unwrap(); drop(sender); let xs = t.await; assert_eq!(xs, vec![92]) }); } pin_project! { /// The opposite of `Fuse`: makes the stream panic if polled after termination. struct Explode { #[pin] done: bool, #[pin] inner: S, } } impl Stream for Explode { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); if *this.done { panic!("KABOOM!") } let res = this.inner.poll_next(cx); if let Poll::Ready(None) = &res { *this.done = true; } res } } fn explode(s: S) -> Explode { Explode { done: false, inner: s, } } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn merge_works_with_unfused_streams() { let s1 = explode(stream::once(92)); let s2 = explode(stream::once(92)); let mut s = s1.merge(s2); task::block_on(async move { let mut xs = Vec::new(); while let Some(x) = s.next().await { xs.push(x) } assert_eq!(xs, vec![92, 92]); }); } struct S(T); impl Stream for S { type Item = T::Item; fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll> { unsafe { Pin::new_unchecked(&mut self.0) }.poll_next(ctx) } } struct StrictOnce { polled: bool, } impl Stream for StrictOnce { type Item = (); fn poll_next(mut self: Pin<&mut Self>, _: &mut Context) -> Poll> { assert!(!self.polled, "Polled after completion!"); self.polled = true; Poll::Ready(None) } } struct Interchanger { polled: bool, } impl Stream for Interchanger { type Item = S + Unpin>>; fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll> { if self.polled { self.polled = false; ctx.waker().wake_by_ref(); Poll::Pending } else { self.polled = true; Poll::Ready(Some(S(Box::new(StrictOnce { polled: false })))) } } } #[test] fn flat_map_doesnt_poll_completed_inner_stream() { task::block_on(async { assert_eq!( Interchanger { polled: false } .take(2) .flat_map(identity) .count() .await, 0 ); }); } #[test] fn flatten_doesnt_poll_completed_inner_stream() { task::block_on(async { assert_eq!( Interchanger { polled: false } .take(2) .flatten() .count() .await, 0 ); }); } async-rs-async-std-57f61ae/tests/task_local.rs000066400000000000000000000020601476537407000214330ustar00rootroot00000000000000use std::sync::atomic::{AtomicBool, Ordering}; use async_std::task; use async_std::task_local; #[cfg(not(target_os = "unknown"))] use async_std::task::spawn; #[cfg(target_os = "unknown")] use async_std::task::spawn_local as spawn; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn drop_local() { static DROP_LOCAL: AtomicBool = AtomicBool::new(false); struct Local; impl Drop for Local { fn drop(&mut self) { DROP_LOCAL.store(true, Ordering::SeqCst); } } task_local! { static LOCAL: Local = Local; } // Spawn a task that just touches its task-local. let handle = spawn(async { LOCAL.with(|_| ()); }); let task = handle.task().clone(); // Wait for the task to finish and make sure its task-local has been dropped. task::block_on(async { handle.await; assert!(DROP_LOCAL.load(Ordering::SeqCst)); drop(task); }); } async-rs-async-std-57f61ae/tests/tcp.rs000066400000000000000000000064521476537407000201160ustar00rootroot00000000000000#![cfg(not(target_os = "unknown"))] use async_std::io; use async_std::net::{TcpListener, TcpStream}; use async_std::prelude::*; use async_std::task; const THE_WINTERS_TALE: &[u8] = b" Each your doing, So singular in each particular, Crowns what you are doing in the present deed, That all your acts are queens. "; #[test] fn connect() -> io::Result<()> { task::block_on(async { let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; let t = task::spawn(async move { listener.accept().await }); let stream2 = TcpStream::connect(&addr).await?; let stream1 = t.await?.0; assert_eq!(stream1.peer_addr()?, stream2.local_addr()?); assert_eq!(stream2.peer_addr()?, stream1.local_addr()?); Ok(()) }) } #[test] fn incoming_read() -> io::Result<()> { task::block_on(async { let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; task::spawn(async move { let mut stream = TcpStream::connect(&addr).await?; stream.write_all(THE_WINTERS_TALE).await?; io::Result::Ok(()) }); let mut buf = vec![0; 1024]; let mut incoming = listener.incoming(); let mut stream = incoming.next().await.unwrap()?; let n = stream.read(&mut buf).await?; assert_eq!(&buf[..n], THE_WINTERS_TALE); Ok(()) }) } #[test] fn smoke_std_stream_to_async_listener() -> io::Result<()> { use std::io::Write; task::block_on(async { let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; let mut std_stream = std::net::TcpStream::connect(&addr)?; std_stream.write_all(THE_WINTERS_TALE)?; let mut buf = vec![0; 1024]; let mut incoming = listener.incoming(); let mut stream = incoming.next().await.unwrap()?; let n = stream.read(&mut buf).await?; assert_eq!(&buf[..n], THE_WINTERS_TALE); Ok(()) }) } #[test] fn smoke_async_stream_to_std_listener() -> io::Result<()> { use std::io::Read; let std_listener = std::net::TcpListener::bind("127.0.0.1:0")?; let addr = std_listener.local_addr()?; task::block_on(async move { let mut stream = TcpStream::connect(&addr).await?; stream.write_all(THE_WINTERS_TALE).await?; io::Result::Ok(()) })?; let mut buf = vec![0; 1024]; let mut incoming = std_listener.incoming(); let mut stream = incoming.next().unwrap()?; let n = stream.read(&mut buf).unwrap(); assert_eq!(&buf[..n], THE_WINTERS_TALE); Ok(()) } #[test] fn cloned_streams() -> io::Result<()> { task::block_on(async { let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; let mut stream = TcpStream::connect(&addr).await?; let mut cloned_stream = stream.clone(); let mut incoming = listener.incoming(); let mut write_stream = incoming.next().await.unwrap()?; write_stream.write_all(b"Each your doing").await?; let mut buf = [0; 15]; stream.read_exact(&mut buf[..8]).await?; cloned_stream.read_exact(&mut buf[8..]).await?; assert_eq!(&buf[..15], b"Each your doing"); Ok(()) }) } async-rs-async-std-57f61ae/tests/timeout.rs000066400000000000000000000013321476537407000210060ustar00rootroot00000000000000use std::time::Duration; use async_std::future::timeout; use async_std::task; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn timeout_future_many() { task::block_on(async { let futures = (0..10) .map(|i| { timeout(Duration::from_millis(i * 50), async move { task::sleep(Duration::from_millis(i)).await; Ok::<(), async_std::future::TimeoutError>(()) }) }) .collect::>(); for future in futures { future.await.unwrap().unwrap(); } }); } async-rs-async-std-57f61ae/tests/udp.rs000066400000000000000000000017571476537407000201230ustar00rootroot00000000000000#![cfg(not(target_os = "unknown"))] use async_std::io; use async_std::net::UdpSocket; use async_std::task; const THE_MERCHANT_OF_VENICE: &[u8] = b" If you prick us, do we not bleed? If you tickle us, do we not laugh? If you poison us, do we not die? And if you wrong us, shall we not revenge? "; #[test] fn send_recv_peek() -> io::Result<()> { task::block_on(async { let socket1 = UdpSocket::bind("127.0.0.1:0").await?; let socket2 = UdpSocket::bind("127.0.0.1:0").await?; socket1.connect(socket2.local_addr()?).await?; socket2.connect(socket1.local_addr()?).await?; assert_eq!(socket1.peer_addr()?, socket2.local_addr()?); socket1.send(THE_MERCHANT_OF_VENICE).await?; let mut buf = [0u8; 1024]; let n = socket2.peek(&mut buf).await?; assert_eq!(&buf[..n], THE_MERCHANT_OF_VENICE); let n = socket2.recv(&mut buf).await?; assert_eq!(&buf[..n], THE_MERCHANT_OF_VENICE); Ok(()) }) } async-rs-async-std-57f61ae/tests/uds.rs000066400000000000000000000101651476537407000201170ustar00rootroot00000000000000#![cfg(all(unix, not(target_os = "unknown")))] use async_std::io; use async_std::os::unix::net::{UnixDatagram, UnixListener, UnixStream}; use async_std::prelude::*; use async_std::task; use std::time::Duration; const JULIUS_CAESAR: &[u8] = b" Friends, Romans, countrymen - lend me your ears! I come not to praise Caesar, but to bury him. "; #[test] fn send_recv() -> io::Result<()> { task::block_on(async { let (socket1, socket2) = UnixDatagram::pair().unwrap(); socket1.send(JULIUS_CAESAR).await?; let mut buf = vec![0; 1024]; let n = socket2.recv(&mut buf).await?; assert_eq!(&buf[..n], JULIUS_CAESAR); Ok(()) }) } #[test] fn into_raw_fd_datagram() -> io::Result<()> { use async_std::os::unix::io::{FromRawFd, IntoRawFd}; task::block_on(async { let (socket1, socket2) = UnixDatagram::pair().unwrap(); socket1.send(JULIUS_CAESAR).await?; let mut buf = vec![0; 1024]; let socket2 = unsafe { UnixDatagram::from_raw_fd(socket2.into_raw_fd()) }; let n = socket2.recv(&mut buf).await?; assert_eq!(&buf[..n], JULIUS_CAESAR); Ok(()) }) } #[test] fn into_raw_fd_stream() -> io::Result<()> { use async_std::os::unix::io::{FromRawFd, IntoRawFd}; task::block_on(async { let (mut socket1, socket2) = UnixStream::pair().unwrap(); socket1.write(JULIUS_CAESAR).await?; let mut buf = vec![0; 1024]; let mut socket2 = unsafe { UnixStream::from_raw_fd(socket2.into_raw_fd()) }; let n = socket2.read(&mut buf).await?; assert_eq!(&buf[..n], JULIUS_CAESAR); Ok(()) }) } const PING: &[u8] = b"ping"; const PONG: &[u8] = b"pong"; const TEST_TIMEOUT: Duration = Duration::from_secs(3); #[test] fn socket_ping_pong() { let tmp_dir = tempfile::Builder::new() .prefix("socket_ping_pong") .tempdir() .expect("Temp dir not created"); let sock_path = tmp_dir.as_ref().join("sock"); let iter_cnt = 16; let listener = task::block_on(async { UnixListener::bind(&sock_path).await.expect("Socket bind") }); let server_handle = std::thread::spawn(move || { task::block_on(async { ping_pong_server(listener, iter_cnt).await }).unwrap() }); let client_handle = std::thread::spawn(move || { task::block_on(async { ping_pong_client(&sock_path, iter_cnt).await }).unwrap() }); client_handle.join().unwrap(); server_handle.join().unwrap(); } async fn ping_pong_server(listener: UnixListener, iterations: u32) -> std::io::Result<()> { let mut incoming = listener.incoming(); let mut buf = [0; 1024]; for _ix in 0..iterations { if let Some(s) = incoming.next().await { let mut s = s?; let n = s.read(&mut buf[..]).await?; assert_eq!(&buf[..n], PING); s.write_all(&PONG).await?; } } Ok(()) } async fn ping_pong_client(socket: &std::path::PathBuf, iterations: u32) -> std::io::Result<()> { let mut buf = [0; 1024]; for _ix in 0..iterations { let mut socket = UnixStream::connect(&socket).await?; socket.write_all(&PING).await?; let n = async_std::io::timeout(TEST_TIMEOUT, socket.read(&mut buf[..])).await?; assert_eq!(&buf[..n], PONG); } Ok(()) } #[test] fn uds_clone() -> io::Result<()> { task::block_on(async { let tmp_dir = tempfile::Builder::new() .prefix("socket_ping_pong") .tempdir() .expect("Temp dir not created"); let sock_path = tmp_dir.as_ref().join("sock"); let input = UnixListener::bind(&sock_path).await?; let mut writer = UnixStream::connect(&sock_path).await?; let mut reader = input.incoming().next().await.unwrap()?; writer.write(b"original").await.unwrap(); let mut original_buf = [0; 8]; reader.read(&mut original_buf).await?; assert_eq!(&original_buf, b"original"); writer.clone().write(b"clone").await.unwrap(); let mut clone_buf = [0; 5]; reader.clone().read(&mut clone_buf).await?; assert_eq!(&clone_buf, b"clone"); Ok(()) }) } async-rs-async-std-57f61ae/tests/verbose_errors.rs000066400000000000000000000022301476537407000223570ustar00rootroot00000000000000#![cfg(not(target_os = "unknown"))] use async_std::{fs, io, net::ToSocketAddrs, task}; #[test] fn open_file() { task::block_on(async { let non_existing_file = "/ashjudlkahasdasdsikdhajik/asdasdasdasdasdasd/fjuiklashdbflasas"; let res = fs::File::open(non_existing_file).await; match res { Ok(_) => panic!("Found file with random name: We live in a simulation"), Err(e) => assert_eq!( "could not open `/ashjudlkahasdasdsikdhajik/asdasdasdasdasdasd/fjuiklashdbflasas`", &format!("{}", e) ), } }) } #[test] fn resolve_address() { task::block_on(async { let non_existing_addr = "ashjudlkahasdasdsikdhajik.asdasdasdasdasdasd.fjuiklashdbflasas:80"; let res: Result<_, io::Error> = non_existing_addr.to_socket_addrs().await; match res { Ok(_) => panic!("Found address with random name: We live in a simulation"), Err(e) => assert_eq!( "could not resolve address `\"ashjudlkahasdasdsikdhajik.asdasdasdasdasdasd.fjuiklashdbflasas:80\"`", &format!("{}", e) ), } }) }