Skip to content

Commit

Permalink
tokio: move I/O helpers to ext traits (#1204)
Browse files Browse the repository at this point in the history
Refs: #1203
  • Loading branch information
carllerche authored Jun 26, 2019
1 parent 8404f79 commit 11f6b28
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 214 deletions.
64 changes: 64 additions & 0 deletions tokio/src/io/async_read_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::io::copy::{copy, Copy};
use crate::io::read::{read, Read};
use crate::io::read_exact::{read_exact, ReadExact};

use tokio_io::{AsyncRead, AsyncWrite};

/// An extension trait which adds utility methods to `AsyncRead` types.
pub trait AsyncReadExt: AsyncRead {

/// 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.
///
/// # Examples
///
/// ```
/// unimplemented!();
/// ```
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.
///
/// # Examples
///
/// ```
/// unimplemented!();
/// ```
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.
///
/// # Examples
///
/// ```
/// unimplemented!();
/// ```
fn read_exact<'a>(&'a mut self, dst: &'a mut [u8]) -> ReadExact<'a, Self>
where Self: Unpin,
{
read_exact(self, dst)
}
}

impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}
24 changes: 24 additions & 0 deletions tokio/src/io/async_write_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::io::write::{write, Write};

use tokio_io::AsyncWrite;

/// An extension trait which adds utility methods to `AsyncWrite` types.
pub trait AsyncWriteExt: AsyncWrite {
/// Write the provided data into `self`.
///
/// The returned future will resolve to the number of bytes written once the
/// write operation is completed.
///
/// # Examples
///
/// ```
/// unimplemented!();
/// ````
fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
where Self: Unpin,
{
write(self, src)
}
}

impl<W: AsyncWrite + ?Sized> AsyncWriteExt for W {}
38 changes: 6 additions & 32 deletions tokio/src/io/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,8 @@ use std::pin::Pin;
use std::task::{Context, Poll};
use tokio_io::{AsyncRead, AsyncWrite};

macro_rules! ready {
($e:expr) => {
match $e {
::std::task::Poll::Ready(t) => t,
::std::task::Poll::Pending => return ::std::task::Poll::Pending,
}
};
}

/// A future which will copy all data from a reader into a writer.
///
/// Created by the [`copy`] function, this future will resolve to the number of
/// bytes copied or an error if one happens.
///
/// [`copy`]: fn.copy.html
#[derive(Debug)]
pub struct Copy<'a, R, W> {
pub struct Copy<'a, R: ?Sized, W: ?Sized> {
reader: &'a mut R,
read_done: bool,
writer: &'a mut W,
Expand All @@ -30,21 +15,10 @@ pub struct Copy<'a, R, W> {
buf: Box<[u8]>,
}

/// Creates a future which represents copying all the bytes from one object to
/// another.
///
/// 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.
pub fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> Copy<'a, R, W>
pub(crate) fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> Copy<'a, R, W>
where
R: AsyncRead + Unpin,
W: AsyncWrite + Unpin,
R: AsyncRead + Unpin + ?Sized,
W: AsyncWrite + Unpin + ?Sized,
{
Copy {
reader,
Expand All @@ -59,8 +33,8 @@ where

impl<'a, R, W> Future for Copy<'a, R, W>
where
R: AsyncRead + Unpin,
W: AsyncWrite + Unpin,
R: AsyncRead + Unpin + ?Sized,
W: AsyncWrite + Unpin + ?Sized,
{
type Output = io::Result<u64>;

Expand Down
21 changes: 10 additions & 11 deletions tokio/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,21 @@
//! [`ErrorKind`]: enum.ErrorKind.html
//! [`Result`]: type.Result.html

pub use tokio_io::{AsyncRead, AsyncWrite};
mod async_read_ext;
mod async_write_ext;
mod copy;
mod read;
mod write;
mod read_exact;

pub use self::async_read_ext::AsyncReadExt;
pub use self::async_write_ext::AsyncWriteExt;

// standard input, output, and error
#[cfg(feature = "fs")]
pub use tokio_fs::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
pub use tokio_io::{AsyncRead, AsyncWrite};

// Re-export io::Error so that users don't have to deal
// with conflicts when `use`ing `futures::io` and `std::io`.
pub use std::io::{Error, ErrorKind, Result};

mod copy;
mod read;
mod write;
mod read_exact;

pub use self::copy::{copy, Copy};
pub use self::read::{read, Read};
pub use self::write::{write, Write};
pub use self::read_exact::{read_exact, ReadExact};
2 changes: 1 addition & 1 deletion tokio/src/io/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use tokio_io::AsyncRead;
///
/// The returned future will resolve to both the I/O stream and the buffer
/// as well as the number of bytes read once the read operation is completed.
pub fn read<'a, R>(reader: &'a mut R, buf: &'a mut [u8]) -> Read<'a, R>
pub(crate) fn read<'a, R>(reader: &'a mut R, buf: &'a mut [u8]) -> Read<'a, R>
where
R: AsyncRead + Unpin + ?Sized,
{
Expand Down
12 changes: 1 addition & 11 deletions tokio/src/io/read_exact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,13 @@ use std::pin::Pin;
use std::task::{Context, Poll};
use tokio_io::AsyncRead;

macro_rules! ready {
($e:expr) => {
match $e {
::std::task::Poll::Ready(t) => t,
::std::task::Poll::Pending => return ::std::task::Poll::Pending,
}
};
}


/// A future which can be used to easily read exactly enough bytes to fill
/// a buffer.
///
/// Created by the [`read_exact`] function.
///
/// [`read_exact`]: fn.read_exact.html
pub fn read_exact<'a, A>(reader: &'a mut A, buf: &'a mut[u8]) -> ReadExact<'a, A>
pub(crate) fn read_exact<'a, A>(reader: &'a mut A, buf: &'a mut[u8]) -> ReadExact<'a, A>
where
A: AsyncRead + Unpin + ?Sized
{
Expand Down
2 changes: 1 addition & 1 deletion tokio/src/io/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct Write<'a, W: ?Sized> {

/// Tries to write some bytes from the given `buf` to the writer in an
/// asynchronous manner, returning a future.
pub fn write<'a, W>(writer: &'a mut W, buf: &'a [u8]) -> Write<'a, W>
pub(crate) fn write<'a, W>(writer: &'a mut W, buf: &'a [u8]) -> Write<'a, W>
where
W: AsyncWrite + Unpin + ?Sized,
{
Expand Down
9 changes: 9 additions & 0 deletions tokio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ macro_rules! if_runtime {
)*)
}

macro_rules! ready {
($e:expr) => {
match $e {
::std::task::Poll::Ready(t) => t,
::std::task::Poll::Pending => return ::std::task::Poll::Pending,
}
};
}

#[cfg(feature = "timer")]
pub mod clock;
#[cfg(feature = "codec")]
Expand Down
Loading

0 comments on commit 11f6b28

Please sign in to comment.