@@ -27,6 +27,58 @@ pub trait FileExt {
27
27
/// [`File::read`]: ../../../../std/fs/struct.File.html#method.read_vectored
28
28
fn read_at ( & self , bufs : & mut [ IoSliceMut < ' _ > ] , offset : u64 ) -> io:: Result < usize > ;
29
29
30
+ /// Reads the exact number of byte required to fill `buf` from the given offset.
31
+ ///
32
+ /// The offset is relative to the start of the file and thus independent
33
+ /// from the current cursor.
34
+ ///
35
+ /// The current file cursor is not affected by this function.
36
+ ///
37
+ /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
38
+ ///
39
+ /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
40
+ /// [`read_at`]: #tymethod.read_at
41
+ ///
42
+ /// # Errors
43
+ ///
44
+ /// If this function encounters an error of the kind
45
+ /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
46
+ /// will continue.
47
+ ///
48
+ /// If this function encounters an "end of file" before completely filling
49
+ /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
50
+ /// The contents of `buf` are unspecified in this case.
51
+ ///
52
+ /// If any other read error is encountered then this function immediately
53
+ /// returns. The contents of `buf` are unspecified in this case.
54
+ ///
55
+ /// If this function returns an error, it is unspecified how many bytes it
56
+ /// has read, but it will never read more than would be necessary to
57
+ /// completely fill the buffer.
58
+ ///
59
+ /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
60
+ /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
61
+ #[ stable( feature = "rw_exact_all_at" , since = "1.33.0" ) ]
62
+ fn read_exact_at ( & self , mut buf : & mut [ u8 ] , mut offset : u64 ) -> io:: Result < ( ) > {
63
+ while !buf. is_empty ( ) {
64
+ match self . read_at ( buf, offset) {
65
+ Ok ( 0 ) => break ,
66
+ Ok ( n) => {
67
+ let tmp = buf;
68
+ buf = & mut tmp[ n..] ;
69
+ offset += n as u64 ;
70
+ }
71
+ Err ( ref e) if e. kind ( ) == io:: ErrorKind :: Interrupted => { }
72
+ Err ( e) => return Err ( e) ,
73
+ }
74
+ }
75
+ if !buf. is_empty ( ) {
76
+ Err ( io:: Error :: new ( io:: ErrorKind :: UnexpectedEof , "failed to fill whole buffer" ) )
77
+ } else {
78
+ Ok ( ( ) )
79
+ }
80
+ }
81
+
30
82
/// Writes a number of bytes starting from a given offset.
31
83
///
32
84
/// Returns the number of bytes written.
@@ -45,6 +97,48 @@ pub trait FileExt {
45
97
/// [`File::write`]: ../../../../std/fs/struct.File.html#method.write_vectored
46
98
fn write_at ( & self , bufs : & [ IoSlice < ' _ > ] , offset : u64 ) -> io:: Result < usize > ;
47
99
100
+ /// Attempts to write an entire buffer starting from a given offset.
101
+ ///
102
+ /// The offset is relative to the start of the file and thus independent
103
+ /// from the current cursor.
104
+ ///
105
+ /// The current file cursor is not affected by this function.
106
+ ///
107
+ /// This method will continuously call [`write_at`] until there is no more data
108
+ /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
109
+ /// returned. This method will not return until the entire buffer has been
110
+ /// successfully written or such an error occurs. The first error that is
111
+ /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
112
+ /// returned.
113
+ ///
114
+ /// # Errors
115
+ ///
116
+ /// This function will return the first error of
117
+ /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
118
+ ///
119
+ /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
120
+ /// [`write_at`]: #tymethod.write_at
121
+ #[ stable( feature = "rw_exact_all_at" , since = "1.33.0" ) ]
122
+ fn write_all_at ( & self , mut buf : & [ u8 ] , mut offset : u64 ) -> io:: Result < ( ) > {
123
+ while !buf. is_empty ( ) {
124
+ match self . write_at ( buf, offset) {
125
+ Ok ( 0 ) => {
126
+ return Err ( io:: Error :: new (
127
+ io:: ErrorKind :: WriteZero ,
128
+ "failed to write whole buffer" ,
129
+ ) ) ;
130
+ }
131
+ Ok ( n) => {
132
+ buf = & buf[ n..] ;
133
+ offset += n as u64
134
+ }
135
+ Err ( ref e) if e. kind ( ) == io:: ErrorKind :: Interrupted => { }
136
+ Err ( e) => return Err ( e) ,
137
+ }
138
+ }
139
+ Ok ( ( ) )
140
+ }
141
+
48
142
/// Returns the current position within the file.
49
143
///
50
144
/// This corresponds to the `fd_tell` syscall and is similar to
0 commit comments