@@ -67,8 +67,7 @@ use crate::ptr;
6767/// [`TcpStream`]: crate::net::TcpStream
6868/// [`flush`]: BufWriter::flush
6969#[ stable( feature = "rust1" , since = "1.0.0" ) ]
70- pub struct BufWriter < W : Write > {
71- inner : W ,
70+ pub struct BufWriter < W : ?Sized + Write > {
7271 // The buffer. Avoid using this like a normal `Vec` in common code paths.
7372 // That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
7473 // methods that require bounds checking or the like. This makes an enormous
@@ -78,6 +77,7 @@ pub struct BufWriter<W: Write> {
7877 // write the buffered data a second time in BufWriter's destructor. This
7978 // flag tells the Drop impl if it should skip the flush.
8079 panicked : bool ,
80+ inner : W ,
8181}
8282
8383impl < W : Write > BufWriter < W > {
@@ -115,6 +115,69 @@ impl<W: Write> BufWriter<W> {
115115 BufWriter { inner, buf : Vec :: with_capacity ( capacity) , panicked : false }
116116 }
117117
118+ /// Unwraps this `BufWriter<W>`, returning the underlying writer.
119+ ///
120+ /// The buffer is written out before returning the writer.
121+ ///
122+ /// # Errors
123+ ///
124+ /// An [`Err`] will be returned if an error occurs while flushing the buffer.
125+ ///
126+ /// # Examples
127+ ///
128+ /// ```no_run
129+ /// use std::io::BufWriter;
130+ /// use std::net::TcpStream;
131+ ///
132+ /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
133+ ///
134+ /// // unwrap the TcpStream and flush the buffer
135+ /// let stream = buffer.into_inner().unwrap();
136+ /// ```
137+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
138+ pub fn into_inner ( mut self ) -> Result < W , IntoInnerError < BufWriter < W > > > {
139+ match self . flush_buf ( ) {
140+ Err ( e) => Err ( IntoInnerError :: new ( self , e) ) ,
141+ Ok ( ( ) ) => Ok ( self . into_parts ( ) . 0 ) ,
142+ }
143+ }
144+
145+ /// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but
146+ /// unwritten data.
147+ ///
148+ /// If the underlying writer panicked, it is not known what portion of the data was written.
149+ /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer
150+ /// contents can still be recovered).
151+ ///
152+ /// `into_parts` makes no attempt to flush data and cannot fail.
153+ ///
154+ /// # Examples
155+ ///
156+ /// ```
157+ /// use std::io::{BufWriter, Write};
158+ ///
159+ /// let mut buffer = [0u8; 10];
160+ /// let mut stream = BufWriter::new(buffer.as_mut());
161+ /// write!(stream, "too much data").unwrap();
162+ /// stream.flush().expect_err("it doesn't fit");
163+ /// let (recovered_writer, buffered_data) = stream.into_parts();
164+ /// assert_eq!(recovered_writer.len(), 0);
165+ /// assert_eq!(&buffered_data.unwrap(), b"ata");
166+ /// ```
167+ #[ stable( feature = "bufwriter_into_parts" , since = "1.56.0" ) ]
168+ pub fn into_parts ( mut self ) -> ( W , Result < Vec < u8 > , WriterPanicked > ) {
169+ let buf = mem:: take ( & mut self . buf ) ;
170+ let buf = if !self . panicked { Ok ( buf) } else { Err ( WriterPanicked { buf } ) } ;
171+
172+ // SAFETY: forget(self) prevents double dropping inner
173+ let inner = unsafe { ptr:: read ( & self . inner ) } ;
174+ mem:: forget ( self ) ;
175+
176+ ( inner, buf)
177+ }
178+ }
179+
180+ impl < W : ?Sized + Write > BufWriter < W > {
118181 /// Send data in our local buffer into the inner writer, looping as
119182 /// necessary until either it's all been sent or an error occurs.
120183 ///
@@ -284,67 +347,6 @@ impl<W: Write> BufWriter<W> {
284347 self . buf . capacity ( )
285348 }
286349
287- /// Unwraps this `BufWriter<W>`, returning the underlying writer.
288- ///
289- /// The buffer is written out before returning the writer.
290- ///
291- /// # Errors
292- ///
293- /// An [`Err`] will be returned if an error occurs while flushing the buffer.
294- ///
295- /// # Examples
296- ///
297- /// ```no_run
298- /// use std::io::BufWriter;
299- /// use std::net::TcpStream;
300- ///
301- /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
302- ///
303- /// // unwrap the TcpStream and flush the buffer
304- /// let stream = buffer.into_inner().unwrap();
305- /// ```
306- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
307- pub fn into_inner ( mut self ) -> Result < W , IntoInnerError < BufWriter < W > > > {
308- match self . flush_buf ( ) {
309- Err ( e) => Err ( IntoInnerError :: new ( self , e) ) ,
310- Ok ( ( ) ) => Ok ( self . into_parts ( ) . 0 ) ,
311- }
312- }
313-
314- /// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but
315- /// unwritten data.
316- ///
317- /// If the underlying writer panicked, it is not known what portion of the data was written.
318- /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer
319- /// contents can still be recovered).
320- ///
321- /// `into_parts` makes no attempt to flush data and cannot fail.
322- ///
323- /// # Examples
324- ///
325- /// ```
326- /// use std::io::{BufWriter, Write};
327- ///
328- /// let mut buffer = [0u8; 10];
329- /// let mut stream = BufWriter::new(buffer.as_mut());
330- /// write!(stream, "too much data").unwrap();
331- /// stream.flush().expect_err("it doesn't fit");
332- /// let (recovered_writer, buffered_data) = stream.into_parts();
333- /// assert_eq!(recovered_writer.len(), 0);
334- /// assert_eq!(&buffered_data.unwrap(), b"ata");
335- /// ```
336- #[ stable( feature = "bufwriter_into_parts" , since = "1.56.0" ) ]
337- pub fn into_parts ( mut self ) -> ( W , Result < Vec < u8 > , WriterPanicked > ) {
338- let buf = mem:: take ( & mut self . buf ) ;
339- let buf = if !self . panicked { Ok ( buf) } else { Err ( WriterPanicked { buf } ) } ;
340-
341- // SAFETY: forget(self) prevents double dropping inner
342- let inner = unsafe { ptr:: read ( & self . inner ) } ;
343- mem:: forget ( self ) ;
344-
345- ( inner, buf)
346- }
347-
348350 // Ensure this function does not get inlined into `write`, so that it
349351 // remains inlineable and its common path remains as short as possible.
350352 // If this function ends up being called frequently relative to `write`,
@@ -511,7 +513,7 @@ impl fmt::Debug for WriterPanicked {
511513}
512514
513515#[ stable( feature = "rust1" , since = "1.0.0" ) ]
514- impl < W : Write > Write for BufWriter < W > {
516+ impl < W : ? Sized + Write > Write for BufWriter < W > {
515517 #[ inline]
516518 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
517519 // 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> {
640642}
641643
642644#[ stable( feature = "rust1" , since = "1.0.0" ) ]
643- impl < W : Write > fmt:: Debug for BufWriter < W >
645+ impl < W : ? Sized + Write > fmt:: Debug for BufWriter < W >
644646where
645647 W : fmt:: Debug ,
646648{
647649 fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
648650 fmt. debug_struct ( "BufWriter" )
649- . field ( "writer" , & self . inner )
651+ . field ( "writer" , & & self . inner )
650652 . field ( "buffer" , & format_args ! ( "{}/{}" , self . buf. len( ) , self . buf. capacity( ) ) )
651653 . finish ( )
652654 }
653655}
654656
655657#[ stable( feature = "rust1" , since = "1.0.0" ) ]
656- impl < W : Write + Seek > Seek for BufWriter < W > {
658+ impl < W : ? Sized + Write + Seek > Seek for BufWriter < W > {
657659 /// Seek to the offset, in bytes, in the underlying writer.
658660 ///
659661 /// Seeking always writes out the internal buffer before seeking.
@@ -664,7 +666,7 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
664666}
665667
666668#[ stable( feature = "rust1" , since = "1.0.0" ) ]
667- impl < W : Write > Drop for BufWriter < W > {
669+ impl < W : ? Sized + Write > Drop for BufWriter < W > {
668670 fn drop ( & mut self ) {
669671 if !self . panicked {
670672 // dtors should not panic, so we ignore a failed flush
0 commit comments