diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs
index f076ee0923c80..202c0a9a69cec 100644
--- a/library/std/src/io/util.rs
+++ b/library/std/src/io/util.rs
@@ -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 [Ok]\(0)
.
+/// 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();
@@ -76,13 +93,6 @@ 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 {
@@ -90,6 +100,54 @@ impl SizeHint for Empty {
}
}
+#[stable(feature = "empty_write", since = "1.64.0")]
+impl Write for Empty {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> io::Result {
+ Ok(buf.len())
+ }
+
+ #[inline]
+ fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result {
+ 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 {
+ Ok(buf.len())
+ }
+
+ #[inline]
+ fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result {
+ 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
@@ -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
///
@@ -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()
- }
-}
diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs
index 1baa94e64c94c..6de91e29c7707 100644
--- a/library/std/src/io/util/tests.rs
+++ b/library/std/src/io/util/tests.rs
@@ -18,7 +18,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();
@@ -40,7 +40,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);
}
@@ -65,6 +65,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);