Skip to content

Commit

Permalink
Implement AsyncWrite for the generic Cursor<T: AsMut<[u8]>>
Browse files Browse the repository at this point in the history
This introduces an unfortunate point of difference between
futures::io::AsyncWrite and std::io::Write, but I think the increased
ergonomics around writing to statically sized in memory buffers
(presumably just for test purposes) is useful. `impl<T: AsRef<[u8]>>
Read for Cursor<T>` was added in
rust-lang/rust#27197, I'm not sure why `impl<T:
AsMut<[u8]>> Write for Cursor<T>` wasn't added at the same time; I would
propose doing this change in `std` and just piggybacking off it here,
but the breakage is almost certainly not worth it by this point.
  • Loading branch information
Nemo157 committed Jul 21, 2018
1 parent 5fdf4ba commit 3457d40
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 31 deletions.
26 changes: 17 additions & 9 deletions futures-io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ if_std! {
use std::boxed::Box;
use std::io as StdIo;
use std::ptr;
use std::vec::Vec;

// Re-export IoVec for convenience
pub use iovec::IoVec;
Expand Down Expand Up @@ -354,16 +353,25 @@ if_std! {
}
}

impl<'a> AsyncWrite for StdIo::Cursor<&'a mut [u8]> {
delegate_async_write_to_stdio!();
}
impl<T: AsMut<[u8]>> AsyncWrite for StdIo::Cursor<T> {
fn poll_write(&mut self, _: &mut task::Context, buf: &[u8])
-> Poll<Result<usize>>
{
let result = StdIo::Write::write(&mut self.get_mut().as_mut(), buf);
if let Ok(offset) = result {
let position = self.position() + offset as u64;
self.set_position(position);
}
Poll::Ready(result)
}

impl AsyncWrite for StdIo::Cursor<Vec<u8>> {
delegate_async_write_to_stdio!();
}
fn poll_flush(&mut self, _: &mut task::Context) -> Poll<Result<()>> {
Poll::Ready(StdIo::Write::flush(&mut self.get_mut().as_mut()))
}

impl AsyncWrite for StdIo::Cursor<Box<[u8]>> {
delegate_async_write_to_stdio!();
fn poll_close(&mut self, cx: &mut task::Context) -> Poll<Result<()>> {
self.poll_flush(cx)
}
}

impl AsyncWrite for StdIo::Sink {
Expand Down
37 changes: 15 additions & 22 deletions futures-util/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,12 @@ pub trait AsyncReadExt: AsyncRead {
/// use std::io::Cursor;
///
/// let mut reader = Cursor::new([1, 2, 3, 4]);
/// let mut output = [0u8; 5];
/// let mut writer = Cursor::new([0u8; 5]);
///
/// let bytes = {
/// let mut writer = Cursor::new(&mut output[..]);
/// await!(reader.copy_into(&mut writer))?
/// };
/// let bytes = await!(reader.copy_into(&mut writer))?;
///
/// assert_eq!(bytes, 4);
/// assert_eq!(output, [1, 2, 3, 4, 0]);
/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]);
/// # Ok::<(), Box<std::error::Error>>(()) }).unwrap();
/// ```
fn copy_into<'a, W>(
Expand Down Expand Up @@ -201,23 +198,22 @@ pub trait AsyncReadExt: AsyncRead {
/// use futures::io::AsyncReadExt;
/// use std::io::Cursor;
///
/// // Note that for `Cursor` the read and write halves share a single
/// // seek position, this may or may not be true for other types that
/// // implement both `AsyncRead` and `AsyncWrite`.
///
/// let mut reader = Cursor::new([1, 2, 3, 4]);
/// let mut buffer = [0, 0, 0, 0, 4, 3, 2, 1];
/// let mut output = [0u8; 5];
/// let mut buffer = Cursor::new([0, 0, 0, 0, 4, 3, 2, 1]);
/// let mut writer = Cursor::new([0u8; 5]);
///
/// {
/// let mut writer = Cursor::new(&mut output[..]);
/// // Note that for `Cursor` the read and write halves share a single
/// // seek position, this may or may not be true for other types that
/// // implement both `AsyncRead` and `AsyncWrite`.
/// let buffer_cursor = Cursor::new(&mut buffer[..]);
/// let (mut buffer_reader, mut buffer_writer) = buffer_cursor.split();
/// let (mut buffer_reader, mut buffer_writer) = (&mut buffer).split();
/// await!(reader.copy_into(&mut buffer_writer))?;
/// await!(buffer_reader.copy_into(&mut writer))?;
/// }
///
/// assert_eq!(buffer, [1, 2, 3, 4, 4, 3, 2, 1]);
/// assert_eq!(output, [4, 3, 2, 1, 0]);
/// assert_eq!(buffer.into_inner(), [1, 2, 3, 4, 4, 3, 2, 1]);
/// assert_eq!(writer.into_inner(), [4, 3, 2, 1, 0]);
/// # Ok::<(), Box<std::error::Error>>(()) }).unwrap();
/// ```
fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
Expand Down Expand Up @@ -278,14 +274,11 @@ pub trait AsyncWriteExt: AsyncWrite {
/// use futures::io::AsyncWriteExt;
/// use std::io::Cursor;
///
/// let mut output = [0u8; 5];
/// let mut writer = Cursor::new([0u8; 5]);
///
/// {
/// let mut writer = Cursor::new(&mut output[..]);
/// await!(writer.write_all(&[1, 2, 3, 4]))?;
/// }
/// await!(writer.write_all(&[1, 2, 3, 4]))?;
///
/// assert_eq!(output, [1, 2, 3, 4, 0]);
/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]);
/// # Ok::<(), Box<std::error::Error>>(()) }).unwrap();
/// ```
fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> WriteAll<'a, Self> {
Expand Down

0 comments on commit 3457d40

Please sign in to comment.