@@ -652,6 +652,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
652652#[ stable( feature = "rust1" , since = "1.0.0" ) ]
653653pub struct LineWriter < W : Write > {
654654 inner : BufWriter < W > ,
655+ need_flush : bool ,
655656}
656657
657658impl < W : Write > LineWriter < W > {
@@ -692,7 +693,10 @@ impl<W: Write> LineWriter<W> {
692693 /// ```
693694 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
694695 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+ }
696700 }
697701
698702 /// Gets a reference to the underlying writer.
@@ -759,28 +763,57 @@ impl<W: Write> LineWriter<W> {
759763 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
760764 pub fn into_inner ( self ) -> Result < W , IntoInnerError < LineWriter < W > > > {
761765 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)
763770 } )
764771 }
765772}
766773
767774#[ stable( feature = "rust1" , since = "1.0.0" ) ]
768775impl < W : Write > Write for LineWriter < W > {
769776 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) ,
780809 }
781810 }
782811
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+ }
784817}
785818
786819#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1153,4 +1186,44 @@ mod tests {
11531186 BufWriter :: new ( io:: sink ( ) )
11541187 } ) ;
11551188 }
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+ }
11561229}
0 commit comments