@@ -143,6 +143,7 @@ extern crate memchr;
143
143
extern crate safemem;
144
144
145
145
use std:: any:: Any ;
146
+ use std:: cell:: RefCell ;
146
147
use std:: io:: prelude:: * ;
147
148
use std:: io:: SeekFrom ;
148
149
use std:: { cmp, error, fmt, io, mem, ptr} ;
@@ -196,7 +197,7 @@ const DEFAULT_BUF_SIZE: usize = 8 * 1024;
196
197
/// [`new_ringbuf()`]: BufReader::new_ringbuf
197
198
/// [`with_capacity_ringbuf()`]: BufReader::with_capacity_ringbuf
198
199
/// [ringbufs-root]: index.html#ringbuffers--slice-deque-feature
199
- pub struct BufReader < R , P : ReaderPolicy = StdPolicy > {
200
+ pub struct BufReader < R , P = StdPolicy > {
200
201
// First field for null pointer optimization.
201
202
buf : Buffer ,
202
203
inner : R ,
@@ -265,27 +266,32 @@ impl<R> BufReader<R, StdPolicy> {
265
266
}
266
267
}
267
268
268
- impl < R , P : ReaderPolicy > BufReader < R , P > {
269
+ impl < R , P > BufReader < R , P > {
269
270
/// Apply a new `ReaderPolicy` to this `BufReader`, returning the transformed type.
270
271
pub fn set_policy < P_ : ReaderPolicy > ( self , policy : P_ ) -> BufReader < R , P_ > {
271
- BufReader {
272
+ BufReader {
272
273
inner : self . inner ,
273
274
buf : self . buf ,
274
275
policy
275
276
}
276
277
}
277
278
278
- /// Accessor for updating the `ReaderPolicy` in-place.
279
+ /// Mutate the current [ `ReaderPolicy`](policy::ReaderPolicy) in-place.
279
280
///
280
281
/// If you want to change the type, use `.set_policy()`.
281
282
pub fn policy_mut ( & mut self ) -> & mut P { & mut self . policy }
282
283
284
+ /// Inspect the current `ReaderPolicy`.
285
+ pub fn policy ( & self ) -> & P {
286
+ & self . policy
287
+ }
288
+
283
289
/// Move data to the start of the buffer, making room at the end for more
284
290
/// reading.
285
291
///
286
292
/// This is a no-op with the `*_ringbuf()` constructors (requires `slice-deque` feature).
287
293
pub fn make_room ( & mut self ) {
288
- self . buf . make_room ( ) ;
294
+ self . buf . make_room ( ) ;
289
295
}
290
296
291
297
/// Ensure room in the buffer for *at least* `additional` bytes. May not be
@@ -343,14 +349,16 @@ impl<R, P: ReaderPolicy> BufReader<R, P> {
343
349
buf : Some ( self . buf ) ,
344
350
}
345
351
}
352
+ }
346
353
354
+ impl < R , P : ReaderPolicy > BufReader < R , P > {
347
355
#[ inline]
348
356
fn should_read ( & mut self ) -> bool {
349
357
self . policy . before_read ( & mut self . buf ) . 0
350
358
}
351
359
}
352
360
353
- impl < R : Read , P : ReaderPolicy > BufReader < R , P > {
361
+ impl < R : Read , P > BufReader < R , P > {
354
362
/// Unconditionally perform a read into the buffer.
355
363
///
356
364
/// Does not invoke `ReaderPolicy` methods.
@@ -406,7 +414,7 @@ impl<R: Read, P: ReaderPolicy> BufRead for BufReader<R, P> {
406
414
}
407
415
}
408
416
409
- impl < R : fmt:: Debug , P : ReaderPolicy + fmt:: Debug > fmt:: Debug for BufReader < R , P > {
417
+ impl < R : fmt:: Debug , P : fmt:: Debug > fmt:: Debug for BufReader < R , P > {
410
418
fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
411
419
fmt. debug_struct ( "buf_redux::BufReader" )
412
420
. field ( "reader" , & self . inner )
@@ -485,7 +493,7 @@ impl<R: Seek, P: ReaderPolicy> Seek for BufReader<R, P> {
485
493
/// [`new_ringbuf()`]: BufWriter::new_ringbuf
486
494
/// [`with_capacity_ringbuf()`]: BufWriter::with_capacity_ringbuf
487
495
/// [ringbufs-root]: index.html#ringbuffers--slice-deque-feature
488
- pub struct BufWriter < W : Write , P : WriterPolicy = StdPolicy > {
496
+ pub struct BufWriter < W : Write , P = StdPolicy > {
489
497
buf : Buffer ,
490
498
inner : W ,
491
499
policy : P ,
@@ -553,7 +561,7 @@ impl<W: Write> BufWriter<W> {
553
561
}
554
562
}
555
563
556
- impl < W : Write , P : WriterPolicy > BufWriter < W , P > {
564
+ impl < W : Write , P > BufWriter < W , P > {
557
565
/// Set a new [`WriterPolicy`](policy::WriterPolicy), returning the transformed type.
558
566
pub fn set_policy < P_ : WriterPolicy > ( self , policy : P_ ) -> BufWriter < W , P_ > {
559
567
let panicked = self . panicked ;
@@ -569,6 +577,11 @@ impl<W: Write, P: WriterPolicy> BufWriter<W, P> {
569
577
& mut self . policy
570
578
}
571
579
580
+ /// Inspect the current `WriterPolicy`.
581
+ pub fn policy ( & self ) -> & P {
582
+ & self . policy
583
+ }
584
+
572
585
/// Get a reference to the inner writer.
573
586
pub fn get_ref ( & self ) -> & W {
574
587
& self . inner
@@ -607,22 +620,6 @@ impl<W: Write, P: WriterPolicy> BufWriter<W, P> {
607
620
self . buf . make_room ( ) ;
608
621
}
609
622
610
- /// Flush the buffer and unwrap, returning the inner writer on success,
611
- /// or a type wrapping `self` plus the error otherwise.
612
- pub fn into_inner ( mut self ) -> Result < W , IntoInnerError < Self > > {
613
- match self . flush ( ) {
614
- Err ( e) => Err ( IntoInnerError ( self , e) ) ,
615
- Ok ( ( ) ) => Ok ( self . into_inner_ ( ) . 0 ) ,
616
- }
617
- }
618
-
619
- /// Flush the buffer and unwrap, returning the inner writer and
620
- /// any error encountered during flushing.
621
- pub fn into_inner_with_err ( mut self ) -> ( W , Option < io:: Error > ) {
622
- let err = self . flush ( ) . err ( ) ;
623
- ( self . into_inner_ ( ) . 0 , err)
624
- }
625
-
626
623
/// Consume `self` and return both the underlying writer and the buffer
627
624
pub fn into_inner_with_buffer ( self ) -> ( W , Buffer ) {
628
625
self . into_inner_ ( )
@@ -649,6 +646,24 @@ impl<W: Write, P: WriterPolicy> BufWriter<W, P> {
649
646
}
650
647
}
651
648
649
+ impl < W : Write , P : WriterPolicy > BufWriter < W , P > {
650
+ /// Flush the buffer and unwrap, returning the inner writer on success,
651
+ /// or a type wrapping `self` plus the error otherwise.
652
+ pub fn into_inner ( mut self ) -> Result < W , IntoInnerError < Self > > {
653
+ match self . flush ( ) {
654
+ Err ( e) => Err ( IntoInnerError ( self , e) ) ,
655
+ Ok ( ( ) ) => Ok ( self . into_inner_ ( ) . 0 ) ,
656
+ }
657
+ }
658
+
659
+ /// Flush the buffer and unwrap, returning the inner writer and
660
+ /// any error encountered during flushing.
661
+ pub fn into_inner_with_err ( mut self ) -> ( W , Option < io:: Error > ) {
662
+ let err = self . flush ( ) . err ( ) ;
663
+ ( self . into_inner_ ( ) . 0 , err)
664
+ }
665
+ }
666
+
652
667
impl < W : Write , P : WriterPolicy > Write for BufWriter < W , P > {
653
668
fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
654
669
let flush_amt = self . policy . before_write ( & mut self . buf , buf. len ( ) ) . 0 ;
@@ -686,7 +701,7 @@ impl<W: Write + Seek, P: WriterPolicy> Seek for BufWriter<W, P> {
686
701
}
687
702
}
688
703
689
- impl < W : fmt:: Debug + Write , P : WriterPolicy + fmt:: Debug > fmt:: Debug for BufWriter < W , P > {
704
+ impl < W : Write + fmt:: Debug , P : fmt:: Debug > fmt:: Debug for BufWriter < W , P > {
690
705
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
691
706
f. debug_struct ( "buf_redux::BufWriter" )
692
707
. field ( "writer" , & self . inner )
@@ -696,11 +711,21 @@ impl<W: fmt::Debug + Write, P: WriterPolicy + fmt::Debug> fmt::Debug for BufWrit
696
711
}
697
712
}
698
713
699
- impl < W : Write , P : WriterPolicy > Drop for BufWriter < W , P > {
714
+
715
+ /// Attempt to flush the buffer to the underlying writer.
716
+ ///
717
+ /// If an error occurs, the thread-local handler is invoked, if one was previously
718
+ /// set by [`set_drop_err_handler`](set_drop_err_handler) for this thread.
719
+ impl < W : Write , P > Drop for BufWriter < W , P > {
700
720
fn drop ( & mut self ) {
701
721
if !self . panicked {
702
- // dtors should not panic, so we ignore a failed flush
703
- let _r = self . flush ( ) ;
722
+ // instead of ignoring a failed flush, call the handler
723
+ let buf_len = self . buf . len ( ) ;
724
+ if let Err ( err) = self . flush_buf ( buf_len) {
725
+ DROP_ERR_HANDLER . with ( |deh| {
726
+ ( * deh. borrow ( ) ) ( & mut self . inner , & mut self . buf , err)
727
+ } ) ;
728
+ }
704
729
}
705
730
}
706
731
}
@@ -801,7 +826,7 @@ impl<W: Write> Write for LineWriter<W> {
801
826
}
802
827
}
803
828
804
- impl < W : fmt:: Debug + Write > fmt:: Debug for LineWriter < W > {
829
+ impl < W : Write + fmt:: Debug > fmt:: Debug for LineWriter < W > {
805
830
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
806
831
f. debug_struct ( "buf_redux::LineWriter" )
807
832
. field ( "writer" , self . get_ref ( ) )
@@ -1239,6 +1264,25 @@ pub fn copy_buf<B: BufRead, W: Write>(b: &mut B, w: &mut W) -> io::Result<u64> {
1239
1264
Ok ( total_copied)
1240
1265
}
1241
1266
1267
+ thread_local ! (
1268
+ static DROP_ERR_HANDLER : RefCell <Box <Fn ( & mut Write , & mut Buffer , io:: Error ) >>
1269
+ = RefCell :: new( Box :: new( |_, _, _| ( ) ) )
1270
+ ) ;
1271
+
1272
+ /// Set a thread-local handler for errors thrown in `BufWriter`'s `Drop` impl.
1273
+ ///
1274
+ /// The `Write` impl, buffer (at the time of the erroring write) and IO error are provided.
1275
+ ///
1276
+ /// Replaces the previous handler. By default this is a no-op.
1277
+ ///
1278
+ /// ### Panics
1279
+ /// If called from within a handler previously provided to this function.
1280
+ pub fn set_drop_err_handler < F : ' static > ( handler : F )
1281
+ where F : Fn ( & mut Write , & mut Buffer , io:: Error )
1282
+ {
1283
+ DROP_ERR_HANDLER . with ( |deh| * deh. borrow_mut ( ) = Box :: new ( handler) )
1284
+ }
1285
+
1242
1286
#[ cfg( not( feature = "nightly" ) ) ]
1243
1287
fn init_buffer < R : Read + ?Sized > ( _r : & R , buf : & mut [ u8 ] ) {
1244
1288
// we can't trust a reader without nightly
0 commit comments