@@ -751,7 +751,8 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
751
751
///
752
752
/// Seeking always writes out the internal buffer before seeking.
753
753
fn seek ( & mut self , pos : SeekFrom ) -> io:: Result < u64 > {
754
- self . flush_buf ( ) . and_then ( |_| self . get_mut ( ) . seek ( pos) )
754
+ self . flush_buf ( ) ?;
755
+ self . get_mut ( ) . seek ( pos)
755
756
}
756
757
}
757
758
@@ -1862,12 +1863,13 @@ mod tests {
1862
1863
IoSlice :: new( b"a" ) ,
1863
1864
] )
1864
1865
. unwrap( ) ,
1865
- 2 ,
1866
+ 1 ,
1866
1867
) ;
1867
1868
assert_eq ! ( a. get_ref( ) , b"\n " ) ;
1868
1869
1869
1870
assert_eq ! (
1870
1871
a. write_vectored( & [
1872
+ IoSlice :: new( b"a" ) ,
1871
1873
IoSlice :: new( & [ ] ) ,
1872
1874
IoSlice :: new( b"b" ) ,
1873
1875
IoSlice :: new( & [ ] ) ,
@@ -1876,7 +1878,7 @@ mod tests {
1876
1878
IoSlice :: new( b"c" ) ,
1877
1879
] )
1878
1880
. unwrap( ) ,
1879
- 3 ,
1881
+ 4 ,
1880
1882
) ;
1881
1883
assert_eq ! ( a. get_ref( ) , b"\n " ) ;
1882
1884
a. flush ( ) . unwrap ( ) ;
@@ -1893,17 +1895,21 @@ mod tests {
1893
1895
0 ,
1894
1896
) ;
1895
1897
assert_eq ! ( a. write_vectored( & [ IoSlice :: new( b"a\n b" ) , ] ) . unwrap( ) , 3 ) ;
1896
- assert_eq ! ( a. get_ref( ) , b"\n abaca\n " ) ;
1898
+ assert_eq ! ( a. get_ref( ) , b"\n abaca\n b " ) ;
1897
1899
}
1898
1900
1899
1901
#[ test]
1900
1902
fn line_vectored_partial_and_errors ( ) {
1903
+ use crate :: collections:: VecDeque ;
1904
+
1901
1905
enum Call {
1902
1906
Write { inputs : Vec < & ' static [ u8 ] > , output : io:: Result < usize > } ,
1903
1907
Flush { output : io:: Result < ( ) > } ,
1904
1908
}
1909
+
1910
+ #[ derive( Default ) ]
1905
1911
struct Writer {
1906
- calls : Vec < Call > ,
1912
+ calls : VecDeque < Call > ,
1907
1913
}
1908
1914
1909
1915
impl Write for Writer {
@@ -1912,19 +1918,23 @@ mod tests {
1912
1918
}
1913
1919
1914
1920
fn write_vectored ( & mut self , buf : & [ IoSlice < ' _ > ] ) -> io:: Result < usize > {
1915
- match self . calls . pop ( ) . unwrap ( ) {
1921
+ match self . calls . pop_front ( ) . expect ( "unexpected call to write" ) {
1916
1922
Call :: Write { inputs, output } => {
1917
1923
assert_eq ! ( inputs, buf. iter( ) . map( |b| & * * b) . collect:: <Vec <_>>( ) ) ;
1918
1924
output
1919
1925
}
1920
- _ => panic ! ( "unexpected call to write" ) ,
1926
+ Call :: Flush { .. } => panic ! ( "unexpected call to write; expected a flush " ) ,
1921
1927
}
1922
1928
}
1923
1929
1930
+ fn is_write_vectored ( & self ) -> bool {
1931
+ true
1932
+ }
1933
+
1924
1934
fn flush ( & mut self ) -> io:: Result < ( ) > {
1925
- match self . calls . pop ( ) . unwrap ( ) {
1935
+ match self . calls . pop_front ( ) . expect ( "Unexpected call to flush" ) {
1926
1936
Call :: Flush { output } => output,
1927
- _ => panic ! ( "unexpected call to flush" ) ,
1937
+ Call :: Write { .. } => panic ! ( "unexpected call to flush; expected a write " ) ,
1928
1938
}
1929
1939
}
1930
1940
}
@@ -1938,27 +1948,64 @@ mod tests {
1938
1948
}
1939
1949
1940
1950
// partial writes keep going
1941
- let mut a = LineWriter :: new ( Writer { calls : Vec :: new ( ) } ) ;
1951
+ let mut a = LineWriter :: new ( Writer :: default ( ) ) ;
1942
1952
a. write_vectored ( & [ IoSlice :: new ( & [ ] ) , IoSlice :: new ( b"abc" ) ] ) . unwrap ( ) ;
1943
- a. get_mut ( ) . calls . push ( Call :: Flush { output : Ok ( ( ) ) } ) ;
1944
- a. get_mut ( ) . calls . push ( Call :: Write { inputs : vec ! [ b"bcx\n " ] , output : Ok ( 4 ) } ) ;
1945
- a. get_mut ( ) . calls . push ( Call :: Write { inputs : vec ! [ b"abcx\n " ] , output : Ok ( 1 ) } ) ;
1953
+
1954
+ a. get_mut ( ) . calls . push_back ( Call :: Write { inputs : vec ! [ b"abc" ] , output : Ok ( 1 ) } ) ;
1955
+ a. get_mut ( ) . calls . push_back ( Call :: Write { inputs : vec ! [ b"bc" ] , output : Ok ( 2 ) } ) ;
1956
+ a. get_mut ( ) . calls . push_back ( Call :: Write { inputs : vec ! [ b"x" , b"\n " ] , output : Ok ( 2 ) } ) ;
1957
+
1946
1958
a. write_vectored ( & [ IoSlice :: new ( b"x" ) , IoSlice :: new ( b"\n " ) ] ) . unwrap ( ) ;
1947
- a. get_mut ( ) . calls . push ( Call :: Flush { output : Ok ( ( ) ) } ) ;
1959
+
1960
+ a. get_mut ( ) . calls . push_back ( Call :: Flush { output : Ok ( ( ) ) } ) ;
1948
1961
a. flush ( ) . unwrap ( ) ;
1949
1962
1950
1963
// erroneous writes stop and don't write more
1951
- a. get_mut ( ) . calls . push ( Call :: Write { inputs : vec ! [ b"x\n " ] , output : Err ( err ( ) ) } ) ;
1952
- assert_eq ! ( a. write_vectored( & [ IoSlice :: new( b"x" ) , IoSlice :: new( b"\n a" ) ] ) . unwrap( ) , 2 ) ;
1953
- a. get_mut ( ) . calls . push ( Call :: Flush { output : Ok ( ( ) ) } ) ;
1954
- a. get_mut ( ) . calls . push ( Call :: Write { inputs : vec ! [ b"x\n " ] , output : Ok ( 2 ) } ) ;
1964
+ a. get_mut ( ) . calls . push_back ( Call :: Write { inputs : vec ! [ b"x" , b"\n a" ] , output : Err ( err ( ) ) } ) ;
1965
+ a. get_mut ( ) . calls . push_back ( Call :: Flush { output : Ok ( ( ) ) } ) ;
1966
+ assert ! ( a. write_vectored( & [ IoSlice :: new( b"x" ) , IoSlice :: new( b"\n a" ) ] ) . is_err( ) ) ;
1955
1967
a. flush ( ) . unwrap ( ) ;
1956
1968
1957
1969
fn err ( ) -> io:: Error {
1958
1970
io:: Error :: new ( io:: ErrorKind :: Other , "x" )
1959
1971
}
1960
1972
}
1961
1973
1974
+ /// Test that, in cases where vectored writing is not enabled, the
1975
+ /// LineWriter uses the normal `write` call, which more-corectly handles
1976
+ /// partial lines
1977
+ #[ test]
1978
+ fn line_vectored_ignored ( ) {
1979
+ let writer = ProgrammableSink :: default ( ) ;
1980
+ let mut writer = LineWriter :: new ( writer) ;
1981
+
1982
+ let content = [
1983
+ IoSlice :: new ( b"Line 1\n Line" ) ,
1984
+ IoSlice :: new ( b" 2\n Line 3\n L" ) ,
1985
+ IoSlice :: new ( b"ine 4" ) ,
1986
+ IoSlice :: new ( b"\n Line 5\n " ) ,
1987
+ ] ;
1988
+
1989
+ let count = writer. write_vectored ( & content) . unwrap ( ) ;
1990
+ assert_eq ! ( count, 11 ) ;
1991
+ assert_eq ! ( & writer. get_ref( ) . buffer, b"Line 1\n " ) ;
1992
+
1993
+ let count = writer. write_vectored ( & content[ 1 ..] ) . unwrap ( ) ;
1994
+ assert_eq ! ( count, 11 ) ;
1995
+ assert_eq ! ( & writer. get_ref( ) . buffer, b"Line 1\n Line 2\n Line 3\n " ) ;
1996
+
1997
+ let count = writer. write_vectored ( & content[ 2 ..] ) . unwrap ( ) ;
1998
+ assert_eq ! ( count, 5 ) ;
1999
+ assert_eq ! ( & writer. get_ref( ) . buffer, b"Line 1\n Line 2\n Line 3\n " ) ;
2000
+
2001
+ let count = writer. write_vectored ( & content[ 3 ..] ) . unwrap ( ) ;
2002
+ assert_eq ! ( count, 8 ) ;
2003
+ assert_eq ! (
2004
+ writer. get_ref( ) . buffer. as_slice( ) ,
2005
+ b"Line 1\n Line 2\n Line 3\n Line 4\n Line 5" . as_ref( )
2006
+ ) ;
2007
+ }
2008
+
1962
2009
/// Test that, given this input:
1963
2010
///
1964
2011
/// Line 1\n
@@ -1972,7 +2019,7 @@ mod tests {
1972
2019
///
1973
2020
/// This behavior is desirable because it prevents flushing partial lines
1974
2021
#[ test]
1975
- fn test_partial_write_buffers_line ( ) {
2022
+ fn partial_write_buffers_line ( ) {
1976
2023
let writer = ProgrammableSink { accept_prefix : Some ( 13 ) , ..Default :: default ( ) } ;
1977
2024
let mut writer = LineWriter :: new ( writer) ;
1978
2025
@@ -1992,7 +2039,7 @@ mod tests {
1992
2039
/// And given that the full write of lines 1 and 2 was successful
1993
2040
/// That data up to Line 3 is buffered
1994
2041
#[ test]
1995
- fn test_partial_line_buffered_after_line_write ( ) {
2042
+ fn partial_line_buffered_after_line_write ( ) {
1996
2043
let writer = ProgrammableSink :: default ( ) ;
1997
2044
let mut writer = LineWriter :: new ( writer) ;
1998
2045
@@ -2007,7 +2054,7 @@ mod tests {
2007
2054
/// LineBuffer's buffer (that is, without a trailing newline), that that
2008
2055
/// line is written to the inner writer
2009
2056
#[ test]
2010
- fn test_long_line_flushed ( ) {
2057
+ fn long_line_flushed ( ) {
2011
2058
let writer = ProgrammableSink :: default ( ) ;
2012
2059
let mut writer = LineWriter :: with_capacity ( 5 , writer) ;
2013
2060
@@ -2020,7 +2067,7 @@ mod tests {
2020
2067
/// and no additional writes take place. This assures the property that
2021
2068
/// `write` should make at-most-one attempt to write new data.
2022
2069
#[ test]
2023
- fn test_long_tail_not_flushed ( ) {
2070
+ fn line_long_tail_not_flushed ( ) {
2024
2071
let writer = ProgrammableSink :: default ( ) ;
2025
2072
let mut writer = LineWriter :: with_capacity ( 5 , writer) ;
2026
2073
@@ -2036,7 +2083,7 @@ mod tests {
2036
2083
/// Test that, if an attempt to pre-flush buffered data returns Ok(0),
2037
2084
/// this is propagated as an error.
2038
2085
#[ test]
2039
- fn test_line_buffer_write0_error ( ) {
2086
+ fn line_buffer_write0_error ( ) {
2040
2087
let writer = ProgrammableSink {
2041
2088
// Accept one write, then return Ok(0) on subsequent ones
2042
2089
max_writes : Some ( 1 ) ,
@@ -2060,7 +2107,7 @@ mod tests {
2060
2107
/// Test that, if a write returns Ok(0) after a successful pre-flush, this
2061
2108
/// is propogated as Ok(0)
2062
2109
#[ test]
2063
- fn test_line_buffer_write0_normal ( ) {
2110
+ fn line_buffer_write0_normal ( ) {
2064
2111
let writer = ProgrammableSink {
2065
2112
// Accept two writes, then return Ok(0) on subsequent ones
2066
2113
max_writes : Some ( 2 ) ,
@@ -2078,4 +2125,39 @@ mod tests {
2078
2125
assert_eq ! ( writer. write( b" Line End\n " ) . unwrap( ) , 0 ) ;
2079
2126
assert_eq ! ( & writer. get_ref( ) . buffer, b"Line 1\n Partial" ) ;
2080
2127
}
2128
+
2129
+ /// LineWriter has a custom `write_all`; make sure it works correctly
2130
+ #[ test]
2131
+ fn line_write_all ( ) {
2132
+ let writer = ProgrammableSink {
2133
+ // Only write 5 bytes at a time
2134
+ accept_prefix : Some ( 5 ) ,
2135
+ ..Default :: default ( )
2136
+ } ;
2137
+ let mut writer = LineWriter :: new ( writer) ;
2138
+
2139
+ writer. write_all ( b"Line 1\n Line 2\n Line 3\n Line 4\n Partial" ) . unwrap ( ) ;
2140
+ assert_eq ! ( & writer. get_ref( ) . buffer, b"Line 1\n Line 2\n Line 3\n Line 4\n " ) ;
2141
+ writer. write_all ( b" Line 5\n " ) . unwrap ( ) ;
2142
+ assert_eq ! (
2143
+ writer. get_ref( ) . buffer. as_slice( ) ,
2144
+ b"Line 1\n Line 2\n Line 3\n Line 4\n Partial Line 5\n " . as_ref( ) ,
2145
+ ) ;
2146
+ }
2147
+
2148
+ #[ test]
2149
+ fn line_write_all_error ( ) {
2150
+ let writer = ProgrammableSink {
2151
+ // Only accept up to 3 writes of up to 5 bytes each
2152
+ accept_prefix : Some ( 5 ) ,
2153
+ max_writes : Some ( 3 ) ,
2154
+ ..Default :: default ( )
2155
+ } ;
2156
+
2157
+ let mut writer = LineWriter :: new ( writer) ;
2158
+ let res = writer. write_all ( b"Line 1\n Line 2\n Line 3\n Line 4\n Partial" ) ;
2159
+ assert ! ( res. is_err( ) ) ;
2160
+ // An error from write_all leaves everything in an indeterminate state,
2161
+ // so there's nothing else to test here
2162
+ }
2081
2163
}
0 commit comments