]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | #[cfg(test)] |
2 | mod tests; | |
3 | ||
532ac7d7 XL |
4 | use crate::io::prelude::*; |
5 | ||
6 | use crate::cmp; | |
dfeec247 | 7 | use crate::io::{self, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, SeekFrom}; |
85aaf69f | 8 | |
8faf50e0 | 9 | use core::convert::TryInto; |
85aaf69f | 10 | |
8faf50e0 | 11 | /// A `Cursor` wraps an in-memory buffer and provides it with a |
c30ab7b3 | 12 | /// [`Seek`] implementation. |
85aaf69f | 13 | /// |
8faf50e0 | 14 | /// `Cursor`s are used with in-memory buffers, anything implementing |
3dfed10e | 15 | /// [`AsRef`]`<[u8]>`, to allow them to implement [`Read`] and/or [`Write`], |
8faf50e0 XL |
16 | /// allowing these buffers to be used anywhere you might use a reader or writer |
17 | /// that does actual I/O. | |
85aaf69f | 18 | /// |
c1a9b12d | 19 | /// The standard library implements some I/O traits on various types which |
c30ab7b3 SL |
20 | /// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and |
21 | /// `Cursor<`[`&[u8]`][bytes]`>`. | |
c1a9b12d SL |
22 | /// |
23 | /// # Examples | |
24 | /// | |
c30ab7b3 | 25 | /// We may want to write bytes to a [`File`] in our production |
c1a9b12d SL |
26 | /// code, but use an in-memory buffer in our tests. We can do this with |
27 | /// `Cursor`: | |
28 | /// | |
3dfed10e XL |
29 | /// [bytes]: crate::slice |
30 | /// [`File`]: crate::fs::File | |
c1a9b12d SL |
31 | /// |
32 | /// ```no_run | |
33 | /// use std::io::prelude::*; | |
34 | /// use std::io::{self, SeekFrom}; | |
35 | /// use std::fs::File; | |
36 | /// | |
37 | /// // a library function we've written | |
38 | /// fn write_ten_bytes_at_end<W: Write + Seek>(writer: &mut W) -> io::Result<()> { | |
32a655c1 | 39 | /// writer.seek(SeekFrom::End(-10))?; |
c1a9b12d SL |
40 | /// |
41 | /// for i in 0..10 { | |
32a655c1 | 42 | /// writer.write(&[i])?; |
c1a9b12d SL |
43 | /// } |
44 | /// | |
45 | /// // all went well | |
46 | /// Ok(()) | |
47 | /// } | |
48 | /// | |
49 | /// # fn foo() -> io::Result<()> { | |
50 | /// // Here's some code that uses this library function. | |
51 | /// // | |
52 | /// // We might want to use a BufReader here for efficiency, but let's | |
53 | /// // keep this example focused. | |
32a655c1 | 54 | /// let mut file = File::create("foo.txt")?; |
c1a9b12d | 55 | /// |
32a655c1 | 56 | /// write_ten_bytes_at_end(&mut file)?; |
c1a9b12d SL |
57 | /// # Ok(()) |
58 | /// # } | |
59 | /// | |
60 | /// // now let's write a test | |
61 | /// #[test] | |
62 | /// fn test_writes_bytes() { | |
3b2f2976 | 63 | /// // setting up a real File is much slower than an in-memory buffer, |
c1a9b12d SL |
64 | /// // let's use a cursor instead |
65 | /// use std::io::Cursor; | |
66 | /// let mut buff = Cursor::new(vec![0; 15]); | |
67 | /// | |
b039eaaf | 68 | /// write_ten_bytes_at_end(&mut buff).unwrap(); |
c1a9b12d SL |
69 | /// |
70 | /// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); | |
71 | /// } | |
72 | /// ``` | |
c34b1796 | 73 | #[stable(feature = "rust1", since = "1.0.0")] |
17df50a5 | 74 | #[derive(Debug, Default, Eq, PartialEq)] |
85aaf69f SL |
75 | pub struct Cursor<T> { |
76 | inner: T, | |
77 | pos: u64, | |
78 | } | |
79 | ||
80 | impl<T> Cursor<T> { | |
8faf50e0 | 81 | /// Creates a new cursor wrapping the provided underlying in-memory buffer. |
c1a9b12d | 82 | /// |
3dfed10e XL |
83 | /// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`]) |
84 | /// is not empty. So writing to cursor starts with overwriting [`Vec`] | |
8faf50e0 | 85 | /// content, not with appending to it. |
cc61c64b | 86 | /// |
c1a9b12d SL |
87 | /// # Examples |
88 | /// | |
89 | /// ``` | |
90 | /// use std::io::Cursor; | |
91 | /// | |
92 | /// let buff = Cursor::new(Vec::new()); | |
93 | /// # fn force_inference(_: &Cursor<Vec<u8>>) {} | |
94 | /// # force_inference(&buff); | |
95 | /// ``` | |
c34b1796 | 96 | #[stable(feature = "rust1", since = "1.0.0")] |
29967ef6 XL |
97 | #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] |
98 | pub const fn new(inner: T) -> Cursor<T> { | |
74b04a01 | 99 | Cursor { pos: 0, inner } |
85aaf69f SL |
100 | } |
101 | ||
9346a6ac | 102 | /// Consumes this cursor, returning the underlying value. |
c1a9b12d SL |
103 | /// |
104 | /// # Examples | |
105 | /// | |
106 | /// ``` | |
107 | /// use std::io::Cursor; | |
108 | /// | |
109 | /// let buff = Cursor::new(Vec::new()); | |
110 | /// # fn force_inference(_: &Cursor<Vec<u8>>) {} | |
111 | /// # force_inference(&buff); | |
112 | /// | |
113 | /// let vec = buff.into_inner(); | |
114 | /// ``` | |
c34b1796 | 115 | #[stable(feature = "rust1", since = "1.0.0")] |
dfeec247 XL |
116 | pub fn into_inner(self) -> T { |
117 | self.inner | |
118 | } | |
85aaf69f | 119 | |
9346a6ac | 120 | /// Gets a reference to the underlying value in this cursor. |
c1a9b12d SL |
121 | /// |
122 | /// # Examples | |
123 | /// | |
124 | /// ``` | |
125 | /// use std::io::Cursor; | |
126 | /// | |
127 | /// let buff = Cursor::new(Vec::new()); | |
128 | /// # fn force_inference(_: &Cursor<Vec<u8>>) {} | |
129 | /// # force_inference(&buff); | |
130 | /// | |
131 | /// let reference = buff.get_ref(); | |
132 | /// ``` | |
c34b1796 | 133 | #[stable(feature = "rust1", since = "1.0.0")] |
29967ef6 XL |
134 | #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] |
135 | pub const fn get_ref(&self) -> &T { | |
dfeec247 XL |
136 | &self.inner |
137 | } | |
85aaf69f | 138 | |
9346a6ac | 139 | /// Gets a mutable reference to the underlying value in this cursor. |
85aaf69f SL |
140 | /// |
141 | /// Care should be taken to avoid modifying the internal I/O state of the | |
142 | /// underlying value as it may corrupt this cursor's position. | |
c1a9b12d SL |
143 | /// |
144 | /// # Examples | |
145 | /// | |
146 | /// ``` | |
147 | /// use std::io::Cursor; | |
148 | /// | |
149 | /// let mut buff = Cursor::new(Vec::new()); | |
150 | /// # fn force_inference(_: &Cursor<Vec<u8>>) {} | |
151 | /// # force_inference(&buff); | |
152 | /// | |
153 | /// let reference = buff.get_mut(); | |
154 | /// ``` | |
c34b1796 | 155 | #[stable(feature = "rust1", since = "1.0.0")] |
dfeec247 XL |
156 | pub fn get_mut(&mut self) -> &mut T { |
157 | &mut self.inner | |
158 | } | |
85aaf69f | 159 | |
c1a9b12d SL |
160 | /// Returns the current position of this cursor. |
161 | /// | |
162 | /// # Examples | |
163 | /// | |
164 | /// ``` | |
165 | /// use std::io::Cursor; | |
166 | /// use std::io::prelude::*; | |
167 | /// use std::io::SeekFrom; | |
168 | /// | |
169 | /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); | |
170 | /// | |
171 | /// assert_eq!(buff.position(), 0); | |
172 | /// | |
173 | /// buff.seek(SeekFrom::Current(2)).unwrap(); | |
174 | /// assert_eq!(buff.position(), 2); | |
175 | /// | |
176 | /// buff.seek(SeekFrom::Current(-1)).unwrap(); | |
177 | /// assert_eq!(buff.position(), 1); | |
178 | /// ``` | |
c34b1796 | 179 | #[stable(feature = "rust1", since = "1.0.0")] |
29967ef6 XL |
180 | #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] |
181 | pub const fn position(&self) -> u64 { | |
dfeec247 XL |
182 | self.pos |
183 | } | |
85aaf69f | 184 | |
c1a9b12d SL |
185 | /// Sets the position of this cursor. |
186 | /// | |
187 | /// # Examples | |
188 | /// | |
189 | /// ``` | |
190 | /// use std::io::Cursor; | |
191 | /// | |
192 | /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); | |
193 | /// | |
194 | /// assert_eq!(buff.position(), 0); | |
195 | /// | |
196 | /// buff.set_position(2); | |
197 | /// assert_eq!(buff.position(), 2); | |
198 | /// | |
199 | /// buff.set_position(4); | |
200 | /// assert_eq!(buff.position(), 4); | |
201 | /// ``` | |
c34b1796 | 202 | #[stable(feature = "rust1", since = "1.0.0")] |
dfeec247 XL |
203 | pub fn set_position(&mut self, pos: u64) { |
204 | self.pos = pos; | |
205 | } | |
85aaf69f SL |
206 | } |
207 | ||
136023e0 XL |
208 | impl<T> Cursor<T> |
209 | where | |
210 | T: AsRef<[u8]>, | |
211 | { | |
212 | /// Returns the remaining slice. | |
213 | /// | |
214 | /// # Examples | |
215 | /// | |
216 | /// ``` | |
217 | /// #![feature(cursor_remaining)] | |
218 | /// use std::io::Cursor; | |
219 | /// | |
220 | /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); | |
221 | /// | |
222 | /// assert_eq!(buff.remaining_slice(), &[1, 2, 3, 4, 5]); | |
223 | /// | |
224 | /// buff.set_position(2); | |
225 | /// assert_eq!(buff.remaining_slice(), &[3, 4, 5]); | |
226 | /// | |
227 | /// buff.set_position(4); | |
228 | /// assert_eq!(buff.remaining_slice(), &[5]); | |
229 | /// | |
230 | /// buff.set_position(6); | |
231 | /// assert_eq!(buff.remaining_slice(), &[]); | |
232 | /// ``` | |
233 | #[unstable(feature = "cursor_remaining", issue = "86369")] | |
234 | pub fn remaining_slice(&self) -> &[u8] { | |
235 | let len = self.pos.min(self.inner.as_ref().len() as u64); | |
236 | &self.inner.as_ref()[(len as usize)..] | |
237 | } | |
238 | ||
239 | /// Returns `true` if the remaining slice is empty. | |
240 | /// | |
241 | /// # Examples | |
242 | /// | |
243 | /// ``` | |
244 | /// #![feature(cursor_remaining)] | |
245 | /// use std::io::Cursor; | |
246 | /// | |
247 | /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); | |
248 | /// | |
249 | /// buff.set_position(2); | |
250 | /// assert!(!buff.is_empty()); | |
251 | /// | |
252 | /// buff.set_position(5); | |
253 | /// assert!(buff.is_empty()); | |
254 | /// | |
255 | /// buff.set_position(10); | |
256 | /// assert!(buff.is_empty()); | |
257 | /// ``` | |
258 | #[unstable(feature = "cursor_remaining", issue = "86369")] | |
259 | pub fn is_empty(&self) -> bool { | |
260 | self.pos >= self.inner.as_ref().len() as u64 | |
261 | } | |
262 | } | |
263 | ||
17df50a5 XL |
264 | #[stable(feature = "rust1", since = "1.0.0")] |
265 | impl<T> Clone for Cursor<T> | |
266 | where | |
267 | T: Clone, | |
268 | { | |
269 | #[inline] | |
270 | fn clone(&self) -> Self { | |
271 | Cursor { inner: self.inner.clone(), pos: self.pos } | |
272 | } | |
273 | ||
274 | #[inline] | |
275 | fn clone_from(&mut self, other: &Self) { | |
276 | self.inner.clone_from(&other.inner); | |
277 | self.pos = other.pos; | |
278 | } | |
279 | } | |
280 | ||
b039eaaf | 281 | #[stable(feature = "rust1", since = "1.0.0")] |
dfeec247 XL |
282 | impl<T> io::Seek for Cursor<T> |
283 | where | |
284 | T: AsRef<[u8]>, | |
285 | { | |
b039eaaf | 286 | fn seek(&mut self, style: SeekFrom) -> io::Result<u64> { |
8bb4bdeb | 287 | let (base_pos, offset) = match style { |
dfeec247 XL |
288 | SeekFrom::Start(n) => { |
289 | self.pos = n; | |
290 | return Ok(n); | |
291 | } | |
8bb4bdeb XL |
292 | SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), |
293 | SeekFrom::Current(n) => (self.pos, n), | |
b039eaaf | 294 | }; |
8bb4bdeb XL |
295 | let new_pos = if offset >= 0 { |
296 | base_pos.checked_add(offset as u64) | |
b039eaaf | 297 | } else { |
8bb4bdeb XL |
298 | base_pos.checked_sub((offset.wrapping_neg()) as u64) |
299 | }; | |
300 | match new_pos { | |
dfeec247 XL |
301 | Some(n) => { |
302 | self.pos = n; | |
303 | Ok(self.pos) | |
304 | } | |
cdc7bbd5 | 305 | None => Err(Error::new_const( |
dfeec247 | 306 | ErrorKind::InvalidInput, |
cdc7bbd5 | 307 | &"invalid seek to a negative or overflowing position", |
dfeec247 | 308 | )), |
85aaf69f SL |
309 | } |
310 | } | |
532ac7d7 XL |
311 | |
312 | fn stream_len(&mut self) -> io::Result<u64> { | |
313 | Ok(self.inner.as_ref().len() as u64) | |
314 | } | |
315 | ||
316 | fn stream_position(&mut self) -> io::Result<u64> { | |
317 | Ok(self.pos) | |
318 | } | |
85aaf69f SL |
319 | } |
320 | ||
c34b1796 | 321 | #[stable(feature = "rust1", since = "1.0.0")] |
dfeec247 XL |
322 | impl<T> Read for Cursor<T> |
323 | where | |
324 | T: AsRef<[u8]>, | |
325 | { | |
b039eaaf | 326 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
136023e0 | 327 | let n = Read::read(&mut self.remaining_slice(), buf)?; |
b039eaaf SL |
328 | self.pos += n as u64; |
329 | Ok(n) | |
85aaf69f | 330 | } |
041b39d2 | 331 | |
48663c56 | 332 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
9fa01778 XL |
333 | let mut nread = 0; |
334 | for buf in bufs { | |
335 | let n = self.read(buf)?; | |
336 | nread += n; | |
337 | if n < buf.len() { | |
338 | break; | |
339 | } | |
340 | } | |
341 | Ok(nread) | |
342 | } | |
343 | ||
f9f354fc XL |
344 | fn is_read_vectored(&self) -> bool { |
345 | true | |
346 | } | |
347 | ||
ff7c6d11 XL |
348 | fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { |
349 | let n = buf.len(); | |
136023e0 | 350 | Read::read_exact(&mut self.remaining_slice(), buf)?; |
ff7c6d11 XL |
351 | self.pos += n as u64; |
352 | Ok(()) | |
353 | } | |
354 | ||
041b39d2 XL |
355 | #[inline] |
356 | unsafe fn initializer(&self) -> Initializer { | |
357 | Initializer::nop() | |
358 | } | |
85aaf69f SL |
359 | } |
360 | ||
c34b1796 | 361 | #[stable(feature = "rust1", since = "1.0.0")] |
dfeec247 XL |
362 | impl<T> BufRead for Cursor<T> |
363 | where | |
364 | T: AsRef<[u8]>, | |
365 | { | |
b039eaaf | 366 | fn fill_buf(&mut self) -> io::Result<&[u8]> { |
136023e0 | 367 | Ok(self.remaining_slice()) |
85aaf69f | 368 | } |
dfeec247 XL |
369 | fn consume(&mut self, amt: usize) { |
370 | self.pos += amt as u64; | |
371 | } | |
85aaf69f SL |
372 | } |
373 | ||
2c00a5a8 | 374 | // Non-resizing write implementation |
48663c56 | 375 | #[inline] |
2c00a5a8 XL |
376 | fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> { |
377 | let pos = cmp::min(*pos_mut, slice.len() as u64); | |
378 | let amt = (&mut slice[(pos as usize)..]).write(buf)?; | |
379 | *pos_mut += amt as u64; | |
380 | Ok(amt) | |
381 | } | |
382 | ||
48663c56 | 383 | #[inline] |
9fa01778 XL |
384 | fn slice_write_vectored( |
385 | pos_mut: &mut u64, | |
386 | slice: &mut [u8], | |
48663c56 | 387 | bufs: &[IoSlice<'_>], |
dfeec247 | 388 | ) -> io::Result<usize> { |
9fa01778 XL |
389 | let mut nwritten = 0; |
390 | for buf in bufs { | |
391 | let n = slice_write(pos_mut, slice, buf)?; | |
392 | nwritten += n; | |
393 | if n < buf.len() { | |
394 | break; | |
395 | } | |
396 | } | |
397 | Ok(nwritten) | |
398 | } | |
399 | ||
2c00a5a8 XL |
400 | // Resizing write implementation |
401 | fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> { | |
8faf50e0 | 402 | let pos: usize = (*pos_mut).try_into().map_err(|_| { |
cdc7bbd5 | 403 | Error::new_const( |
dfeec247 | 404 | ErrorKind::InvalidInput, |
cdc7bbd5 | 405 | &"cursor position exceeds maximum possible vector length", |
dfeec247 | 406 | ) |
2c00a5a8 XL |
407 | })?; |
408 | // Make sure the internal buffer is as least as big as where we | |
409 | // currently are | |
410 | let len = vec.len(); | |
411 | if len < pos { | |
412 | // use `resize` so that the zero filling is as efficient as possible | |
413 | vec.resize(pos, 0); | |
414 | } | |
415 | // Figure out what bytes will be used to overwrite what's currently | |
416 | // there (left), and what will be appended on the end (right) | |
417 | { | |
418 | let space = vec.len() - pos; | |
419 | let (left, right) = buf.split_at(cmp::min(space, buf.len())); | |
420 | vec[pos..pos + left.len()].copy_from_slice(left); | |
421 | vec.extend_from_slice(right); | |
422 | } | |
423 | ||
424 | // Bump us forward | |
425 | *pos_mut = (pos + buf.len()) as u64; | |
426 | Ok(buf.len()) | |
427 | } | |
428 | ||
9fa01778 XL |
429 | fn vec_write_vectored( |
430 | pos_mut: &mut u64, | |
431 | vec: &mut Vec<u8>, | |
48663c56 | 432 | bufs: &[IoSlice<'_>], |
dfeec247 | 433 | ) -> io::Result<usize> { |
9fa01778 XL |
434 | let mut nwritten = 0; |
435 | for buf in bufs { | |
436 | nwritten += vec_write(pos_mut, vec, buf)?; | |
437 | } | |
438 | Ok(nwritten) | |
439 | } | |
440 | ||
c34b1796 | 441 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 442 | impl Write for Cursor<&mut [u8]> { |
3157f602 | 443 | #[inline] |
2c00a5a8 XL |
444 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
445 | slice_write(&mut self.pos, self.inner, buf) | |
446 | } | |
9fa01778 XL |
447 | |
448 | #[inline] | |
48663c56 | 449 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
9fa01778 XL |
450 | slice_write_vectored(&mut self.pos, self.inner, bufs) |
451 | } | |
452 | ||
f9f354fc XL |
453 | #[inline] |
454 | fn is_write_vectored(&self) -> bool { | |
455 | true | |
456 | } | |
457 | ||
48663c56 | 458 | #[inline] |
dfeec247 XL |
459 | fn flush(&mut self) -> io::Result<()> { |
460 | Ok(()) | |
461 | } | |
2c00a5a8 XL |
462 | } |
463 | ||
0531ce1d | 464 | #[stable(feature = "cursor_mut_vec", since = "1.25.0")] |
9fa01778 | 465 | impl Write for Cursor<&mut Vec<u8>> { |
2c00a5a8 XL |
466 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
467 | vec_write(&mut self.pos, self.inner, buf) | |
85aaf69f | 468 | } |
9fa01778 | 469 | |
48663c56 | 470 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
9fa01778 XL |
471 | vec_write_vectored(&mut self.pos, self.inner, bufs) |
472 | } | |
473 | ||
f9f354fc XL |
474 | #[inline] |
475 | fn is_write_vectored(&self) -> bool { | |
476 | true | |
477 | } | |
478 | ||
48663c56 | 479 | #[inline] |
dfeec247 XL |
480 | fn flush(&mut self) -> io::Result<()> { |
481 | Ok(()) | |
482 | } | |
85aaf69f SL |
483 | } |
484 | ||
c34b1796 | 485 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
486 | impl Write for Cursor<Vec<u8>> { |
487 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
2c00a5a8 | 488 | vec_write(&mut self.pos, &mut self.inner, buf) |
85aaf69f | 489 | } |
9fa01778 | 490 | |
48663c56 | 491 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
9fa01778 XL |
492 | vec_write_vectored(&mut self.pos, &mut self.inner, bufs) |
493 | } | |
494 | ||
f9f354fc XL |
495 | #[inline] |
496 | fn is_write_vectored(&self) -> bool { | |
497 | true | |
498 | } | |
499 | ||
48663c56 | 500 | #[inline] |
dfeec247 XL |
501 | fn flush(&mut self) -> io::Result<()> { |
502 | Ok(()) | |
503 | } | |
85aaf69f SL |
504 | } |
505 | ||
b039eaaf SL |
506 | #[stable(feature = "cursor_box_slice", since = "1.5.0")] |
507 | impl Write for Cursor<Box<[u8]>> { | |
3157f602 | 508 | #[inline] |
b039eaaf | 509 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
2c00a5a8 | 510 | slice_write(&mut self.pos, &mut self.inner, buf) |
b039eaaf | 511 | } |
9fa01778 XL |
512 | |
513 | #[inline] | |
48663c56 | 514 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
9fa01778 XL |
515 | slice_write_vectored(&mut self.pos, &mut self.inner, bufs) |
516 | } | |
517 | ||
f9f354fc XL |
518 | #[inline] |
519 | fn is_write_vectored(&self) -> bool { | |
520 | true | |
521 | } | |
522 | ||
48663c56 | 523 | #[inline] |
dfeec247 XL |
524 | fn flush(&mut self) -> io::Result<()> { |
525 | Ok(()) | |
526 | } | |
b039eaaf | 527 | } |