@@ -67,8 +67,7 @@ use crate::ptr;
67
67
/// [`TcpStream`]: crate::net::TcpStream
68
68
/// [`flush`]: BufWriter::flush
69
69
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
70
- pub struct BufWriter < W : Write > {
71
- inner : W ,
70
+ pub struct BufWriter < W : ?Sized + Write > {
72
71
// The buffer. Avoid using this like a normal `Vec` in common code paths.
73
72
// That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
74
73
// methods that require bounds checking or the like. This makes an enormous
@@ -78,6 +77,7 @@ pub struct BufWriter<W: Write> {
78
77
// write the buffered data a second time in BufWriter's destructor. This
79
78
// flag tells the Drop impl if it should skip the flush.
80
79
panicked : bool ,
80
+ inner : W ,
81
81
}
82
82
83
83
impl < W : Write > BufWriter < W > {
@@ -115,6 +115,69 @@ impl<W: Write> BufWriter<W> {
115
115
BufWriter { inner, buf : Vec :: with_capacity ( capacity) , panicked : false }
116
116
}
117
117
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 > {
118
181
/// Send data in our local buffer into the inner writer, looping as
119
182
/// necessary until either it's all been sent or an error occurs.
120
183
///
@@ -284,67 +347,6 @@ impl<W: Write> BufWriter<W> {
284
347
self . buf . capacity ( )
285
348
}
286
349
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
-
348
350
// Ensure this function does not get inlined into `write`, so that it
349
351
// remains inlineable and its common path remains as short as possible.
350
352
// If this function ends up being called frequently relative to `write`,
@@ -511,7 +513,7 @@ impl fmt::Debug for WriterPanicked {
511
513
}
512
514
513
515
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
514
- impl < W : Write > Write for BufWriter < W > {
516
+ impl < W : ? Sized + Write > Write for BufWriter < W > {
515
517
#[ inline]
516
518
fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
517
519
// 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> {
640
642
}
641
643
642
644
#[ 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 >
644
646
where
645
647
W : fmt:: Debug ,
646
648
{
647
649
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
648
650
fmt. debug_struct ( "BufWriter" )
649
- . field ( "writer" , & self . inner )
651
+ . field ( "writer" , & & self . inner )
650
652
. field ( "buffer" , & format_args ! ( "{}/{}" , self . buf. len( ) , self . buf. capacity( ) ) )
651
653
. finish ( )
652
654
}
653
655
}
654
656
655
657
#[ 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 > {
657
659
/// Seek to the offset, in bytes, in the underlying writer.
658
660
///
659
661
/// Seeking always writes out the internal buffer before seeking.
@@ -664,7 +666,7 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
664
666
}
665
667
666
668
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
667
- impl < W : Write > Drop for BufWriter < W > {
669
+ impl < W : ? Sized + Write > Drop for BufWriter < W > {
668
670
fn drop ( & mut self ) {
669
671
if !self . panicked {
670
672
// dtors should not panic, so we ignore a failed flush
0 commit comments