docs: annotate io mod with doc_cfg (#1808)

Annotates types in `tokio::io` module with their required feature flag.
This annotation is included in generated documentation.

Notes:

* The annotation must be on the type or function itself. Annotating just
  the re-export is not sufficient.

* The annotation must be **inside** the `pin_project!` macro or it is
  lost.
This commit is contained in:
Carl Lerche
2019-11-22 09:56:08 -08:00
committed by GitHub
parent 8546ff826d
commit 9b2aa14bb1
34 changed files with 768 additions and 679 deletions
+1
View File
@@ -126,3 +126,4 @@ tempfile = "3.1.0"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
+95 -92
View File
@@ -10,98 +10,101 @@ use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::Relaxed;
use std::task::{Context, Poll};
/// Associates an I/O resource that implements the [`std::io::Read`] and/or
/// [`std::io::Write`] traits with the reactor that drives it.
///
/// `PollEvented` uses [`Registration`] internally to take a type that
/// implements [`mio::Evented`] as well as [`std::io::Read`] and or
/// [`std::io::Write`] and associate it with a reactor that will drive it.
///
/// Once the [`mio::Evented`] type is wrapped by `PollEvented`, it can be
/// used from within the future's execution model. As such, the `PollEvented`
/// type provides [`AsyncRead`] and [`AsyncWrite`] implementations using the
/// underlying I/O resource as well as readiness events provided by the reactor.
///
/// **Note**: While `PollEvented` is `Sync` (if the underlying I/O type is
/// `Sync`), the caller must ensure that there are at most two tasks that use a
/// `PollEvented` instance concurrently. One for reading and one for writing.
/// While violating this requirement is "safe" from a Rust memory model point of
/// view, it will result in unexpected behavior in the form of lost
/// notifications and tasks hanging.
///
/// ## Readiness events
///
/// Besides just providing [`AsyncRead`] and [`AsyncWrite`] implementations,
/// this type also supports access to the underlying readiness event stream.
/// While similar in function to what [`Registration`] provides, the semantics
/// are a bit different.
///
/// Two functions are provided to access the readiness events:
/// [`poll_read_ready`] and [`poll_write_ready`]. These functions return the
/// current readiness state of the `PollEvented` instance. If
/// [`poll_read_ready`] indicates read readiness, immediately calling
/// [`poll_read_ready`] again will also indicate read readiness.
///
/// When the operation is attempted and is unable to succeed due to the I/O
/// resource not being ready, the caller must call [`clear_read_ready`] or
/// [`clear_write_ready`]. This clears the readiness state until a new readiness
/// event is received.
///
/// This allows the caller to implement additional functions. For example,
/// [`TcpListener`] implements poll_accept by using [`poll_read_ready`] and
/// [`clear_read_ready`].
///
/// ```rust
/// use tokio::io::PollEvented;
///
/// use futures::ready;
/// use mio::Ready;
/// use mio::net::{TcpStream, TcpListener};
/// use std::io;
/// use std::task::{Context, Poll};
///
/// struct MyListener {
/// poll_evented: PollEvented<TcpListener>,
/// }
///
/// impl MyListener {
/// pub fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll<Result<TcpStream, io::Error>> {
/// let ready = Ready::readable();
///
/// ready!(self.poll_evented.poll_read_ready(cx, ready))?;
///
/// match self.poll_evented.get_ref().accept() {
/// Ok((socket, _)) => Poll::Ready(Ok(socket)),
/// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
/// self.poll_evented.clear_read_ready(cx, ready)?;
/// Poll::Pending
/// }
/// Err(e) => Poll::Ready(Err(e)),
/// }
/// }
/// }
/// ```
///
/// ## Platform-specific events
///
/// `PollEvented` also allows receiving platform-specific `mio::Ready` events.
/// These events are included as part of the read readiness event stream. The
/// write readiness event stream is only for `Ready::writable()` events.
///
/// [`std::io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
/// [`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
/// [`AsyncRead`]: ../io/trait.AsyncRead.html
/// [`AsyncWrite`]: ../io/trait.AsyncWrite.html
/// [`mio::Evented`]: https://docs.rs/mio/0.6/mio/trait.Evented.html
/// [`Registration`]: struct.Registration.html
/// [`TcpListener`]: ../net/struct.TcpListener.html
/// [`clear_read_ready`]: #method.clear_read_ready
/// [`clear_write_ready`]: #method.clear_write_ready
/// [`poll_read_ready`]: #method.poll_read_ready
/// [`poll_write_ready`]: #method.poll_write_ready
pub struct PollEvented<E: Evented> {
io: Option<E>,
inner: Inner,
cfg_io_driver! {
/// Associates an I/O resource that implements the [`std::io::Read`] and/or
/// [`std::io::Write`] traits with the reactor that drives it.
///
/// `PollEvented` uses [`Registration`] internally to take a type that
/// implements [`mio::Evented`] as well as [`std::io::Read`] and or
/// [`std::io::Write`] and associate it with a reactor that will drive it.
///
/// Once the [`mio::Evented`] type is wrapped by `PollEvented`, it can be
/// used from within the future's execution model. As such, the
/// `PollEvented` type provides [`AsyncRead`] and [`AsyncWrite`]
/// implementations using the underlying I/O resource as well as readiness
/// events provided by the reactor.
///
/// **Note**: While `PollEvented` is `Sync` (if the underlying I/O type is
/// `Sync`), the caller must ensure that there are at most two tasks that
/// use a `PollEvented` instance concurrently. One for reading and one for
/// writing. While violating this requirement is "safe" from a Rust memory
/// model point of view, it will result in unexpected behavior in the form
/// of lost notifications and tasks hanging.
///
/// ## Readiness events
///
/// Besides just providing [`AsyncRead`] and [`AsyncWrite`] implementations,
/// this type also supports access to the underlying readiness event stream.
/// While similar in function to what [`Registration`] provides, the
/// semantics are a bit different.
///
/// Two functions are provided to access the readiness events:
/// [`poll_read_ready`] and [`poll_write_ready`]. These functions return the
/// current readiness state of the `PollEvented` instance. If
/// [`poll_read_ready`] indicates read readiness, immediately calling
/// [`poll_read_ready`] again will also indicate read readiness.
///
/// When the operation is attempted and is unable to succeed due to the I/O
/// resource not being ready, the caller must call [`clear_read_ready`] or
/// [`clear_write_ready`]. This clears the readiness state until a new
/// readiness event is received.
///
/// This allows the caller to implement additional functions. For example,
/// [`TcpListener`] implements poll_accept by using [`poll_read_ready`] and
/// [`clear_read_ready`].
///
/// ```rust
/// use tokio::io::PollEvented;
///
/// use futures::ready;
/// use mio::Ready;
/// use mio::net::{TcpStream, TcpListener};
/// use std::io;
/// use std::task::{Context, Poll};
///
/// struct MyListener {
/// poll_evented: PollEvented<TcpListener>,
/// }
///
/// impl MyListener {
/// pub fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll<Result<TcpStream, io::Error>> {
/// let ready = Ready::readable();
///
/// ready!(self.poll_evented.poll_read_ready(cx, ready))?;
///
/// match self.poll_evented.get_ref().accept() {
/// Ok((socket, _)) => Poll::Ready(Ok(socket)),
/// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
/// self.poll_evented.clear_read_ready(cx, ready)?;
/// Poll::Pending
/// }
/// Err(e) => Poll::Ready(Err(e)),
/// }
/// }
/// }
/// ```
///
/// ## Platform-specific events
///
/// `PollEvented` also allows receiving platform-specific `mio::Ready` events.
/// These events are included as part of the read readiness event stream. The
/// write readiness event stream is only for `Ready::writable()` events.
///
/// [`std::io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
/// [`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
/// [`AsyncRead`]: ../io/trait.AsyncRead.html
/// [`AsyncWrite`]: ../io/trait.AsyncWrite.html
/// [`mio::Evented`]: https://docs.rs/mio/0.6/mio/trait.Evented.html
/// [`Registration`]: struct.Registration.html
/// [`TcpListener`]: ../net/struct.TcpListener.html
/// [`clear_read_ready`]: #method.clear_read_ready
/// [`clear_write_ready`]: #method.clear_write_ready
/// [`poll_read_ready`]: #method.poll_read_ready
/// [`poll_write_ready`]: #method.poll_write_ready
pub struct PollEvented<E: Evented> {
io: Option<E>,
inner: Inner,
}
}
struct Inner {
+37 -34
View File
@@ -5,40 +5,43 @@ use mio::{self, Evented};
use std::task::{Context, Poll};
use std::io;
/// Associates an I/O resource with the reactor instance that drives it.
///
/// A registration represents an I/O resource registered with a Reactor such
/// that it will receive task notifications on readiness. This is the lowest
/// level API for integrating with a reactor.
///
/// The association between an I/O resource is made by calling [`new`]. Once
/// the association is established, it remains established until the
/// registration instance is dropped.
///
/// A registration instance represents two separate readiness streams. One for
/// the read readiness and one for write readiness. These streams are
/// independent and can be consumed from separate tasks.
///
/// **Note**: while `Registration` is `Sync`, the caller must ensure that there
/// are at most two tasks that use a registration instance concurrently. One
/// task for [`poll_read_ready`] and one task for [`poll_write_ready`]. While
/// violating this requirement is "safe" from a Rust memory safety point of
/// view, it will result in unexpected behavior in the form of lost
/// notifications and tasks hanging.
///
/// ## Platform-specific events
///
/// `Registration` also allows receiving platform-specific `mio::Ready` events.
/// These events are included as part of the read readiness event stream. The
/// write readiness event stream is only for `Ready::writable()` events.
///
/// [`new`]: #method.new
/// [`poll_read_ready`]: #method.poll_read_ready`]
/// [`poll_write_ready`]: #method.poll_write_ready`]
#[derive(Debug)]
pub struct Registration {
handle: Handle,
address: Address,
cfg_io_driver! {
/// Associates an I/O resource with the reactor instance that drives it.
///
/// A registration represents an I/O resource registered with a Reactor such
/// that it will receive task notifications on readiness. This is the lowest
/// level API for integrating with a reactor.
///
/// The association between an I/O resource is made by calling [`new`]. Once
/// the association is established, it remains established until the
/// registration instance is dropped.
///
/// A registration instance represents two separate readiness streams. One
/// for the read readiness and one for write readiness. These streams are
/// independent and can be consumed from separate tasks.
///
/// **Note**: while `Registration` is `Sync`, the caller must ensure that
/// there are at most two tasks that use a registration instance
/// concurrently. One task for [`poll_read_ready`] and one task for
/// [`poll_write_ready`]. While violating this requirement is "safe" from a
/// Rust memory safety point of view, it will result in unexpected behavior
/// in the form of lost notifications and tasks hanging.
///
/// ## Platform-specific events
///
/// `Registration` also allows receiving platform-specific `mio::Ready`
/// events. These events are included as part of the read readiness event
/// stream. The write readiness event stream is only for `Ready::writable()`
/// events.
///
/// [`new`]: #method.new
/// [`poll_read_ready`]: #method.poll_read_ready`]
/// [`poll_write_ready`]: #method.poll_write_ready`]
#[derive(Debug)]
pub struct Registration {
handle: Handle,
address: Address,
}
}
// ===== impl Registration =====
+32 -30
View File
@@ -16,14 +16,39 @@ use std::sync::atomic::Ordering::{Acquire, Release};
use std::sync::Arc;
use std::task::{Context, Poll};
/// The readable half of a value returned from `split`.
pub struct ReadHalf<T> {
inner: Arc<Inner<T>>,
}
cfg_io_util! {
/// The readable half of a value returned from `split`.
pub struct ReadHalf<T> {
inner: Arc<Inner<T>>,
}
/// The writable half of a value returned from `split`.
pub struct WriteHalf<T> {
inner: Arc<Inner<T>>,
/// The writable half of a value returned from `split`.
pub struct WriteHalf<T> {
inner: Arc<Inner<T>>,
}
/// Split a single value implementing `AsyncRead + AsyncWrite` into separate
/// `AsyncRead` and `AsyncWrite` handles.
///
/// To restore this read/write object from its `split::ReadHalf` and
/// `split::WriteHalf` use `unsplit`.
pub fn split<T>(stream: T) -> (ReadHalf<T>, WriteHalf<T>)
where
T: AsyncRead + AsyncWrite,
{
let inner = Arc::new(Inner {
locked: AtomicBool::new(false),
stream: UnsafeCell::new(stream),
});
let rd = ReadHalf {
inner: inner.clone(),
};
let wr = WriteHalf { inner };
(rd, wr)
}
}
struct Inner<T> {
@@ -35,29 +60,6 @@ struct Guard<'a, T> {
inner: &'a Inner<T>,
}
/// Split a single value implementing `AsyncRead + AsyncWrite` into separate
/// `AsyncRead` and `AsyncWrite` handles.
///
/// To restore this read/write object from its `split::ReadHalf` and
/// `split::WriteHalf` use `unsplit`.
pub fn split<T>(stream: T) -> (ReadHalf<T>, WriteHalf<T>)
where
T: AsyncRead + AsyncWrite,
{
let inner = Arc::new(Inner {
locked: AtomicBool::new(false),
stream: UnsafeCell::new(stream),
});
let rd = ReadHalf {
inner: inner.clone(),
};
let wr = WriteHalf { inner };
(rd, wr)
}
impl<T> ReadHalf<T> {
/// Reunite with a previously split `WriteHalf`.
///
+23 -21
View File
@@ -6,28 +6,30 @@ use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
/// A handle to the standard error stream of a process.
///
/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent
/// writes to `Stderr` must be executed with care.
///
/// Created by the [`stderr`] function.
///
/// [`stderr`]: fn.stderr.html
/// [`AsyncWrite`]: trait.AsyncWrite.html
#[derive(Debug)]
pub struct Stderr {
std: Blocking<std::io::Stderr>,
}
cfg_io_std! {
/// A handle to the standard error stream of a process.
///
/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent
/// writes to `Stderr` must be executed with care.
///
/// Created by the [`stderr`] function.
///
/// [`stderr`]: fn.stderr.html
/// [`AsyncWrite`]: trait.AsyncWrite.html
#[derive(Debug)]
pub struct Stderr {
std: Blocking<std::io::Stderr>,
}
/// Constructs a new handle to the standard error of the current process.
///
/// The returned handle allows writing to standard error from the within the
/// Tokio runtime.
pub fn stderr() -> Stderr {
let std = io::stderr();
Stderr {
std: Blocking::new(std),
/// Constructs a new handle to the standard error of the current process.
///
/// The returned handle allows writing to standard error from the within the
/// Tokio runtime.
pub fn stderr() -> Stderr {
let std = io::stderr();
Stderr {
std: Blocking::new(std),
}
}
}
+29 -27
View File
@@ -6,34 +6,36 @@ use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
/// A handle to the standard input stream of a process.
///
/// The handle implements the [`AsyncRead`] trait, but beware that concurrent
/// reads of `Stdin` must be executed with care.
///
/// As an additional caveat, reading from the handle may block the calling
/// future indefinitely, if there is not enough data available. This makes this
/// handle unsuitable for use in any circumstance where immediate reaction to
/// available data is required, e.g. interactive use or when implementing a
/// subprocess driven by requests on the standard input.
///
/// Created by the [`stdin`] function.
///
/// [`stdin`]: fn.stdin.html
/// [`AsyncRead`]: trait.AsyncRead.html
#[derive(Debug)]
pub struct Stdin {
std: Blocking<std::io::Stdin>,
}
cfg_io_std! {
/// A handle to the standard input stream of a process.
///
/// The handle implements the [`AsyncRead`] trait, but beware that concurrent
/// reads of `Stdin` must be executed with care.
///
/// As an additional caveat, reading from the handle may block the calling
/// future indefinitely, if there is not enough data available. This makes this
/// handle unsuitable for use in any circumstance where immediate reaction to
/// available data is required, e.g. interactive use or when implementing a
/// subprocess driven by requests on the standard input.
///
/// Created by the [`stdin`] function.
///
/// [`stdin`]: fn.stdin.html
/// [`AsyncRead`]: trait.AsyncRead.html
#[derive(Debug)]
pub struct Stdin {
std: Blocking<std::io::Stdin>,
}
/// Constructs a new handle to the standard input of the current process.
///
/// The returned handle allows reading from standard input from the within the
/// Tokio runtime.
pub fn stdin() -> Stdin {
let std = io::stdin();
Stdin {
std: Blocking::new(std),
/// Constructs a new handle to the standard input of the current process.
///
/// The returned handle allows reading from standard input from the within the
/// Tokio runtime.
pub fn stdin() -> Stdin {
let std = io::stdin();
Stdin {
std: Blocking::new(std),
}
}
}
+23 -21
View File
@@ -6,28 +6,30 @@ use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
/// A handle to the standard output stream of a process.
///
/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent
/// writes to `Stdout` must be executed with care.
///
/// Created by the [`stdout`] function.
///
/// [`stdout`]: fn.stdout.html
/// [`AsyncWrite`]: trait.AsyncWrite.html
#[derive(Debug)]
pub struct Stdout {
std: Blocking<std::io::Stdout>,
}
cfg_io_std! {
/// A handle to the standard output stream of a process.
///
/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent
/// writes to `Stdout` must be executed with care.
///
/// Created by the [`stdout`] function.
///
/// [`stdout`]: fn.stdout.html
/// [`AsyncWrite`]: trait.AsyncWrite.html
#[derive(Debug)]
pub struct Stdout {
std: Blocking<std::io::Stdout>,
}
/// Constructs a new handle to the standard output of the current process.
///
/// The returned handle allows writing to standard out from the within the Tokio
/// runtime.
pub fn stdout() -> Stdout {
let std = io::stdout();
Stdout {
std: Blocking::new(std),
/// Constructs a new handle to the standard output of the current process.
///
/// The returned handle allows writing to standard out from the within the Tokio
/// runtime.
pub fn stdout() -> Stdout {
let std = io::stdout();
Stdout {
std: Blocking::new(std),
}
}
}
+111 -109
View File
@@ -4,118 +4,120 @@ use crate::io::util::read_until::{read_until, ReadUntil};
use crate::io::util::split::{split, Split};
use crate::io::AsyncBufRead;
/// An extension trait which adds utility methods to `AsyncBufRead` types.
pub trait AsyncBufReadExt: AsyncBufRead {
/// Creates a future which will read all the bytes associated with this I/O
/// object into `buf` until the delimiter `byte` or EOF is reached.
/// This method is the async equivalent to [`BufRead::read_until`](std::io::BufRead::read_until).
///
/// 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`.
///
/// The returned future will resolve to the number of bytes read once the read
/// operation is completed.
///
/// In the case of an error the buffer and the object will be discarded, with
/// the error yielded.
fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
where
Self: Unpin,
{
read_until(self, byte, buf)
}
cfg_io_util! {
/// An extension trait which adds utility methods to `AsyncBufRead` types.
pub trait AsyncBufReadExt: AsyncBufRead {
/// Creates a future which will read all the bytes associated with this I/O
/// object into `buf` until the delimiter `byte` or EOF is reached.
/// This method is the async equivalent to [`BufRead::read_until`](std::io::BufRead::read_until).
///
/// 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`.
///
/// The returned future will resolve to the number of bytes read once the read
/// operation is completed.
///
/// In the case of an error the buffer and the object will be discarded, with
/// the error yielded.
fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
where
Self: Unpin,
{
read_until(self, byte, buf)
}
/// Creates a future which will read all the bytes associated with this I/O
/// object into `buf` until a newline (the 0xA byte) or EOF is reached,
/// This method is the async equivalent to [`BufRead::read_line`](std::io::BufRead::read_line).
///
/// 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`.
///
/// The returned future will resolve to the number of bytes read once the read
/// operation is completed.
///
/// In the case of an error the buffer and the object will be discarded, with
/// the error yielded.
///
/// # 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`]: AsyncBufReadExt::read_until
fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
where
Self: Unpin,
{
read_line(self, buf)
}
/// Creates a future which will read all the bytes associated with this I/O
/// object into `buf` until a newline (the 0xA byte) or EOF is reached,
/// This method is the async equivalent to [`BufRead::read_line`](std::io::BufRead::read_line).
///
/// 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`.
///
/// The returned future will resolve to the number of bytes read once the read
/// operation is completed.
///
/// In the case of an error the buffer and the object will be discarded, with
/// the error yielded.
///
/// # 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`]: AsyncBufReadExt::read_until
fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
where
Self: Unpin,
{
read_line(self, buf)
}
/// Returns a stream of the contents of this reader split on the byte
/// `byte`.
///
/// This method is the asynchronous equivalent to
/// [`BufRead::split`](std::io::BufRead::split).
///
/// The stream returned from this function will yield instances of
/// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
/// the delimiter byte at the end.
///
/// [`io::Result`]: std::io::Result
/// [`Vec<u8>`]: std::vec::Vec
///
/// # Errors
///
/// Each item of the stream has the same error semantics as
/// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until).
///
/// # Examples
///
/// ```
/// # use tokio::io::AsyncBufRead;
/// use tokio::io::AsyncBufReadExt;
///
/// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> {
/// let mut segments = my_buf_read.split(b'f');
///
/// while let Some(segment) = segments.next_segment().await? {
/// println!("length = {}", segment.len())
/// }
/// # Ok(())
/// # }
/// ```
fn split(self, byte: u8) -> Split<Self>
where
Self: Sized + Unpin,
{
split(self, byte)
}
/// Returns a stream of the contents of this reader split on the byte
/// `byte`.
///
/// This method is the asynchronous equivalent to
/// [`BufRead::split`](std::io::BufRead::split).
///
/// The stream returned from this function will yield instances of
/// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
/// the delimiter byte at the end.
///
/// [`io::Result`]: std::io::Result
/// [`Vec<u8>`]: std::vec::Vec
///
/// # Errors
///
/// Each item of the stream has the same error semantics as
/// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until).
///
/// # Examples
///
/// ```
/// # use tokio::io::AsyncBufRead;
/// use tokio::io::AsyncBufReadExt;
///
/// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> {
/// let mut segments = my_buf_read.split(b'f');
///
/// while let Some(segment) = segments.next_segment().await? {
/// println!("length = {}", segment.len())
/// }
/// # Ok(())
/// # }
/// ```
fn split(self, byte: u8) -> Split<Self>
where
Self: Sized + Unpin,
{
split(self, byte)
}
/// Returns a stream over the lines of this reader.
/// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
///
/// 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`]: std::io::Result
/// [`String`]: String
///
/// # Errors
///
/// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
///
/// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
fn lines(self) -> Lines<Self>
where
Self: Sized,
{
lines(self)
/// Returns a stream over the lines of this reader.
/// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
///
/// 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`]: std::io::Result
/// [`String`]: String
///
/// # Errors
///
/// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
///
/// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
fn lines(self) -> Lines<Self>
where
Self: Sized,
{
lines(self)
}
}
}
+75 -73
View File
@@ -7,85 +7,87 @@ use crate::io::util::read_to_string::{read_to_string, ReadToString};
use crate::io::util::take::{take, Take};
use crate::io::{AsyncRead, AsyncWrite};
/// An extension trait which adds utility methods to `AsyncRead` types.
pub trait AsyncReadExt: AsyncRead {
/// Creates an adaptor which will chain this stream with another.
///
/// The returned `AsyncRead` instance will first read all bytes from this object
/// until EOF is encountered. Afterwards the output is equivalent to the
/// output of `next`.
fn chain<R>(self, next: R) -> Chain<Self, R>
where
Self: Sized,
R: AsyncRead,
{
chain(self, next)
}
cfg_io_util! {
/// An extension trait which adds utility methods to `AsyncRead` types.
pub trait AsyncReadExt: AsyncRead {
/// Creates an adaptor which will chain this stream with another.
///
/// The returned `AsyncRead` instance will first read all bytes from this object
/// until EOF is encountered. Afterwards the output is equivalent to the
/// output of `next`.
fn chain<R>(self, next: R) -> Chain<Self, R>
where
Self: Sized,
R: AsyncRead,
{
chain(self, next)
}
/// Copy all data from `self` into the provided `AsyncWrite`.
///
/// The returned future will copy all the bytes read from `reader` into the
/// `writer` specified. This future will only complete once the `reader`
/// has hit EOF and all bytes have been written to and flushed from the
/// `writer` provided.
///
/// On success the number of bytes is returned and the `reader` and `writer`
/// are consumed. On error the error is returned and the I/O objects are
/// consumed as well.
fn copy<'a, W>(&'a mut self, dst: &'a mut W) -> Copy<'a, Self, W>
where
Self: Unpin,
W: AsyncWrite + Unpin + ?Sized,
{
copy(self, dst)
}
/// Copy all data from `self` into the provided `AsyncWrite`.
///
/// The returned future will copy all the bytes read from `reader` into the
/// `writer` specified. This future will only complete once the `reader`
/// has hit EOF and all bytes have been written to and flushed from the
/// `writer` provided.
///
/// On success the number of bytes is returned and the `reader` and `writer`
/// are consumed. On error the error is returned and the I/O objects are
/// consumed as well.
fn copy<'a, W>(&'a mut self, dst: &'a mut W) -> Copy<'a, Self, W>
where
Self: Unpin,
W: AsyncWrite + Unpin + ?Sized,
{
copy(self, dst)
}
/// Read data into the provided buffer.
///
/// The returned future will resolve to the number of bytes read once the
/// read operation is completed.
fn read<'a>(&'a mut self, dst: &'a mut [u8]) -> Read<'a, Self>
where
Self: Unpin,
{
read(self, dst)
}
/// Read data into the provided buffer.
///
/// The returned future will resolve to the number of bytes read once the
/// read operation is completed.
fn read<'a>(&'a mut self, dst: &'a mut [u8]) -> Read<'a, Self>
where
Self: Unpin,
{
read(self, dst)
}
/// Read exactly the amount of data needed to fill the provided buffer.
fn read_exact<'a>(&'a mut self, dst: &'a mut [u8]) -> ReadExact<'a, Self>
where
Self: Unpin,
{
read_exact(self, dst)
}
/// Read exactly the amount of data needed to fill the provided buffer.
fn read_exact<'a>(&'a mut self, dst: &'a mut [u8]) -> ReadExact<'a, Self>
where
Self: Unpin,
{
read_exact(self, dst)
}
/// Read all bytes until EOF in this source, placing them into `dst`.
///
/// On success the total number of bytes read is returned.
fn read_to_end<'a>(&'a mut self, dst: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>
where
Self: Unpin,
{
read_to_end(self, dst)
}
/// Read all bytes until EOF in this source, placing them into `dst`.
///
/// On success the total number of bytes read is returned.
fn read_to_end<'a>(&'a mut self, dst: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>
where
Self: Unpin,
{
read_to_end(self, dst)
}
/// Read all bytes until EOF in this source, placing them into `dst`.
///
/// On success the total number of bytes read is returned.
fn read_to_string<'a>(&'a mut self, dst: &'a mut String) -> ReadToString<'a, Self>
where
Self: Unpin,
{
read_to_string(self, dst)
}
/// Read all bytes until EOF in this source, placing them into `dst`.
///
/// On success the total number of bytes read is returned.
fn read_to_string<'a>(&'a mut self, dst: &'a mut String) -> ReadToString<'a, Self>
where
Self: Unpin,
{
read_to_string(self, dst)
}
/// Creates an AsyncRead adapter which will read at most `limit` bytes
/// from the underlying reader.
fn take(self, limit: u64) -> Take<Self>
where
Self: Sized,
{
take(self, limit)
/// Creates an AsyncRead adapter which will read at most `limit` bytes
/// from the underlying reader.
fn take(self, limit: u64) -> Take<Self>
where
Self: Sized,
{
take(self, limit)
}
}
}
+31 -29
View File
@@ -4,38 +4,40 @@ use crate::io::util::write::{write, Write};
use crate::io::util::write_all::{write_all, WriteAll};
use crate::io::AsyncWrite;
/// An extension trait which adds utility methods to `AsyncWrite` types.
pub trait AsyncWriteExt: AsyncWrite {
/// Write a buffer into this writter, returning how many bytes were written.
fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
where
Self: Unpin,
{
write(self, src)
}
cfg_io_util! {
/// An extension trait which adds utility methods to `AsyncWrite` types.
pub trait AsyncWriteExt: AsyncWrite {
/// Write a buffer into this writter, returning how many bytes were written.
fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
where
Self: Unpin,
{
write(self, src)
}
/// Attempt to write an entire buffer into this writter.
fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self>
where
Self: Unpin,
{
write_all(self, src)
}
/// Attempt to write an entire buffer into this writter.
fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self>
where
Self: Unpin,
{
write_all(self, src)
}
/// Flush the contents of this writer.
fn flush(&mut self) -> Flush<'_, Self>
where
Self: Unpin,
{
flush(self)
}
/// Flush the contents of this writer.
fn flush(&mut self) -> Flush<'_, Self>
where
Self: Unpin,
{
flush(self)
}
/// Shutdown this writer.
fn shutdown(&mut self) -> Shutdown<'_, Self>
where
Self: Unpin,
{
shutdown(self)
/// Shutdown this writer.
fn shutdown(&mut self) -> Shutdown<'_, Self>
where
Self: Unpin,
{
shutdown(self)
}
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ pin_project! {
/// 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.
// TODO: Examples
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
pub struct BufReader<R> {
#[pin]
pub(super) inner: R,
+1
View File
@@ -16,6 +16,7 @@ pin_project! {
/// types aid with these problems respectively, but do so in only one direction. `BufStream` wraps
/// one in the other so that both directions are buffered. See their documentation for details.
#[derive(Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
pub struct BufStream<RW> {
#[pin]
inner: BufReader<BufWriter<RW>>,
+1 -1
View File
@@ -29,7 +29,7 @@ pin_project! {
/// [`AsyncWrite`]: AsyncWrite
/// [`flush`]: super::AsyncWriteExt::flush
///
// TODO: Examples
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
pub struct BufWriter<W> {
#[pin]
pub(super) inner: W,
+1
View File
@@ -9,6 +9,7 @@ use std::task::{Context, Poll};
pin_project! {
/// Stream for the [`chain`](super::AsyncReadExt::chain) method.
#[must_use = "streams do nothing unless polled"]
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
pub struct Chain<T, U> {
#[pin]
first: T,
+66 -64
View File
@@ -5,71 +5,73 @@ use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
/// A future that asynchronously copies the entire contents of a reader into a
/// writer.
///
/// This struct is generally created by calling [`copy`][copy]. Please
/// see the documentation of `copy()` for more details.
///
/// [copy]: fn.copy.html
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Copy<'a, R: ?Sized, W: ?Sized> {
reader: &'a mut R,
read_done: bool,
writer: &'a mut W,
pos: usize,
cap: usize,
amt: u64,
buf: Box<[u8]>,
}
cfg_io_util! {
/// A future that asynchronously copies the entire contents of a reader into a
/// writer.
///
/// This struct is generally created by calling [`copy`][copy]. Please
/// see the documentation of `copy()` for more details.
///
/// [copy]: fn.copy.html
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Copy<'a, R: ?Sized, W: ?Sized> {
reader: &'a mut R,
read_done: bool,
writer: &'a mut W,
pos: usize,
cap: usize,
amt: u64,
buf: Box<[u8]>,
}
/// Asynchronously copies the entire contents of a reader into a writer.
///
/// This function returns a future that 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.
///
/// This is an asynchronous version of [`std::io::copy`][std].
///
/// # Errors
///
/// The returned future will finish with an error will return an error
/// immediately if any call to `poll_read` or `poll_write` returns an error.
///
/// # Examples
///
/// ```
/// use tokio::io;
///
/// # async fn dox() -> std::io::Result<()> {
/// let mut reader: &[u8] = b"hello";
/// let mut writer: Vec<u8> = vec![];
///
/// io::copy(&mut reader, &mut writer).await?;
///
/// assert_eq!(&b"hello"[..], &writer[..]);
/// # Ok(())
/// # }
/// ```
///
/// [std]: https://doc.rust-lang.org/std/io/fn.copy.html
pub fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> Copy<'a, R, W>
where
R: AsyncRead + Unpin + ?Sized,
W: AsyncWrite + Unpin + ?Sized,
{
Copy {
reader,
read_done: false,
writer,
amt: 0,
pos: 0,
cap: 0,
buf: Box::new([0; 2048]),
/// Asynchronously copies the entire contents of a reader into a writer.
///
/// This function returns a future that 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.
///
/// This is an asynchronous version of [`std::io::copy`][std].
///
/// # Errors
///
/// The returned future will finish with an error will return an error
/// immediately if any call to `poll_read` or `poll_write` returns an error.
///
/// # Examples
///
/// ```
/// use tokio::io;
///
/// # async fn dox() -> std::io::Result<()> {
/// let mut reader: &[u8] = b"hello";
/// let mut writer: Vec<u8> = vec![];
///
/// io::copy(&mut reader, &mut writer).await?;
///
/// assert_eq!(&b"hello"[..], &writer[..]);
/// # Ok(())
/// # }
/// ```
///
/// [std]: https://doc.rust-lang.org/std/io/fn.copy.html
pub fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> Copy<'a, R, W>
where
R: AsyncRead + Unpin + ?Sized,
W: AsyncWrite + Unpin + ?Sized,
{
Copy {
reader,
read_done: false,
writer,
amt: 0,
pos: 0,
cap: 0,
buf: Box::new([0; 2048]),
}
}
}
+36 -34
View File
@@ -5,41 +5,43 @@ use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
// An async reader which is always at EOF.
///
/// This struct is generally created by calling [`empty`]. Please see
/// the documentation of [`empty()`][`empty`] for more details.
///
/// This is an asynchronous version of [`std::io::empty`][std].
///
/// [`empty`]: fn.empty.html
/// [std]: https://doc.rust-lang.org/std/io/struct.Empty.html
pub struct Empty {
_p: (),
}
cfg_io_util! {
// An async reader which is always at EOF.
///
/// This struct is generally created by calling [`empty`]. Please see
/// the documentation of [`empty()`][`empty`] for more details.
///
/// This is an asynchronous version of [`std::io::empty`][std].
///
/// [`empty`]: fn.empty.html
/// [std]: https://doc.rust-lang.org/std/io/struct.Empty.html
pub struct Empty {
_p: (),
}
/// Creates a new empty async reader.
///
/// All reads from the returned reader will return `Poll::Ready(Ok(0))`.
///
/// This is an asynchronous version of [`std::io::empty`][std].
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```rust
/// # use tokio::io::{self, AsyncReadExt};
/// # async fn dox() {
/// let mut buffer = String::new();
/// io::empty().read_to_string(&mut buffer).await.unwrap();
/// assert!(buffer.is_empty());
/// # }
/// ```
///
/// [std]: https://doc.rust-lang.org/std/io/fn.empty.html
pub fn empty() -> Empty {
Empty { _p: () }
/// Creates a new empty async reader.
///
/// All reads from the returned reader will return `Poll::Ready(Ok(0))`.
///
/// This is an asynchronous version of [`std::io::empty`][std].
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```rust
/// # use tokio::io::{self, AsyncReadExt};
/// # async fn dox() {
/// let mut buffer = String::new();
/// io::empty().read_to_string(&mut buffer).await.unwrap();
/// assert!(buffer.is_empty());
/// # }
/// ```
///
/// [std]: https://doc.rust-lang.org/std/io/fn.empty.html
pub fn empty() -> Empty {
Empty { _p: () }
}
}
impl AsyncRead for Empty {
+8 -6
View File
@@ -5,12 +5,14 @@ use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
/// A future used to fully flush an I/O object.
///
/// Created by the [`AsyncWriteExt::flush`] function.
#[derive(Debug)]
pub struct Flush<'a, A: ?Sized> {
a: &'a mut A,
cfg_io_util! {
/// A future used to fully flush an I/O object.
///
/// Created by the [`AsyncWriteExt::flush`] function.
#[derive(Debug)]
pub struct Flush<'a, A: ?Sized> {
a: &'a mut A,
}
}
/// Creates a future which will entirely flush an I/O object.
+1
View File
@@ -11,6 +11,7 @@ pin_project! {
/// Stream for the [`lines`](crate::io::AsyncBufReadExt::lines) method.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
pub struct Lines<R> {
#[pin]
reader: R,
+11 -9
View File
@@ -18,15 +18,17 @@ where
Read { reader, buf }
}
/// A future which can be used to easily read available number of bytes to fill
/// a buffer.
///
/// Created by the [`read`] function.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Read<'a, R: ?Sized> {
reader: &'a mut R,
buf: &'a mut [u8],
cfg_io_util! {
/// A future which can be used to easily read available number of bytes to fill
/// a buffer.
///
/// Created by the [`read`] function.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Read<'a, R: ?Sized> {
reader: &'a mut R,
buf: &'a mut [u8],
}
}
impl<R> Future for Read<'_, R>
+12 -10
View File
@@ -21,16 +21,18 @@ where
}
}
/// Creates a future which will read exactly enough bytes to fill `buf`,
/// returning an error if EOF is hit sooner.
///
/// On success the number of bytes is returned
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReadExact<'a, A: ?Sized> {
reader: &'a mut A,
buf: &'a mut [u8],
pos: usize,
cfg_io_util! {
/// Creates a future which will read exactly enough bytes to fill `buf`,
/// returning an error if EOF is hit sooner.
///
/// On success the number of bytes is returned
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReadExact<'a, A: ?Sized> {
reader: &'a mut A,
buf: &'a mut [u8],
pos: usize,
}
}
fn eof() -> io::Error {
+10 -8
View File
@@ -8,14 +8,16 @@ use std::pin::Pin;
use std::str;
use std::task::{Context, Poll};
/// Future for the [`read_line`](crate::io::AsyncBufReadExt::read_line) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReadLine<'a, R: ?Sized> {
reader: &'a mut R,
buf: &'a mut String,
bytes: Vec<u8>,
read: usize,
cfg_io_util! {
/// Future for the [`read_line`](crate::io::AsyncBufReadExt::read_line) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReadLine<'a, R: ?Sized> {
reader: &'a mut R,
buf: &'a mut String,
bytes: Vec<u8>,
read: usize,
}
}
pub(crate) fn read_line<'a, R>(reader: &'a mut R, buf: &'a mut String) -> ReadLine<'a, R>
+1
View File
@@ -8,6 +8,7 @@ use std::task::{Context, Poll};
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
pub struct ReadToEnd<'a, R: ?Sized> {
reader: &'a mut R,
buf: &'a mut Vec<u8>,
+10 -8
View File
@@ -6,14 +6,16 @@ use std::pin::Pin;
use std::task::{Context, Poll};
use std::{io, mem, str};
/// Future for the [`read_to_string`](super::AsyncReadExt::read_to_string) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReadToString<'a, R: ?Sized> {
reader: &'a mut R,
buf: &'a mut String,
bytes: Vec<u8>,
start_len: usize,
cfg_io_util! {
/// Future for the [`read_to_string`](super::AsyncReadExt::read_to_string) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReadToString<'a, R: ?Sized> {
reader: &'a mut R,
buf: &'a mut String,
bytes: Vec<u8>,
start_len: usize,
}
}
pub(crate) fn read_to_string<'a, R>(reader: &'a mut R, buf: &'a mut String) -> ReadToString<'a, R>
+10 -8
View File
@@ -6,14 +6,16 @@ use std::mem;
use std::pin::Pin;
use std::task::{Context, Poll};
/// Future for the [`read_until`](crate::io::AsyncBufReadExt::read_until) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReadUntil<'a, R: ?Sized> {
reader: &'a mut R,
byte: u8,
buf: &'a mut Vec<u8>,
read: usize,
cfg_io_util! {
/// Future for the [`read_until`](crate::io::AsyncBufReadExt::read_until) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReadUntil<'a, R: ?Sized> {
reader: &'a mut R,
byte: u8,
buf: &'a mut Vec<u8>,
read: usize,
}
}
pub(crate) fn read_until<'a, R>(
+37 -35
View File
@@ -4,42 +4,44 @@ use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
/// An async reader which yields one byte over and over and over and over and
/// over and...
///
/// This struct is generally created by calling [`repeat`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// This is an asynchronous version of [`std::io::Repeat`][std].
///
/// [repeat]: fn.repeat.html
/// [std]: https://doc.rust-lang.org/std/io/struct.Repeat.html
#[derive(Debug)]
pub struct Repeat {
byte: u8,
}
cfg_io_util! {
/// An async reader which yields one byte over and over and over and over and
/// over and...
///
/// This struct is generally created by calling [`repeat`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// This is an asynchronous version of [`std::io::Repeat`][std].
///
/// [repeat]: fn.repeat.html
/// [std]: https://doc.rust-lang.org/std/io/struct.Repeat.html
#[derive(Debug)]
pub struct Repeat {
byte: u8,
}
/// Creates an instance of an async reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
///
/// This is an asynchronous version of [`std::io::repeat`][std].
///
/// # Examples
///
/// ```
/// # use tokio::io::{self, AsyncReadExt};
/// # async fn dox() {
/// let mut buffer = [0; 3];
/// io::repeat(0b101).read_exact(&mut buffer).await.unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// # }
/// ```
///
/// [std]: https://doc.rust-lang.org/std/io/fn.repeat.html
pub fn repeat(byte: u8) -> Repeat {
Repeat { byte }
/// Creates an instance of an async reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
///
/// This is an asynchronous version of [`std::io::repeat`][std].
///
/// # Examples
///
/// ```
/// # use tokio::io::{self, AsyncReadExt};
/// # async fn dox() {
/// let mut buffer = [0; 3];
/// io::repeat(0b101).read_exact(&mut buffer).await.unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// # }
/// ```
///
/// [std]: https://doc.rust-lang.org/std/io/fn.repeat.html
pub fn repeat(byte: u8) -> Repeat {
Repeat { byte }
}
}
impl AsyncRead for Repeat {
+8 -6
View File
@@ -5,12 +5,14 @@ use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
/// A future used to shutdown an I/O object.
///
/// Created by the [`AsyncWriteExt::shutdown`] function.
#[derive(Debug)]
pub struct Shutdown<'a, A: ?Sized> {
a: &'a mut A,
cfg_io_util! {
/// A future used to shutdown an I/O object.
///
/// Created by the [`AsyncWriteExt::shutdown`] function.
#[derive(Debug)]
pub struct Shutdown<'a, A: ?Sized> {
a: &'a mut A,
}
}
/// Creates a future which will shutdown an I/O object.
+34 -32
View File
@@ -5,39 +5,41 @@ use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
/// An async writer which will move data into the void.
///
/// This struct is generally created by calling [`sink`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// This is an asynchronous version of `std::io::Sink`.
///
/// [sink]: fn.sink.html
pub struct Sink {
_p: (),
}
cfg_io_util! {
/// An async writer which will move data into the void.
///
/// This struct is generally created by calling [`sink`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// This is an asynchronous version of `std::io::Sink`.
///
/// [sink]: fn.sink.html
pub struct Sink {
_p: (),
}
/// Creates an instance of an async writer which will successfully consume all
/// data.
///
/// All calls to `poll_write` on the returned instance will return
/// `Poll::Ready(Ok(buf.len()))` and the contents of the buffer will not be
/// inspected.
///
/// This is an asynchronous version of `std::io::sink`.
///
/// # Examples
///
/// ```rust
/// # use tokio::io::{self, AsyncWriteExt};
/// # async fn dox() {
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::sink().write(&buffer).await.unwrap();
/// assert_eq!(num_bytes, 5);
/// # }
/// ```
pub fn sink() -> Sink {
Sink { _p: () }
/// Creates an instance of an async writer which will successfully consume all
/// data.
///
/// All calls to `poll_write` on the returned instance will return
/// `Poll::Ready(Ok(buf.len()))` and the contents of the buffer will not be
/// inspected.
///
/// This is an asynchronous version of `std::io::sink`.
///
/// # Examples
///
/// ```rust
/// # use tokio::io::{self, AsyncWriteExt};
/// # async fn dox() {
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::sink().write(&buffer).await.unwrap();
/// assert_eq!(num_bytes, 5);
/// # }
/// ```
pub fn sink() -> Sink {
Sink { _p: () }
}
}
impl AsyncWrite for Sink {
+1
View File
@@ -11,6 +11,7 @@ pin_project! {
/// Stream for the [`split`](crate::io::AsyncBufReadExt::split) method.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
pub struct Split<R> {
#[pin]
reader: R,
+1
View File
@@ -10,6 +10,7 @@ pin_project! {
/// Stream for the [`take`](super::AsyncReadExt::take) method.
#[derive(Debug)]
#[must_use = "streams do nothing unless you `.await` or poll them"]
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
pub struct Take<R> {
#[pin]
inner: R,
+8 -6
View File
@@ -5,12 +5,14 @@ use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
/// A future to write some of the buffer to an `AsyncWrite`.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Write<'a, W: ?Sized> {
writer: &'a mut W,
buf: &'a [u8],
cfg_io_util! {
/// A future to write some of the buffer to an `AsyncWrite`.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Write<'a, W: ?Sized> {
writer: &'a mut W,
buf: &'a [u8],
}
}
/// Tries to write some bytes from the given `buf` to the writer in an
+7 -5
View File
@@ -6,11 +6,13 @@ use std::mem;
use std::pin::Pin;
use std::task::{Context, Poll};
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct WriteAll<'a, W: ?Sized> {
writer: &'a mut W,
buf: &'a [u8],
cfg_io_util! {
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct WriteAll<'a, W: ?Sized> {
writer: &'a mut W,
buf: &'a [u8],
}
}
pub(crate) fn write_all<'a, W>(writer: &'a mut W, buf: &'a [u8]) -> WriteAll<'a, W>
+2 -1
View File
@@ -10,6 +10,7 @@
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
#![cfg_attr(docsrs, feature(doc_cfg))]
//! A runtime for writing reliable, asynchronous, and slim applications.
//!
@@ -71,7 +72,7 @@
//! [`tokio::task`]: crate::task
//! [`spawn`]: crate::task::spawn()
//! [`JoinHandle`]: crate::task::JoinHandle
//! [`blocking`]: task/index.html#blocking-and-yielding
//! [blocking]: task/index.html#blocking-and-yielding
//!
//! The [`tokio::sync`] module contains synchronization primitives to use when
//! need to communicate or share data. These include:
+38 -7
View File
@@ -12,7 +12,11 @@ macro_rules! cfg_resource_drivers {
macro_rules! cfg_blocking {
($($item:item)*) => {
$( #[cfg(feature = "blocking")] $item )*
$(
#[cfg(feature = "blocking")]
#[cfg_attr(docsrs, doc(cfg(feature = "blocking")))]
$item
)*
}
}
@@ -50,12 +54,22 @@ macro_rules! cfg_not_blocking_impl {
macro_rules! cfg_dns {
($($item:item)*) => {
$( #[cfg(feature = "dns")] $item )*
$(
#[cfg(feature = "dns")]
#[cfg_attr(docsrs, doc(cfg(feature = "dns")))]
$item
)*
}
}
macro_rules! cfg_fs {
($($item:item)*) => { $( #[cfg(feature = "fs")] $item )* }
($($item:item)*) => {
$(
#[cfg(feature = "fs")]
#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
$item
)*
}
}
macro_rules! cfg_io_blocking {
@@ -66,25 +80,40 @@ macro_rules! cfg_io_blocking {
macro_rules! cfg_io_driver {
($($item:item)*) => {
$( #[cfg(feature = "io-driver")] $item )*
$(
#[cfg(feature = "io-driver")]
#[cfg_attr(docsrs, doc(cfg(feature = "io-driver")))]
$item
)*
}
}
macro_rules! cfg_not_io_driver {
($($item:item)*) => {
$( #[cfg(not(feature = "io-driver"))] $item )*
$(
#[cfg(not(feature = "io-driver"))]
$item
)*
}
}
macro_rules! cfg_io_std {
($($item:item)*) => {
$( #[cfg(feature = "io-std")] $item )*
$(
#[cfg(feature = "io-std")]
#[cfg_attr(docsrs, doc(cfg(feature = "io-std")))]
$item
)*
}
}
macro_rules! cfg_io_util {
($($item:item)*) => {
$( #[cfg(feature = "io-util")] $item )*
$(
#[cfg(feature = "io-util")]
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
$item
)*
}
}
@@ -110,6 +139,7 @@ macro_rules! cfg_macros {
($($item:item)*) => {
$(
#[cfg(feature = "macros")]
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
#[doc(inline)]
$item
)*
@@ -120,6 +150,7 @@ macro_rules! cfg_process {
($($item:item)*) => {
$(
#[cfg(feature = "process")]
#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
#[cfg(not(loom))]
$item
)*
+6 -2
View File
@@ -101,10 +101,14 @@
//! While similar to the standard library, this crate's `Child` type differs
//! importantly in the behavior of `drop`. In the standard library, a child
//! process will continue running after the instance of [`std::process::Child`]
//! is dropped. In this crate, however, because [`tokio::process::Child`][Child] is a
//! is dropped. In this crate, however, because [`tokio::process::Child`] is a
//! future of the child's `ExitStatus`, a child process is terminated if
//! `tokio::process::Child` is dropped. The behavior of the standard library can
//! be regained with the [`Child::forget`](crate::process::Child::forget) method.
//! be regained with the [`Child::forget`](crate::process::Child::forget)
//! method.
//!
//! [`Command`]: crate::process::Command
//! [`tokio::process::Child`]: crate::process::Child
#[path = "unix/mod.rs"]
#[cfg(unix)]