summaryrefslogtreecommitdiffstats
path: root/library/std/src/io/buffered/bufwriter.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /library/std/src/io/buffered/bufwriter.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/std/src/io/buffered/bufwriter.rs')
-rw-r--r--library/std/src/io/buffered/bufwriter.rs140
1 files changed, 71 insertions, 69 deletions
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 14c455d4f..0f04f2911 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -67,8 +67,7 @@ use crate::ptr;
/// [`TcpStream`]: crate::net::TcpStream
/// [`flush`]: BufWriter::flush
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufWriter<W: Write> {
- inner: W,
+pub struct BufWriter<W: ?Sized + Write> {
// The buffer. Avoid using this like a normal `Vec` in common code paths.
// That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
// methods that require bounds checking or the like. This makes an enormous
@@ -78,10 +77,11 @@ pub struct BufWriter<W: Write> {
// write the buffered data a second time in BufWriter's destructor. This
// flag tells the Drop impl if it should skip the flush.
panicked: bool,
+ inner: W,
}
impl<W: Write> BufWriter<W> {
- /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB,
+ /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KiB,
/// but may change in the future.
///
/// # Examples
@@ -115,6 +115,69 @@ impl<W: Write> BufWriter<W> {
BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false }
}
+ /// Unwraps this `BufWriter<W>`, returning the underlying writer.
+ ///
+ /// The buffer is written out before returning the writer.
+ ///
+ /// # Errors
+ ///
+ /// An [`Err`] will be returned if an error occurs while flushing the buffer.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::io::BufWriter;
+ /// use std::net::TcpStream;
+ ///
+ /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
+ ///
+ /// // unwrap the TcpStream and flush the buffer
+ /// let stream = buffer.into_inner().unwrap();
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
+ match self.flush_buf() {
+ Err(e) => Err(IntoInnerError::new(self, e)),
+ Ok(()) => Ok(self.into_parts().0),
+ }
+ }
+
+ /// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but
+ /// unwritten data.
+ ///
+ /// If the underlying writer panicked, it is not known what portion of the data was written.
+ /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer
+ /// contents can still be recovered).
+ ///
+ /// `into_parts` makes no attempt to flush data and cannot fail.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::io::{BufWriter, Write};
+ ///
+ /// let mut buffer = [0u8; 10];
+ /// let mut stream = BufWriter::new(buffer.as_mut());
+ /// write!(stream, "too much data").unwrap();
+ /// stream.flush().expect_err("it doesn't fit");
+ /// let (recovered_writer, buffered_data) = stream.into_parts();
+ /// assert_eq!(recovered_writer.len(), 0);
+ /// assert_eq!(&buffered_data.unwrap(), b"ata");
+ /// ```
+ #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
+ pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
+ let buf = mem::take(&mut self.buf);
+ let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
+
+ // SAFETY: forget(self) prevents double dropping inner
+ let inner = unsafe { ptr::read(&self.inner) };
+ mem::forget(self);
+
+ (inner, buf)
+ }
+}
+
+impl<W: ?Sized + Write> BufWriter<W> {
/// Send data in our local buffer into the inner writer, looping as
/// necessary until either it's all been sent or an error occurs.
///
@@ -284,67 +347,6 @@ impl<W: Write> BufWriter<W> {
self.buf.capacity()
}
- /// Unwraps this `BufWriter<W>`, returning the underlying writer.
- ///
- /// The buffer is written out before returning the writer.
- ///
- /// # Errors
- ///
- /// An [`Err`] will be returned if an error occurs while flushing the buffer.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// use std::io::BufWriter;
- /// use std::net::TcpStream;
- ///
- /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
- ///
- /// // unwrap the TcpStream and flush the buffer
- /// let stream = buffer.into_inner().unwrap();
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
- match self.flush_buf() {
- Err(e) => Err(IntoInnerError::new(self, e)),
- Ok(()) => Ok(self.into_parts().0),
- }
- }
-
- /// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but
- /// unwritten data.
- ///
- /// If the underlying writer panicked, it is not known what portion of the data was written.
- /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer
- /// contents can still be recovered).
- ///
- /// `into_parts` makes no attempt to flush data and cannot fail.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::io::{BufWriter, Write};
- ///
- /// let mut buffer = [0u8; 10];
- /// let mut stream = BufWriter::new(buffer.as_mut());
- /// write!(stream, "too much data").unwrap();
- /// stream.flush().expect_err("it doesn't fit");
- /// let (recovered_writer, buffered_data) = stream.into_parts();
- /// assert_eq!(recovered_writer.len(), 0);
- /// assert_eq!(&buffered_data.unwrap(), b"ata");
- /// ```
- #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
- pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
- let buf = mem::take(&mut self.buf);
- let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
-
- // SAFETY: forget(self) prevents double dropping inner
- let inner = unsafe { ptr::read(&self.inner) };
- mem::forget(self);
-
- (inner, buf)
- }
-
// Ensure this function does not get inlined into `write`, so that it
// remains inlineable and its common path remains as short as possible.
// If this function ends up being called frequently relative to `write`,
@@ -511,7 +513,7 @@ impl fmt::Debug for WriterPanicked {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write> Write for BufWriter<W> {
+impl<W: ?Sized + Write> Write for BufWriter<W> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
// Use < instead of <= to avoid a needless trip through the buffer in some cases.
@@ -640,20 +642,20 @@ impl<W: Write> Write for BufWriter<W> {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write> fmt::Debug for BufWriter<W>
+impl<W: ?Sized + Write> fmt::Debug for BufWriter<W>
where
W: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("BufWriter")
- .field("writer", &self.inner)
+ .field("writer", &&self.inner)
.field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
.finish()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write + Seek> Seek for BufWriter<W> {
+impl<W: ?Sized + Write + Seek> Seek for BufWriter<W> {
/// Seek to the offset, in bytes, in the underlying writer.
///
/// Seeking always writes out the internal buffer before seeking.
@@ -664,7 +666,7 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Write> Drop for BufWriter<W> {
+impl<W: ?Sized + Write> Drop for BufWriter<W> {
fn drop(&mut self) {
if !self.panicked {
// dtors should not panic, so we ignore a failed flush