|
| 1 | +use crate::error; |
1 | 2 | use crate::fmt;
|
2 | 3 | use crate::io::{
|
3 | 4 | self, Error, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
|
4 | 5 | };
|
| 6 | +use crate::mem; |
5 | 7 |
|
6 | 8 | /// Wraps a writer and buffers its output.
|
7 | 9 | ///
|
@@ -287,6 +289,103 @@ impl<W: Write> BufWriter<W> {
|
287 | 289 | Ok(()) => Ok(self.inner.take().unwrap()),
|
288 | 290 | }
|
289 | 291 | }
|
| 292 | + |
| 293 | + /// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but |
| 294 | + /// unwritten data. |
| 295 | + /// |
| 296 | + /// If the underlying writer panicked, it is not known what portion of the data was written. |
| 297 | + /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer |
| 298 | + /// contents can still be recovered). |
| 299 | + /// |
| 300 | + /// `into_raw_parts` makes no attempt to flush data and cannot fail. |
| 301 | + /// |
| 302 | + /// # Examples |
| 303 | + /// |
| 304 | + /// ``` |
| 305 | + /// #![feature(bufwriter_into_raw_parts)] |
| 306 | + /// use std::io::{BufWriter, Write}; |
| 307 | + /// |
| 308 | + /// let mut buffer = [0u8; 10]; |
| 309 | + /// let mut stream = BufWriter::new(buffer.as_mut()); |
| 310 | + /// write!(stream, "too much data").unwrap(); |
| 311 | + /// stream.flush().expect_err("it doesn't fit"); |
| 312 | + /// let (recovered_writer, buffered_data) = stream.into_raw_parts(); |
| 313 | + /// assert_eq!(recovered_writer.len(), 0); |
| 314 | + /// assert_eq!(&buffered_data.unwrap(), b"ata"); |
| 315 | + /// ``` |
| 316 | + #[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] |
| 317 | + pub fn into_raw_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) { |
| 318 | + let buf = mem::take(&mut self.buf); |
| 319 | + let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; |
| 320 | + (self.inner.take().unwrap(), buf) |
| 321 | + } |
| 322 | +} |
| 323 | + |
| 324 | +#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] |
| 325 | +/// Error returned for the buffered data from `BufWriter::into_raw_parts`, when the underlying |
| 326 | +/// writer has previously panicked. Contains the (possibly partly written) buffered data. |
| 327 | +/// |
| 328 | +/// # Example |
| 329 | +/// |
| 330 | +/// ``` |
| 331 | +/// #![feature(bufwriter_into_raw_parts)] |
| 332 | +/// use std::io::{self, BufWriter, Write}; |
| 333 | +/// use std::panic::{catch_unwind, AssertUnwindSafe}; |
| 334 | +/// |
| 335 | +/// struct PanickingWriter; |
| 336 | +/// impl Write for PanickingWriter { |
| 337 | +/// fn write(&mut self, buf: &[u8]) -> io::Result<usize> { panic!() } |
| 338 | +/// fn flush(&mut self) -> io::Result<()> { panic!() } |
| 339 | +/// } |
| 340 | +/// |
| 341 | +/// let mut stream = BufWriter::new(PanickingWriter); |
| 342 | +/// write!(stream, "some data").unwrap(); |
| 343 | +/// let result = catch_unwind(AssertUnwindSafe(|| { |
| 344 | +/// stream.flush().unwrap() |
| 345 | +/// })); |
| 346 | +/// assert!(result.is_err()); |
| 347 | +/// let (recovered_writer, buffered_data) = stream.into_raw_parts(); |
| 348 | +/// assert!(matches!(recovered_writer, PanickingWriter)); |
| 349 | +/// assert_eq!(buffered_data.unwrap_err().into_inner(), b"some data"); |
| 350 | +/// ``` |
| 351 | +pub struct WriterPanicked { |
| 352 | + buf: Vec<u8>, |
| 353 | +} |
| 354 | + |
| 355 | +impl WriterPanicked { |
| 356 | + /// Returns the perhaps-unwritten data. Some of this data may have been written by the |
| 357 | + /// panicking call(s) to the underlying writer, so simply writing it again is not a good idea. |
| 358 | + #[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] |
| 359 | + pub fn into_inner(self) -> Vec<u8> { |
| 360 | + self.buf |
| 361 | + } |
| 362 | + |
| 363 | + const DESCRIPTION: &'static str = |
| 364 | + "BufWriter inner writer panicked, what data remains unwritten is not known"; |
| 365 | +} |
| 366 | + |
| 367 | +#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] |
| 368 | +impl error::Error for WriterPanicked { |
| 369 | + #[allow(deprecated, deprecated_in_future)] |
| 370 | + fn description(&self) -> &str { |
| 371 | + Self::DESCRIPTION |
| 372 | + } |
| 373 | +} |
| 374 | + |
| 375 | +#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] |
| 376 | +impl fmt::Display for WriterPanicked { |
| 377 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 378 | + write!(f, "{}", Self::DESCRIPTION) |
| 379 | + } |
| 380 | +} |
| 381 | + |
| 382 | +#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] |
| 383 | +impl fmt::Debug for WriterPanicked { |
| 384 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 385 | + f.debug_struct("WriterPanicked") |
| 386 | + .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity())) |
| 387 | + .finish() |
| 388 | + } |
290 | 389 | }
|
291 | 390 |
|
292 | 391 | #[stable(feature = "rust1", since = "1.0.0")]
|
|
0 commit comments