@@ -652,6 +652,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
652
652
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
653
653
pub struct LineWriter < W : Write > {
654
654
inner : BufWriter < W > ,
655
+ need_flush : bool ,
655
656
}
656
657
657
658
impl < W : Write > LineWriter < W > {
@@ -692,7 +693,10 @@ impl<W: Write> LineWriter<W> {
692
693
/// ```
693
694
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
694
695
pub fn with_capacity ( cap : usize , inner : W ) -> LineWriter < W > {
695
- LineWriter { inner : BufWriter :: with_capacity ( cap, inner) }
696
+ LineWriter {
697
+ inner : BufWriter :: with_capacity ( cap, inner) ,
698
+ need_flush : false ,
699
+ }
696
700
}
697
701
698
702
/// Gets a reference to the underlying writer.
@@ -759,28 +763,57 @@ impl<W: Write> LineWriter<W> {
759
763
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
760
764
pub fn into_inner ( self ) -> Result < W , IntoInnerError < LineWriter < W > > > {
761
765
self . inner . into_inner ( ) . map_err ( |IntoInnerError ( buf, e) | {
762
- IntoInnerError ( LineWriter { inner : buf } , e)
766
+ IntoInnerError ( LineWriter {
767
+ inner : buf,
768
+ need_flush : false ,
769
+ } , e)
763
770
} )
764
771
}
765
772
}
766
773
767
774
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
768
775
impl < W : Write > Write for LineWriter < W > {
769
776
fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
770
- match memchr:: memrchr ( b'\n' , buf) {
771
- Some ( i) => {
772
- let n = self . inner . write ( & buf[ ..i + 1 ] ) ?;
773
- if n != i + 1 || self . inner . flush ( ) . is_err ( ) {
774
- // Do not return errors on partial writes.
775
- return Ok ( n) ;
776
- }
777
- self . inner . write ( & buf[ i + 1 ..] ) . map ( |i| n + i)
778
- }
779
- None => self . inner . write ( buf) ,
777
+ if self . need_flush {
778
+ self . flush ( ) ?;
779
+ }
780
+
781
+ // Find the last newline character in the buffer provided. If found then
782
+ // we're going to write all the data up to that point and then flush,
783
+ // otherewise we just write the whole block to the underlying writer.
784
+ let i = match memchr:: memrchr ( b'\n' , buf) {
785
+ Some ( i) => i,
786
+ None => return self . inner . write ( buf) ,
787
+ } ;
788
+
789
+
790
+ // Ok, we're going to write a partial amount of the data given first
791
+ // followed by flushing the newline. After we've successfully written
792
+ // some data then we *must* report that we wrote that data, so future
793
+ // errors are ignored. We set our internal `need_flush` flag, though, in
794
+ // case flushing fails and we need to try it first next time.
795
+ let n = self . inner . write ( & buf[ ..i + 1 ] ) ?;
796
+ self . need_flush = true ;
797
+ if self . flush ( ) . is_err ( ) || n != i + 1 {
798
+ return Ok ( n)
799
+ }
800
+
801
+ // At this point we successfully wrote `i + 1` bytes and flushed it out,
802
+ // meaning that the entire line is now flushed out on the screen. While
803
+ // we can attempt to finish writing the rest of the data provided.
804
+ // Remember though that we ignore errors here as we've successfully
805
+ // written data, so we need to report that.
806
+ match self . inner . write ( & buf[ i + 1 ..] ) {
807
+ Ok ( i) => Ok ( n + i) ,
808
+ Err ( _) => Ok ( n) ,
780
809
}
781
810
}
782
811
783
- fn flush ( & mut self ) -> io:: Result < ( ) > { self . inner . flush ( ) }
812
+ fn flush ( & mut self ) -> io:: Result < ( ) > {
813
+ self . inner . flush ( ) ?;
814
+ self . need_flush = false ;
815
+ Ok ( ( ) )
816
+ }
784
817
}
785
818
786
819
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1153,4 +1186,44 @@ mod tests {
1153
1186
BufWriter :: new ( io:: sink ( ) )
1154
1187
} ) ;
1155
1188
}
1189
+
1190
+ struct AcceptOneThenFail {
1191
+ written : bool ,
1192
+ flushed : bool ,
1193
+ }
1194
+
1195
+ impl Write for AcceptOneThenFail {
1196
+ fn write ( & mut self , data : & [ u8 ] ) -> io:: Result < usize > {
1197
+ if !self . written {
1198
+ assert_eq ! ( data, b"a\n b\n " ) ;
1199
+ self . written = true ;
1200
+ Ok ( data. len ( ) )
1201
+ } else {
1202
+ Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "test" ) )
1203
+ }
1204
+ }
1205
+
1206
+ fn flush ( & mut self ) -> io:: Result < ( ) > {
1207
+ assert ! ( self . written) ;
1208
+ assert ! ( !self . flushed) ;
1209
+ self . flushed = true ;
1210
+ Err ( io:: Error :: new ( io:: ErrorKind :: Other , "test" ) )
1211
+ }
1212
+ }
1213
+
1214
+ #[ test]
1215
+ fn erroneous_flush_retried ( ) {
1216
+ let a = AcceptOneThenFail {
1217
+ written : false ,
1218
+ flushed : false ,
1219
+ } ;
1220
+
1221
+ let mut l = LineWriter :: new ( a) ;
1222
+ assert_eq ! ( l. write( b"a\n b\n a" ) . unwrap( ) , 4 ) ;
1223
+ assert ! ( l. get_ref( ) . written) ;
1224
+ assert ! ( l. get_ref( ) . flushed) ;
1225
+ l. get_mut ( ) . flushed = false ;
1226
+
1227
+ assert_eq ! ( l. write( b"a" ) . unwrap_err( ) . kind( ) , io:: ErrorKind :: Other )
1228
+ }
1156
1229
}
0 commit comments