io_arrays/
rustix.rs

1//! Functions for implementing [`ReadAt`] and [`WriteAt`] for file-like types
2//! which implement [`AsFilelike`] on Posix-ish platforms.
3//!
4//! [`ReadAt`]: crate::ReadAt
5//! [`WriteAt`]: crate::WriteAt
6
7use crate::Metadata;
8use io_lifetimes::AsFilelike;
9use std::fs::File;
10use std::io::{self, IoSlice, IoSliceMut};
11#[cfg(unix)]
12use std::os::unix::fs::MetadataExt;
13#[cfg(target_os = "wasi")]
14use std::os::unix::fs::MetadataExt;
15use system_interface::fs::FileIoExt;
16#[cfg(feature = "io-streams")]
17use {
18    crate::owned_streamer::OwnedStreamer,
19    cap_fs_ext::{OpenOptions, Reopen},
20    io_streams::StreamReader,
21    std::io::SeekFrom,
22};
23
24/// Implement [`crate::Array::metadata`].
25#[inline]
26pub fn metadata<'a, Filelike: AsFilelike>(filelike: &Filelike) -> io::Result<Metadata> {
27    filelike
28        .as_filelike_view::<File>()
29        .metadata()
30        .map(|meta| Metadata {
31            len: meta.len(),
32            blksize: meta.blksize(),
33        })
34}
35
36/// Implement [`crate::ReadAt::read_at`].
37#[inline]
38pub fn read_at<'a, Filelike: AsFilelike>(
39    filelike: &Filelike,
40    buf: &mut [u8],
41    offset: u64,
42) -> io::Result<usize> {
43    <File as FileIoExt>::read_at(&filelike.as_filelike_view::<File>(), buf, offset)
44}
45
46/// Implement [`crate::ReadAt::read_exact_at`].
47#[inline]
48pub fn read_exact_at<'a, Filelike: AsFilelike>(
49    filelike: &Filelike,
50    buf: &mut [u8],
51    offset: u64,
52) -> io::Result<()> {
53    <File as FileIoExt>::read_exact_at(&filelike.as_filelike_view::<File>(), buf, offset)
54}
55
56/// Implement [`crate::ReadAt::read_vectored_at`].
57#[inline]
58pub fn read_vectored_at<'a, Filelike: AsFilelike>(
59    filelike: &Filelike,
60    bufs: &mut [IoSliceMut],
61    offset: u64,
62) -> io::Result<usize> {
63    <File as FileIoExt>::read_vectored_at(&filelike.as_filelike_view::<File>(), bufs, offset)
64}
65
66/// Implement [`crate::ReadAt::read_exact_vectored_at`].
67#[inline]
68pub fn read_exact_vectored_at<'a, Filelike: AsFilelike>(
69    filelike: &Filelike,
70    bufs: &mut [IoSliceMut],
71    offset: u64,
72) -> io::Result<()> {
73    <File as FileIoExt>::read_exact_vectored_at(&filelike.as_filelike_view::<File>(), bufs, offset)
74}
75
76/// Implement [`crate::ReadAt::is_read_vectored_at`].
77#[inline]
78pub fn is_read_vectored_at<'a, Filelike: AsFilelike>(filelike: &Filelike) -> bool {
79    <File as FileIoExt>::is_read_vectored_at(&filelike.as_filelike_view::<File>())
80}
81
82/// Implement [`crate::ReadAt::read_via_stream_at`].
83#[cfg(feature = "io-streams")]
84pub fn read_via_stream_at<'a, Filelike: AsFilelike>(
85    filelike: &Filelike,
86    offset: u64,
87) -> io::Result<StreamReader> {
88    // On operating systems where we can do so, reopen the file so that we
89    // get an independent current position.
90    let view = filelike.as_filelike_view::<File>();
91    if let Ok(file) = view.reopen(OpenOptions::new().read(true)) {
92        if offset != 0 {
93            file.seek(SeekFrom::Start(offset))?;
94        }
95        return Ok(StreamReader::file(file));
96    }
97
98    // Otherwise, manually stream the file.
99    StreamReader::piped_thread(Box::new(OwnedStreamer::new(view.try_clone()?, offset)))
100}
101
102/// Implement [`crate::WriteAt::write_at`].
103#[inline]
104pub fn write_at<'a, Filelike: AsFilelike>(
105    filelike: &Filelike,
106    buf: &[u8],
107    offset: u64,
108) -> io::Result<usize> {
109    <File as FileIoExt>::write_at(&filelike.as_filelike_view::<File>(), buf, offset)
110}
111
112/// Implement [`crate::WriteAt::write_all_at`].
113#[inline]
114pub fn write_all_at<'a, Filelike: AsFilelike>(
115    filelike: &Filelike,
116    buf: &[u8],
117    offset: u64,
118) -> io::Result<()> {
119    <File as FileIoExt>::write_all_at(&filelike.as_filelike_view::<File>(), buf, offset)
120}
121
122/// Implement [`crate::WriteAt::write_vectored_at`].
123#[inline]
124pub fn write_vectored_at<'a, Filelike: AsFilelike>(
125    filelike: &Filelike,
126    bufs: &[IoSlice],
127    offset: u64,
128) -> io::Result<usize> {
129    <File as FileIoExt>::write_vectored_at(&filelike.as_filelike_view::<File>(), bufs, offset)
130}
131
132/// Implement [`crate::WriteAt::write_all_vectored_at`].
133#[inline]
134pub fn write_all_vectored_at<'a, Filelike: AsFilelike>(
135    filelike: &Filelike,
136    bufs: &mut [IoSlice],
137    offset: u64,
138) -> io::Result<()> {
139    <File as FileIoExt>::write_all_vectored_at(&filelike.as_filelike_view::<File>(), bufs, offset)
140}
141
142/// Implement [`crate::WriteAt::is_write_vectored_at`].
143#[inline]
144pub fn is_write_vectored_at<'a, Filelike: AsFilelike>(filelike: &Filelike) -> bool {
145    <File as FileIoExt>::is_write_vectored_at(&filelike.as_filelike_view::<File>())
146}