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}