Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge functionality of io::Sink into io::Empty #98154

Merged
merged 1 commit into from
Jul 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 76 additions & 24 deletions library/std/src/io/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,41 @@ use crate::io::{
self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write,
};

/// A reader which is always at EOF.
/// `Empty` ignores any data written via [`Write`], and will always be empty
/// (returning zero bytes) when read via [`Read`].
///
/// This struct is generally created by calling [`empty()`]. Please see
/// the documentation of [`empty()`] for more details.
/// This struct is generally created by calling [`empty()`]. Please
/// see the documentation of [`empty()`] for more details.
#[stable(feature = "rust1", since = "1.0.0")]
#[non_exhaustive]
#[derive(Copy, Clone, Default)]
#[derive(Copy, Clone, Debug, Default)]
pub struct Empty;

/// Constructs a new handle to an empty reader.
/// Creates a value that is always at EOF for reads, and ignores all data written.
///
/// All reads from the returned reader will return <code>[Ok]\(0)</code>.
/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`]
/// and the contents of the buffer will not be inspected.
///
/// All calls to [`read`] from the returned reader will return [`Ok(0)`].
///
/// [`Ok(buf.len())`]: Ok
/// [`Ok(0)`]: Ok
///
/// [`write`]: Write::write
/// [`read`]: Read::read
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
/// ```rust
/// use std::io::{self, Write};
///
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::empty().write(&buffer).unwrap();
/// assert_eq!(num_bytes, 5);
/// ```
///
///
/// ```rust
/// use std::io::{self, Read};
///
/// let mut buffer = String::new();
Expand Down Expand Up @@ -76,20 +93,61 @@ impl Seek for Empty {
}
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Empty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Empty").finish_non_exhaustive()
}
}

impl SizeHint for Empty {
#[inline]
fn upper_bound(&self) -> Option<usize> {
Some(0)
}
}

#[stable(feature = "empty_write", since = "1.64.0")]
impl Write for Empty {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
Ok(buf.len())
}

#[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let total_len = bufs.iter().map(|b| b.len()).sum();
Ok(total_len)
}

#[inline]
fn is_write_vectored(&self) -> bool {
true
}

#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}

#[stable(feature = "empty_write", since = "1.64.0")]
impl Write for &Empty {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
Ok(buf.len())
}

#[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let total_len = bufs.iter().map(|b| b.len()).sum();
Ok(total_len)
}

#[inline]
fn is_write_vectored(&self) -> bool {
true
}

#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat()`]. Please
Expand Down Expand Up @@ -182,19 +240,20 @@ impl fmt::Debug for Repeat {

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink`]. Please
/// This struct is generally created by calling [`sink()`]. Please
/// see the documentation of [`sink()`] for more details.
#[stable(feature = "rust1", since = "1.0.0")]
#[non_exhaustive]
#[derive(Copy, Clone, Default)]
#[derive(Copy, Clone, Debug, Default)]
pub struct Sink;

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to [`write`] on the returned instance will return `Ok(buf.len())`
/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`]
/// and the contents of the buffer will not be inspected.
///
/// [`write`]: Write::write
/// [`Ok(buf.len())`]: Ok
///
/// # Examples
///
Expand Down Expand Up @@ -259,10 +318,3 @@ impl Write for &Sink {
Ok(())
}
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Sink {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Sink").finish_non_exhaustive()
}
}
13 changes: 11 additions & 2 deletions library/std/src/io/util/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fn empty_reads() {
assert_eq!(e.read(&mut []).unwrap(), 0);
assert_eq!(e.read(&mut [0]).unwrap(), 0);
assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
assert_eq!(Read::by_ref(&mut e).read(&mut [0; 1024]).unwrap(), 0);

let buf: &mut [MaybeUninit<_>] = &mut [];
let mut buf: BorrowedBuf<'_> = buf.into();
Expand All @@ -99,7 +99,7 @@ fn empty_reads() {

let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024];
let mut buf: BorrowedBuf<'_> = buf.into();
e.by_ref().read_buf(buf.unfilled()).unwrap();
Read::by_ref(&mut e).read_buf(buf.unfilled()).unwrap();
assert_eq!(buf.len(), 0);
assert_eq!(buf.init_len(), 0);
}
Expand All @@ -124,6 +124,15 @@ fn empty_seeks() {
assert!(matches!(e.seek(SeekFrom::Current(i64::MAX)), Ok(0)));
}

#[test]
fn empty_sinks() {
let mut e = empty();
assert_eq!(e.write(&[]).unwrap(), 0);
assert_eq!(e.write(&[0]).unwrap(), 1);
assert_eq!(e.write(&[0; 1024]).unwrap(), 1024);
assert_eq!(Write::by_ref(&mut e).write(&[0; 1024]).unwrap(), 1024);
}

#[test]
fn repeat_repeats() {
let mut r = repeat(4);
Expand Down