monoio/fs/file/mod.rs
1use std::{future::Future, io, path::Path};
2
3use crate::{
4 buf::{IoBuf, IoBufMut, IoVecBuf, IoVecBufMut},
5 driver::{op::Op, shared_fd::SharedFd},
6 fs::OpenOptions,
7 io::{AsyncReadRent, AsyncWriteRent},
8 BufResult,
9};
10
11#[cfg(unix)]
12mod unix;
13#[cfg(unix)]
14use unix as file_impl;
15#[cfg(windows)]
16mod windows;
17#[cfg(windows)]
18use windows as file_impl;
19
20use crate::io::{AsyncReadRentAt, AsyncWriteRentAt};
21
22/// A reference to an open file on the filesystem.
23///
24/// An instance of a `File` can be read and/or written depending on what options
25/// it was opened with. The `File` type provides **positional** read and write
26/// operations. The file does not maintain an internal cursor. The caller is
27/// required to specify an offset when issuing an operation.
28///
29/// While files are automatically closed when they go out of scope, the
30/// operation happens asynchronously in the background. It is recommended to
31/// call the `close()` function in order to guarantee that the file successfully
32/// closed before exiting the scope. Closing a file does not guarantee writes
33/// have persisted to disk. Use [`sync_all`] to ensure all writes have reached
34/// the filesystem.
35///
36/// [`sync_all`]: File::sync_all
37///
38/// # Examples
39///
40/// Creates a new file and write data to it:
41///
42/// ```no_run
43/// use monoio::fs::File;
44///
45/// #[monoio::main]
46/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
47/// // Open a file
48/// let file = File::create("hello.txt").await?;
49///
50/// // Write some data
51/// let (res, buf) = file.write_at(&b"hello world"[..], 0).await;
52/// let n = res?;
53///
54/// println!("wrote {} bytes", n);
55///
56/// // Sync data to the file system.
57/// file.sync_all().await?;
58///
59/// // Close the file
60/// file.close().await?;
61///
62/// Ok(())
63/// }
64/// ```
65#[derive(Debug)]
66pub struct File {
67 /// Open file descriptor
68 fd: SharedFd,
69}
70
71impl File {
72 /// Attempts to open a file in read-only mode.
73 ///
74 /// See the [`OpenOptions::open`] method for more details.
75 ///
76 /// # Errors
77 ///
78 /// This function will return an error if `path` does not already exist.
79 /// Other errors may also be returned according to [`OpenOptions::open`].
80 ///
81 /// # Examples
82 ///
83 /// ```no_run
84 /// use monoio::fs::File;
85 ///
86 /// #[monoio::main]
87 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
88 /// let f = File::open("foo.txt").await?;
89 ///
90 /// // Close the file
91 /// f.close().await?;
92 /// Ok(())
93 /// }
94 /// ```
95 pub async fn open(path: impl AsRef<Path>) -> io::Result<File> {
96 OpenOptions::new().read(true).open(path).await
97 }
98
99 /// Opens a file in write-only mode.
100 ///
101 /// This function will create a file if it does not exist,
102 /// and will truncate it if it does.
103 ///
104 /// See the [`OpenOptions::open`] function for more details.
105 ///
106 /// # Examples
107 ///
108 /// ```no_run
109 /// use monoio::fs::File;
110 ///
111 /// #[monoio::main]
112 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
113 /// let f = File::create("foo.txt").await?;
114 ///
115 /// // Close the file
116 /// f.close().await?;
117 /// Ok(())
118 /// }
119 /// ```
120 pub async fn create(path: impl AsRef<Path>) -> io::Result<File> {
121 OpenOptions::new()
122 .write(true)
123 .create(true)
124 .truncate(true)
125 .open(path)
126 .await
127 }
128
129 pub(crate) fn from_shared_fd(fd: SharedFd) -> File {
130 File { fd }
131 }
132
133 async fn read<T: IoBufMut>(&mut self, buf: T) -> crate::BufResult<usize, T> {
134 file_impl::read(self.fd.clone(), buf).await
135 }
136
137 async fn read_vectored<T: IoVecBufMut>(&mut self, buf_vec: T) -> crate::BufResult<usize, T> {
138 file_impl::read_vectored(self.fd.clone(), buf_vec).await
139 }
140
141 /// Read some bytes at the specified offset from the file into the specified
142 /// buffer, returning how many bytes were read.
143 ///
144 /// # Return
145 ///
146 /// The method returns the operation result and the same buffer value passed
147 /// as an argument.
148 ///
149 /// If the method returns [`Ok(n)`], then the read was successful. A nonzero
150 /// `n` value indicates that the buffer has been filled with `n` bytes of
151 /// data from the file. If `n` is `0`, then one of the following happened:
152 ///
153 /// 1. The specified offset is the end of the file.
154 /// 2. The buffer specified was 0 bytes in length.
155 ///
156 /// It is not an error if the returned value `n` is smaller than the buffer
157 /// size, even when the file contains enough data to fill the buffer.
158 ///
159 /// # Platform-specific behavior
160 ///
161 /// - On unix-like platform
162 /// - this function will **not** change the file pointer, and the `pos` always start from
163 /// the begin of file.
164 /// - On windows
165 /// - this function will change the file pointer, but the `pos` always start from the begin
166 /// of file.
167 ///
168 /// Addtionally,
169 ///
170 /// - On Unix and Windows (without the `iouring` feature enabled or not support the `iouring`):
171 /// - If the sync feature is enabled and the thread pool is attached, this operation will be
172 /// executed on the blocking thread pool, preventing it from blocking the current thread.
173 /// - If the sync feature is enabled but the thread pool is not attached, or if the sync
174 /// feature is disabled, the operation will be executed on the local thread, blocking the
175 /// current thread.
176 ///
177 /// - On Linux (with iouring enabled and supported):
178 ///
179 /// This operation will use io-uring to execute the task asynchronously.
180 ///
181 ///
182 /// # Errors
183 ///
184 /// If this function encounters any form of I/O or other error, an error
185 /// variant will be returned. The buffer is returned on error.
186 ///
187 /// # Examples
188 ///
189 /// ```no_run
190 /// use monoio::fs::File;
191 ///
192 /// #[monoio::main]
193 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
194 /// let f = File::open("foo.txt").await?;
195 /// let buffer = vec![0; 10];
196 ///
197 /// // Read up to 10 bytes
198 /// let (res, buffer) = f.read_at(buffer, 0).await;
199 /// let n = res?;
200 ///
201 /// println!("The bytes: {:?}", &buffer[..n]);
202 ///
203 /// // Close the file
204 /// f.close().await?;
205 /// Ok(())
206 /// }
207 /// ```
208 pub async fn read_at<T: IoBufMut>(&self, buf: T, pos: u64) -> crate::BufResult<usize, T> {
209 file_impl::read_at(self.fd.clone(), buf, pos).await
210 }
211
212 /// Read the exact number of bytes required to fill `buf` at the specified
213 /// offset from the file.
214 ///
215 /// This function reads as many as bytes as necessary to completely fill the
216 /// specified buffer `buf`.
217 ///
218 /// # Return
219 ///
220 /// The method returns the operation result and the same buffer value passed
221 /// as an argument.
222 ///
223 /// If the method returns [`Ok(())`], then the read was successful.
224 ///
225 /// # Errors
226 ///
227 /// If this function encounters an error of the kind
228 /// [`ErrorKind::Interrupted`] then the error is ignored and the
229 /// operation will continue.
230 ///
231 /// If this function encounters an "end of file" before completely filling
232 /// the buffer, it returns an error of the kind
233 /// [`ErrorKind::UnexpectedEof`]. The buffer is returned on error.
234 ///
235 /// If this function encounters any form of I/O or other error, an error
236 /// variant will be returned. The buffer is returned on error.
237 ///
238 /// # Examples
239 ///
240 /// ```no_run
241 /// use monoio::fs::File;
242 ///
243 /// #[monoio::main]
244 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
245 /// let f = File::open("foo.txt").await?;
246 /// let buffer = vec![0; 10];
247 ///
248 /// // Read up to 10 bytes
249 /// let (res, buffer) = f.read_exact_at(buffer, 0).await;
250 /// res?;
251 ///
252 /// println!("The bytes: {:?}", buffer);
253 ///
254 /// // Close the file
255 /// f.close().await?;
256 /// Ok(())
257 /// }
258 /// ```
259 ///
260 /// [`ErrorKind::Interrupted`]: std::io::ErrorKind::Interrupted
261 /// [`ErrorKind::UnexpectedEof`]: std::io::ErrorKind::UnexpectedEof
262 pub async fn read_exact_at<T: IoBufMut>(
263 &self,
264 mut buf: T,
265 pos: u64,
266 ) -> crate::BufResult<(), T> {
267 let len = buf.bytes_total();
268 let mut read = 0;
269 while read < len {
270 let slice = unsafe { buf.slice_mut_unchecked(read..len) };
271 let (res, slice) = self.read_at(slice, pos + read as u64).await;
272 buf = slice.into_inner();
273 match res {
274 Ok(0) => {
275 return (
276 Err(io::Error::new(
277 io::ErrorKind::UnexpectedEof,
278 "failed to fill whole buffer",
279 )),
280 buf,
281 )
282 }
283 Ok(n) => {
284 read += n;
285 }
286 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
287 Err(e) => return (Err(e), buf),
288 };
289 }
290
291 (Ok(()), buf)
292 }
293
294 async fn write<T: IoBuf>(&mut self, buf: T) -> crate::BufResult<usize, T> {
295 file_impl::write(self.fd.clone(), buf).await
296 }
297
298 async fn write_vectored<T: IoVecBuf>(&mut self, buf_vec: T) -> crate::BufResult<usize, T> {
299 file_impl::write_vectored(self.fd.clone(), buf_vec).await
300 }
301
302 /// Write a buffer into this file at the specified offset, returning how
303 /// many bytes were written.
304 ///
305 /// This function will attempt to write the entire contents of `buf`, but
306 /// the entire write may not succeed, or the write may also generate an
307 /// error. The bytes will be written starting at the specified offset.
308 ///
309 /// # Return
310 ///
311 /// The method returns the operation result and the same buffer value passed
312 /// in as an argument. A return value of `0` typically means that the
313 /// underlying file is no longer able to accept bytes and will likely not be
314 /// able to in the future as well, or that the buffer provided is empty.
315 ///
316 /// # Platform-specific behavior
317 ///
318 /// - On Unix and Windows (without the `iouring` feature enabled or not support the `iouring`):
319 /// - If the sync feature is enabled and the thread pool is attached, this operation will be
320 /// executed on the blocking thread pool, preventing it from blocking the current thread.
321 /// - If the sync feature is enabled but the thread pool is not attached, or if the sync
322 /// feature is disabled, the operation will be executed on the local thread, blocking the
323 /// current thread.
324 ///
325 /// - On Linux (with iouring enabled and supported):
326 ///
327 /// This operation will use io-uring to execute the task asynchronously.
328 ///
329 /// # Errors
330 ///
331 /// Each call to `write` may generate an I/O error indicating that the
332 /// operation could not be completed. If an error is returned then no bytes
333 /// in the buffer were written to this writer.
334 ///
335 /// It is **not** considered an error if the entire buffer could not be
336 /// written to this writer.
337 ///
338 /// # Examples
339 ///
340 /// ```no_run
341 /// use monoio::fs::File;
342 ///
343 /// #[monoio::main]
344 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
345 /// let file = File::create("foo.txt").await?;
346 ///
347 /// // Writes some prefix of the byte string, not necessarily all of it.
348 /// let (res, _) = file.write_at(&b"some bytes"[..], 0).await;
349 /// let n = res?;
350 ///
351 /// println!("wrote {} bytes", n);
352 ///
353 /// // Close the file
354 /// file.close().await?;
355 /// Ok(())
356 /// }
357 /// ```
358 ///
359 /// [`Ok(n)`]: Ok
360 pub async fn write_at<T: IoBuf>(&self, buf: T, pos: u64) -> crate::BufResult<usize, T> {
361 file_impl::write_at(self.fd.clone(), buf, pos).await
362 }
363
364 /// Attempts to write an entire buffer into this file at the specified
365 /// offset.
366 ///
367 /// This method will continuously call [`write_at`] until there is no more
368 /// data to be written or an error of non-[`ErrorKind::Interrupted`]
369 /// kind is returned. This method will not return until the entire
370 /// buffer has been successfully written or such an error occurs.
371 ///
372 /// If the buffer contains no data, this will never call [`write_at`].
373 ///
374 /// # Return
375 ///
376 /// The method returns the operation result and the same buffer value passed
377 /// in as an argument.
378 ///
379 /// # Errors
380 ///
381 /// This function will return the first error of
382 /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
383 ///
384 /// # Examples
385 ///
386 /// ```no_run
387 /// use monoio::fs::File;
388 ///
389 /// #[monoio::main]
390 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
391 /// let file = File::create("foo.txt").await?;
392 ///
393 /// // Writes some prefix of the byte string, not necessarily all of it.
394 /// let (res, _) = file.write_all_at(&b"some bytes"[..], 0).await;
395 /// res?;
396 ///
397 /// println!("wrote all bytes");
398 ///
399 /// // Close the file
400 /// file.close().await?;
401 /// Ok(())
402 /// }
403 /// ```
404 ///
405 /// [`write_at`]: File::write_at
406 /// [`ErrorKind::Interrupted`]: std::io::ErrorKind::Interrupted
407 pub async fn write_all_at<T: IoBuf>(&self, mut buf: T, pos: u64) -> crate::BufResult<(), T> {
408 let len = buf.bytes_init();
409 let mut written = 0;
410 while written < len {
411 let slice = unsafe { buf.slice_unchecked(written..len) };
412 let (res, slice) = self.write_at(slice, pos + written as u64).await;
413 buf = slice.into_inner();
414 match res {
415 Ok(0) => {
416 return (
417 Err(io::Error::new(
418 io::ErrorKind::WriteZero,
419 "failed to write whole buffer",
420 )),
421 buf,
422 )
423 }
424 Ok(n) => written += n,
425 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
426 Err(e) => return (Err(e), buf),
427 };
428 }
429
430 (Ok(()), buf)
431 }
432
433 /// Attempts to sync all OS-internal metadata to disk.
434 ///
435 /// This function will attempt to ensure that all in-memory data reaches the
436 /// filesystem before completing.
437 ///
438 /// This can be used to handle errors that would otherwise only be caught
439 /// when the `File` is closed. Dropping a file will ignore errors in
440 /// synchronizing this in-memory data.
441 ///
442 /// # Examples
443 ///
444 /// ```no_run
445 /// use monoio::fs::File;
446 ///
447 /// #[monoio::main]
448 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
449 /// let f = File::create("foo.txt").await?;
450 /// let (res, buf) = f.write_at(&b"Hello, world!"[..], 0).await;
451 /// let n = res?;
452 ///
453 /// f.sync_all().await?;
454 ///
455 /// // Close the file
456 /// f.close().await?;
457 /// Ok(())
458 /// }
459 /// ```
460 pub async fn sync_all(&self) -> io::Result<()> {
461 let op = Op::fsync(&self.fd).unwrap();
462 let completion = op.await;
463
464 completion.meta.result?;
465 Ok(())
466 }
467
468 /// Attempts to sync file data to disk.
469 ///
470 /// This method is similar to [`sync_all`], except that it may not
471 /// synchronize file metadata to the filesystem.
472 ///
473 /// This is intended for use cases that must synchronize content, but don't
474 /// need the metadata on disk. The goal of this method is to reduce disk
475 /// operations.
476 ///
477 /// Note that some platforms may simply implement this in terms of
478 /// [`sync_all`].
479 ///
480 /// [`sync_all`]: File::sync_all
481 ///
482 /// # Examples
483 ///
484 /// ```no_run
485 /// use monoio::fs::File;
486 ///
487 /// #[monoio::main]
488 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
489 /// let f = File::create("foo.txt").await?;
490 /// let (res, buf) = f.write_at(&b"Hello, world!"[..], 0).await;
491 /// let n = res?;
492 ///
493 /// f.sync_data().await?;
494 ///
495 /// // Close the file
496 /// f.close().await?;
497 /// Ok(())
498 /// }
499 /// ```
500 pub async fn sync_data(&self) -> io::Result<()> {
501 let op = Op::datasync(&self.fd).unwrap();
502 let completion = op.await;
503
504 completion.meta.result?;
505 Ok(())
506 }
507
508 #[inline]
509 fn flush(&mut self) -> impl Future<Output = io::Result<()>> {
510 std::future::ready(Ok(()))
511 }
512
513 /// Closes the file.
514 ///
515 /// The method completes once the close operation has completed,
516 /// guaranteeing that resources associated with the file have been released.
517 ///
518 /// If `close` is not called before dropping the file, the file is closed in
519 /// the background, but there is no guarantee as to **when** the close
520 /// operation will complete.
521 ///
522 /// # Examples
523 ///
524 /// ```no_run
525 /// use monoio::fs::File;
526 ///
527 /// #[monoio::main]
528 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
529 /// // Open the file
530 /// let f = File::open("foo.txt").await?;
531 /// // Close the file
532 /// f.close().await?;
533 ///
534 /// Ok(())
535 /// }
536 /// ```
537 pub async fn close(self) -> io::Result<()> {
538 self.fd.close().await;
539 Ok(())
540 }
541}
542
543impl AsyncWriteRent for File {
544 /// Writes the contents of a buffer to a file, returning the number of bytes written.
545 ///
546 /// This function attempts to write the entire buffer `buf`, but the write may not fully
547 /// succeed, and it might also result in an error. A call to `write` represents *at most one*
548 /// attempt to write to the underlying object.
549 ///
550 /// # Return
551 ///
552 /// If the return value is `(Ok(n), buf)`, it guarantees that `n <= buf.len()`. A return value
553 /// of `0` typically indicates that the underlying object can no longer accept bytes and likely
554 /// won't be able to in the future, or that the provided buffer is empty.
555 ///
556 /// # Errors
557 ///
558 /// Each `write` call may result in an I/O error, indicating that the operation couldn't be
559 /// completed. If an error occurs, no bytes from the buffer were written to the file.
560 ///
561 /// It is **not** considered an error if the entire buffer could not be written to the file.
562 ///
563 /// # Example
564 ///
565 /// ```no_run
566 /// use monoio::io::AsyncWriteRent;
567 ///
568 /// #[monoio::main]
569 /// async fn main() -> std::io::Result<()> {
570 /// let mut file = monoio::fs::File::create("example.txt").await?;
571 /// let (res, buf) = file.write("Hello, world").await;
572 /// res?;
573 /// Ok(())
574 /// }
575 /// ```
576 async fn write<T: IoBuf>(&mut self, buf: T) -> crate::BufResult<usize, T> {
577 self.write(buf).await
578 }
579
580 /// This function attempts to write the entire contents of `buf_vec`, but the write may not
581 /// fully succeed, and it might also result in an error. The bytes will be written starting at
582 /// the current file pointer.
583 ///
584 /// # Return
585 ///
586 /// The method returns the result of the operation along with the same array of buffers passed
587 /// as an argument. A return value of `0` typically indicates that the underlying file can no
588 /// longer accept bytes and likely won't be able to in the future, or that the provided buffer
589 /// is empty.
590 ///
591 /// # Platform-specific behavior
592 ///
593 /// - On windows
594 /// - due to windows does not have syscall like `writev`, so the implement of this function
595 /// on windows is by internally calling the `WriteFile` syscall to write each buffer into
596 /// file.
597 ///
598 /// # Errors
599 ///
600 /// Each `write` call may result in an I/O error, indicating the operation couldn't be
601 /// completed. If an error occurs, no bytes from the buffer were written to the file.
602 ///
603 /// It is **not** considered an error if the entire buffer could not be written to the file.
604 ///
605 /// # Example
606 ///
607 /// ```no_run
608 /// use monoio::io::AsyncWriteRent;
609 ///
610 /// #[monoio::main]
611 /// async fn main() -> std::io::Result<()> {
612 /// let buf_vec = monoio::buf::VecBuf::from(vec![
613 /// "Hello".to_owned().into_bytes(),
614 /// "World".to_owned().into_bytes(),
615 /// ]);
616 /// let mut file = monoio::fs::File::create("example.txt").await?;
617 /// let (res, buf_vec) = file.writev(buf_vec).await;
618 /// res?;
619 /// Ok(())
620 /// }
621 /// ```
622 async fn writev<T: crate::buf::IoVecBuf>(&mut self, buf_vec: T) -> crate::BufResult<usize, T> {
623 self.write_vectored(buf_vec).await
624 }
625
626 /// Flushes the file, ensuring that all buffered contents are written to their destination.
627 ///
628 /// # Platform-specific behavior
629 ///
630 /// Since the `File` structure doesn't contain any internal buffers, this function is currently
631 /// a no-op.
632 async fn flush(&mut self) -> std::io::Result<()> {
633 self.flush().await
634 }
635
636 /// This function will call [`flush`] inside.
637 async fn shutdown(&mut self) -> std::io::Result<()> {
638 self.flush().await
639 }
640}
641
642impl AsyncWriteRentAt for File {
643 fn write_at<T: IoBuf>(
644 &mut self,
645 buf: T,
646 pos: usize,
647 ) -> impl Future<Output = BufResult<usize, T>> {
648 File::write_at(self, buf, pos as u64)
649 }
650}
651
652impl AsyncReadRent for File {
653 /// Reads bytes from the file at the current file pointer into the specified buffer, returning
654 /// the number of bytes read.
655 ///
656 /// # Return
657 ///
658 /// The method returns a tuple with the result of the operation and the same buffer passed as an
659 /// argument.
660 ///
661 /// If the method returns [`(Ok(n), buf)`], a non-zero `n` means the buffer has been filled with
662 /// `n` bytes of data from the file. If `n` is `0`, it indicates one of the following:
663 ///
664 /// 1. The current file pointer is at the end of the file.
665 /// 2. The provided buffer was 0 bytes in length.
666 ///
667 /// It is not an error if `n` is smaller than the buffer size, even if there is enough data in
668 /// the file to fill the buffer.
669 ///
670 /// # Platform-specific behavior
671 ///
672 /// - On Unix and Windows (without the `iouring` feature enabled or not support the `iouring`):
673 /// - If the sync feature is enabled and the thread pool is attached, this operation will be
674 /// executed on the blocking thread pool, preventing it from blocking the current thread.
675 /// - If the sync feature is enabled but the thread pool is not attached, or if the sync
676 /// feature is disabled, the operation will be executed on the local thread, blocking the
677 /// current thread.
678 ///
679 /// - On Linux (with iouring enabled and supported):
680 ///
681 /// This operation will use io-uring to execute the task asynchronously.
682 ///
683 /// # Errors
684 ///
685 /// If an I/O or other error occurs, an error variant will be returned, and the buffer will also
686 /// be returned.
687 ///
688 /// # Example
689 ///
690 /// ```no_run
691 /// use monoio::io::AsyncReadRent;
692 ///
693 /// #[monoio::main]
694 /// async fn main() -> std::io::Result<()> {
695 /// let buf = Vec::with_capacity(1024);
696 /// let mut file = monoio::fs::File::open("example.txt").await?;
697 /// let (res, buf) = file.read(buf).await;
698 /// println!("bytes read: {}", res?);
699 /// Ok(())
700 /// }
701 /// ```
702 async fn read<T: IoBufMut>(&mut self, buf: T) -> crate::BufResult<usize, T> {
703 self.read(buf).await
704 }
705
706 /// Read some bytes at the specified offset from the file into the specified
707 /// array of buffers, returning how many bytes were read.
708 ///
709 /// # Return
710 ///
711 /// The method returns the operation result and the same array of buffers
712 /// passed as an argument.
713 ///
714 /// If the method returns [`Ok(n)`], then the read was successful. A nonzero
715 /// `n` value indicates that the buffers have been filled with `n` bytes of
716 /// data from the file. If `n` is `0`, then one of the following happened:
717 ///
718 /// 1. The specified offset is the end of the file.
719 /// 2. The buffers specified were 0 bytes in length.
720 ///
721 /// It is not an error if the returned value `n` is smaller than the buffer
722 /// size, even when the file contains enough data to fill the buffer.
723 ///
724 /// # Platform-specific behavior
725 ///
726 /// - On windows
727 /// - due to windows does not have syscall like `readv`, so the implement of this function
728 /// on windows is by internally calling the `ReadFile` syscall to fill each buffer.
729 ///
730 /// - On Unix and Windows (without the `iouring` feature enabled or not support the `iouring`):
731 /// - If the sync feature is enabled and the thread pool is attached, this operation will be
732 /// executed on the blocking thread pool, preventing it from blocking the current thread.
733 /// - If the sync feature is enabled but the thread pool is not attached, or if the sync
734 /// feature is disabled, the operation will be executed on the local thread, blocking the
735 /// current thread.
736 ///
737 /// - On Linux (with iouring enabled and supported):
738 ///
739 /// This operation will use io-uring to execute the task asynchronously.
740 ///
741 ///
742 /// # Errors
743 ///
744 /// If this function encounters any form of I/O or other error, an error
745 /// variant will be returned. The buffer is returned on error.
746 ///
747 /// # Example
748 ///
749 /// ```no_run
750 /// use monoio::io::AsyncReadRent;
751 ///
752 /// #[monoio::main]
753 /// async fn main() -> std::io::Result<()> {
754 /// let mut file = monoio::fs::File::open("example.txt").await?;
755 /// let buffers = monoio::buf::VecBuf::from(vec![
756 /// Vec::<u8>::with_capacity(10),
757 /// Vec::<u8>::with_capacity(10),
758 /// ]);
759 ///
760 /// let (res, buffer) = file.readv(buffers).await;
761 ///
762 /// println!("bytes read: {}", res?);
763 /// Ok(())
764 /// }
765 /// ```
766 async fn readv<T: crate::buf::IoVecBufMut>(&mut self, buf: T) -> crate::BufResult<usize, T> {
767 self.read_vectored(buf).await
768 }
769}
770
771impl AsyncReadRentAt for File {
772 fn read_at<T: IoBufMut>(
773 &mut self,
774 buf: T,
775 pos: usize,
776 ) -> impl Future<Output = BufResult<usize, T>> {
777 File::read_at(self, buf, pos as u64)
778 }
779}