@@ -348,6 +348,30 @@ impl File {
348
348
inner : self . inner . duplicate ( ) ?
349
349
} )
350
350
}
351
+
352
+ /// Reads a number of bytes starting from a given offset.
353
+ ///
354
+ /// The offset is relative to the file start and thus independent from the
355
+ /// current cursor.
356
+ ///
357
+ /// Note that similar to `File::read`, it is not an error to return a short
358
+ /// read.
359
+ #[ unstable( feature = "file_offset" , issue = "35918" ) ]
360
+ pub fn read_at ( & self , buf : & mut [ u8 ] , offset : u64 ) -> io:: Result < usize > {
361
+ self . inner . read_at ( buf, offset)
362
+ }
363
+
364
+ /// Writes a number of bytes starting from a given offset.
365
+ ///
366
+ /// The offset is relative to the file start and thus independent from the
367
+ /// current cursor.
368
+ ///
369
+ /// Note that similar to `File::write`, it is not an error to return a
370
+ /// short write.
371
+ #[ unstable( feature = "file_offset" , issue = "35918" ) ]
372
+ pub fn write_at ( & self , buf : & [ u8 ] , offset : u64 ) -> io:: Result < usize > {
373
+ self . inner . write_at ( buf, offset)
374
+ }
351
375
}
352
376
353
377
impl AsInner < fs_imp:: File > for File {
@@ -1893,6 +1917,53 @@ mod tests {
1893
1917
check ! ( fs:: remove_file( filename) ) ;
1894
1918
}
1895
1919
1920
+ #[ test]
1921
+ fn file_test_io_read_write_at ( ) {
1922
+ let tmpdir = tmpdir ( ) ;
1923
+ let filename = tmpdir. join ( "file_rt_io_file_test_read_write_at.txt" ) ;
1924
+ let mut buf = [ 0 ; 256 ] ;
1925
+ let write1 = "asdf" ;
1926
+ let write2 = "qwer-" ;
1927
+ let write3 = "-zxcv" ;
1928
+ let content = "qwer-asdf-zxcv" ;
1929
+ {
1930
+ let oo = OpenOptions :: new ( ) . create_new ( true ) . write ( true ) . read ( true ) . clone ( ) ;
1931
+ let mut rw = check ! ( oo. open( & filename) ) ;
1932
+ assert_eq ! ( check!( rw. write_at( write1. as_bytes( ) , 5 ) ) , write1. len( ) ) ;
1933
+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 0 ) ;
1934
+ assert_eq ! ( check!( rw. read_at( & mut buf, 5 ) ) , write1. len( ) ) ;
1935
+ assert_eq ! ( str :: from_utf8( & buf[ ..write1. len( ) ] ) , Ok ( write1) ) ;
1936
+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 0 ) ;
1937
+ assert_eq ! ( check!( rw. write( write2. as_bytes( ) ) ) , write2. len( ) ) ;
1938
+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 5 ) ;
1939
+ assert_eq ! ( check!( rw. read( & mut buf) ) , write1. len( ) ) ;
1940
+ assert_eq ! ( str :: from_utf8( & buf[ ..write1. len( ) ] ) , Ok ( write1) ) ;
1941
+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 9 ) ;
1942
+ assert_eq ! ( check!( rw. read_at( & mut buf[ ..write2. len( ) ] , 0 ) ) , write2. len( ) ) ;
1943
+ assert_eq ! ( str :: from_utf8( & buf[ ..write2. len( ) ] ) , Ok ( write2) ) ;
1944
+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 9 ) ;
1945
+ assert_eq ! ( check!( rw. write_at( write3. as_bytes( ) , 9 ) ) , write3. len( ) ) ;
1946
+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 9 ) ;
1947
+ }
1948
+ {
1949
+ let mut read = check ! ( File :: open( & filename) ) ;
1950
+ assert_eq ! ( check!( read. read_at( & mut buf, 0 ) ) , content. len( ) ) ;
1951
+ assert_eq ! ( str :: from_utf8( & buf[ ..content. len( ) ] ) , Ok ( content) ) ;
1952
+ assert_eq ! ( check!( read. seek( SeekFrom :: Current ( 0 ) ) ) , 0 ) ;
1953
+ assert_eq ! ( check!( read. seek( SeekFrom :: End ( -5 ) ) ) , 9 ) ;
1954
+ assert_eq ! ( check!( read. read_at( & mut buf, 0 ) ) , content. len( ) ) ;
1955
+ assert_eq ! ( str :: from_utf8( & buf[ ..content. len( ) ] ) , Ok ( content) ) ;
1956
+ assert_eq ! ( check!( read. seek( SeekFrom :: Current ( 0 ) ) ) , 9 ) ;
1957
+ assert_eq ! ( check!( read. read( & mut buf) ) , write3. len( ) ) ;
1958
+ assert_eq ! ( str :: from_utf8( & buf[ ..write3. len( ) ] ) , Ok ( write3) ) ;
1959
+ assert_eq ! ( check!( read. seek( SeekFrom :: Current ( 0 ) ) ) , 14 ) ;
1960
+ assert_eq ! ( check!( read. read_at( & mut buf, 0 ) ) , content. len( ) ) ;
1961
+ assert_eq ! ( str :: from_utf8( & buf[ ..content. len( ) ] ) , Ok ( content) ) ;
1962
+ assert_eq ! ( check!( read. seek( SeekFrom :: Current ( 0 ) ) ) , 14 ) ;
1963
+ }
1964
+ check ! ( fs:: remove_file( & filename) ) ;
1965
+ }
1966
+
1896
1967
#[ test]
1897
1968
fn file_test_stat_is_correct_on_is_file ( ) {
1898
1969
let tmpdir = tmpdir ( ) ;
0 commit comments