@@ -989,6 +989,68 @@ impl<W: Write> Write for LineWriter<W> {
989989 }
990990 }
991991
992+ // Vectored writes are very similar to the writes above, but adjusted for
993+ // the list of buffers that we have to write.
994+ fn write_vectored ( & mut self , bufs : & [ IoSlice < ' _ > ] ) -> io:: Result < usize > {
995+ if self . need_flush {
996+ self . flush ( ) ?;
997+ }
998+
999+ // Find the last newline, and failing that write the whole buffer
1000+ let last_newline = bufs
1001+ . iter ( )
1002+ . enumerate ( )
1003+ . rev ( )
1004+ . filter_map ( |( i, buf) | {
1005+ let pos = memchr:: memrchr ( b'\n' , buf) ?;
1006+ Some ( ( i, pos) )
1007+ } )
1008+ . next ( ) ;
1009+ let ( i, j) = match last_newline {
1010+ Some ( pair) => pair,
1011+ None => return self . inner . write_vectored ( bufs) ,
1012+ } ;
1013+ let ( prefix, suffix) = bufs. split_at ( i) ;
1014+ let ( buf, suffix) = suffix. split_at ( 1 ) ;
1015+ let buf = & buf[ 0 ] ;
1016+
1017+ // Write everything up to the last newline, flushing afterwards. Note
1018+ // that only if we finished our entire `write_vectored` do we try the
1019+ // subsequent
1020+ // `write`
1021+ let mut n = 0 ;
1022+ let prefix_amt = prefix. iter ( ) . map ( |i| i. len ( ) ) . sum ( ) ;
1023+ if prefix_amt > 0 {
1024+ n += self . inner . write_vectored ( prefix) ?;
1025+ self . need_flush = true ;
1026+ }
1027+ if n == prefix_amt {
1028+ match self . inner . write ( & buf[ ..=j] ) {
1029+ Ok ( m) => n += m,
1030+ Err ( e) if n == 0 => return Err ( e) ,
1031+ Err ( _) => return Ok ( n) ,
1032+ }
1033+ self . need_flush = true ;
1034+ }
1035+ if self . flush ( ) . is_err ( ) || n != j + 1 + prefix_amt {
1036+ return Ok ( n) ;
1037+ }
1038+
1039+ // ... and now write out everything remaining
1040+ match self . inner . write ( & buf[ j + 1 ..] ) {
1041+ Ok ( i) => n += i,
1042+ Err ( _) => return Ok ( n) ,
1043+ }
1044+
1045+ if suffix. iter ( ) . map ( |s| s. len ( ) ) . sum :: < usize > ( ) == 0 {
1046+ return Ok ( n)
1047+ }
1048+ match self . inner . write_vectored ( suffix) {
1049+ Ok ( i) => Ok ( n + i) ,
1050+ Err ( _) => Ok ( n) ,
1051+ }
1052+ }
1053+
9921054 fn flush ( & mut self ) -> io:: Result < ( ) > {
9931055 self . inner . flush ( ) ?;
9941056 self . need_flush = false ;
@@ -1015,7 +1077,7 @@ where
10151077#[ cfg( test) ]
10161078mod tests {
10171079 use crate :: io:: prelude:: * ;
1018- use crate :: io:: { self , BufReader , BufWriter , LineWriter , SeekFrom } ;
1080+ use crate :: io:: { self , BufReader , BufWriter , LineWriter , SeekFrom , IoSlice } ;
10191081 use crate :: sync:: atomic:: { AtomicUsize , Ordering } ;
10201082 use crate :: thread;
10211083
@@ -1483,4 +1545,112 @@ mod tests {
14831545
14841546 assert_eq ! ( l. write( b"a" ) . unwrap_err( ) . kind( ) , io:: ErrorKind :: Other )
14851547 }
1548+
1549+ #[ test]
1550+ fn line_vectored ( ) {
1551+ let mut a = LineWriter :: new ( Vec :: new ( ) ) ;
1552+ assert_eq ! (
1553+ a. write_vectored( & [
1554+ IoSlice :: new( & [ ] ) ,
1555+ IoSlice :: new( b"\n " ) ,
1556+ IoSlice :: new( & [ ] ) ,
1557+ IoSlice :: new( b"a" ) ,
1558+ ] )
1559+ . unwrap( ) ,
1560+ 2 ,
1561+ ) ;
1562+ assert_eq ! ( a. get_ref( ) , b"\n " ) ;
1563+
1564+ assert_eq ! (
1565+ a. write_vectored( & [
1566+ IoSlice :: new( & [ ] ) ,
1567+ IoSlice :: new( b"b" ) ,
1568+ IoSlice :: new( & [ ] ) ,
1569+ IoSlice :: new( b"a" ) ,
1570+ IoSlice :: new( & [ ] ) ,
1571+ IoSlice :: new( b"c" ) ,
1572+ ] )
1573+ . unwrap( ) ,
1574+ 3 ,
1575+ ) ;
1576+ assert_eq ! ( a. get_ref( ) , b"\n " ) ;
1577+ a. flush ( ) . unwrap ( ) ;
1578+ assert_eq ! ( a. get_ref( ) , b"\n abac" ) ;
1579+ assert_eq ! ( a. write_vectored( & [ ] ) . unwrap( ) , 0 ) ;
1580+ assert_eq ! (
1581+ a. write_vectored( & [
1582+ IoSlice :: new( & [ ] ) ,
1583+ IoSlice :: new( & [ ] ) ,
1584+ IoSlice :: new( & [ ] ) ,
1585+ IoSlice :: new( & [ ] ) ,
1586+ ] )
1587+ . unwrap( ) ,
1588+ 0 ,
1589+ ) ;
1590+ assert_eq ! ( a. write_vectored( & [ IoSlice :: new( b"a\n b" ) , ] ) . unwrap( ) , 3 ) ;
1591+ assert_eq ! ( a. get_ref( ) , b"\n abaca\n " ) ;
1592+ }
1593+
1594+ #[ test]
1595+ fn line_vectored_partial_and_errors ( ) {
1596+ enum Call {
1597+ Write { inputs : Vec < & ' static [ u8 ] > , output : io:: Result < usize > } ,
1598+ Flush { output : io:: Result < ( ) > } ,
1599+ }
1600+ struct Writer {
1601+ calls : Vec < Call > ,
1602+ }
1603+
1604+ impl Write for Writer {
1605+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
1606+ self . write_vectored ( & [ IoSlice :: new ( buf) ] )
1607+ }
1608+
1609+ fn write_vectored ( & mut self , buf : & [ IoSlice < ' _ > ] ) -> io:: Result < usize > {
1610+ match self . calls . pop ( ) . unwrap ( ) {
1611+ Call :: Write { inputs, output } => {
1612+ assert_eq ! ( inputs, buf. iter( ) . map( |b| & * * b) . collect:: <Vec <_>>( ) ) ;
1613+ output
1614+ }
1615+ _ => panic ! ( "unexpected call to write" ) ,
1616+ }
1617+ }
1618+
1619+ fn flush ( & mut self ) -> io:: Result < ( ) > {
1620+ match self . calls . pop ( ) . unwrap ( ) {
1621+ Call :: Flush { output } => output,
1622+ _ => panic ! ( "unexpected call to flush" ) ,
1623+ }
1624+ }
1625+ }
1626+
1627+ impl Drop for Writer {
1628+ fn drop ( & mut self ) {
1629+ if !thread:: panicking ( ) {
1630+ assert_eq ! ( self . calls. len( ) , 0 ) ;
1631+ }
1632+ }
1633+ }
1634+
1635+ // partial writes keep going
1636+ let mut a = LineWriter :: new ( Writer { calls : Vec :: new ( ) } ) ;
1637+ a. write_vectored ( & [ IoSlice :: new ( & [ ] ) , IoSlice :: new ( b"abc" ) ] ) . unwrap ( ) ;
1638+ a. get_mut ( ) . calls . push ( Call :: Flush { output : Ok ( ( ) ) } ) ;
1639+ a. get_mut ( ) . calls . push ( Call :: Write { inputs : vec ! [ b"bcx\n " ] , output : Ok ( 4 ) } ) ;
1640+ a. get_mut ( ) . calls . push ( Call :: Write { inputs : vec ! [ b"abcx\n " ] , output : Ok ( 1 ) } ) ;
1641+ a. write_vectored ( & [ IoSlice :: new ( b"x" ) , IoSlice :: new ( b"\n " ) ] ) . unwrap ( ) ;
1642+ a. get_mut ( ) . calls . push ( Call :: Flush { output : Ok ( ( ) ) } ) ;
1643+ a. flush ( ) . unwrap ( ) ;
1644+
1645+ // erroneous writes stop and don't write more
1646+ a. get_mut ( ) . calls . push ( Call :: Write { inputs : vec ! [ b"x\n " ] , output : Err ( err ( ) ) } ) ;
1647+ assert_eq ! ( a. write_vectored( & [ IoSlice :: new( b"x" ) , IoSlice :: new( b"\n a" ) ] ) . unwrap( ) , 2 ) ;
1648+ a. get_mut ( ) . calls . push ( Call :: Flush { output : Ok ( ( ) ) } ) ;
1649+ a. get_mut ( ) . calls . push ( Call :: Write { inputs : vec ! [ b"x\n " ] , output : Ok ( 2 ) } ) ;
1650+ a. flush ( ) . unwrap ( ) ;
1651+
1652+ fn err ( ) -> io:: Error {
1653+ io:: Error :: new ( io:: ErrorKind :: Other , "x" )
1654+ }
1655+ }
14861656}
0 commit comments