Coverage Report

Created: 2026-06-28 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cap-primitives-3.4.5/src/fs/file.rs
Line
Count
Source
1
use std::io;
2
3
/// Unix-specific extensions to [`fs::File`].
4
#[cfg(unix)]
5
pub trait FileExt {
6
    /// Reads a number of bytes starting from a given offset.
7
    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
8
9
    /// Like `read_at`, except that it reads into a slice of buffers.
10
    #[cfg(unix_file_vectored_at)]
11
0
    fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
12
0
        default_read_vectored(|b| self.read_at(b, offset), bufs)
13
0
    }
14
15
    /// Reads the exact number of bytes required to fill `buf` from the given offset.
16
0
    fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
17
0
        while !buf.is_empty() {
18
0
            match self.read_at(buf, offset) {
19
0
                Ok(0) => break,
20
0
                Ok(n) => {
21
0
                    let tmp = buf;
22
0
                    buf = &mut tmp[n..];
23
0
                    offset += n as u64;
24
0
                }
25
0
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
26
0
                Err(e) => return Err(e),
27
            }
28
        }
29
0
        if !buf.is_empty() {
30
0
            Err(io::Error::new(
31
0
                io::ErrorKind::UnexpectedEof,
32
0
                "failed to fill whole buffer",
33
0
            ))
34
        } else {
35
0
            Ok(())
36
        }
37
0
    }
38
39
    /// Writes a number of bytes starting from a given offset.
40
    fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
41
42
    /// Like `write_at`, except that it writes from a slice of buffers.
43
    #[cfg(unix_file_vectored_at)]
44
0
    fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
45
0
        default_write_vectored(|b| self.write_at(b, offset), bufs)
46
0
    }
47
48
    /// Attempts to write an entire buffer starting from a given offset.
49
0
    fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
50
0
        while !buf.is_empty() {
51
0
            match self.write_at(buf, offset) {
52
                Ok(0) => {
53
0
                    return Err(io::Error::new(
54
0
                        io::ErrorKind::WriteZero,
55
0
                        "failed to write whole buffer",
56
0
                    ));
57
                }
58
0
                Ok(n) => {
59
0
                    buf = &buf[n..];
60
0
                    offset += n as u64
61
                }
62
0
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
63
0
                Err(e) => return Err(e),
64
            }
65
        }
66
0
        Ok(())
67
0
    }
68
}
69
70
#[cfg(unix_file_vectored_at)]
71
0
fn default_read_vectored<F>(read: F, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize>
72
0
where
73
0
    F: FnOnce(&mut [u8]) -> io::Result<usize>,
74
{
75
0
    let buf = bufs
76
0
        .iter_mut()
77
0
        .find(|b| !b.is_empty())
78
0
        .map_or(&mut [][..], |b| &mut **b);
79
0
    read(buf)
80
0
}
81
82
#[cfg(unix_file_vectored_at)]
83
0
fn default_write_vectored<F>(write: F, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>
84
0
where
85
0
    F: FnOnce(&[u8]) -> io::Result<usize>,
86
{
87
0
    let buf = bufs
88
0
        .iter()
89
0
        .find(|b| !b.is_empty())
90
0
        .map_or(&[][..], |b| &**b);
91
0
    write(buf)
92
0
}
93
94
/// WASI-specific extensions to [`fs::File`].
95
#[cfg(target_os = "wasi")]
96
pub trait FileExt {
97
    /// Reads a number of bytes starting from a given offset.
98
    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
99
        let bufs = &mut [io::IoSliceMut::new(buf)];
100
        self.read_vectored_at(bufs, offset)
101
    }
102
103
    /// Reads a number of bytes starting from a given offset.
104
    fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize>;
105
106
    /// Reads the exact number of byte required to fill `buf` from the given offset.
107
    fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
108
        while !buf.is_empty() {
109
            match self.read_at(buf, offset) {
110
                Ok(0) => break,
111
                Ok(n) => {
112
                    let tmp = buf;
113
                    buf = &mut tmp[n..];
114
                    offset += n as u64;
115
                }
116
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
117
                Err(e) => return Err(e),
118
            }
119
        }
120
        if !buf.is_empty() {
121
            Err(io::Error::new(
122
                io::ErrorKind::UnexpectedEof,
123
                "failed to fill whole buffer",
124
            ))
125
        } else {
126
            Ok(())
127
        }
128
    }
129
130
    /// Writes a number of bytes starting from a given offset.
131
    fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
132
        let bufs = &[io::IoSlice::new(buf)];
133
        self.write_vectored_at(bufs, offset)
134
    }
135
136
    /// Writes a number of bytes starting from a given offset.
137
    fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize>;
138
139
    /// Attempts to write an entire buffer starting from a given offset.
140
    fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
141
        while !buf.is_empty() {
142
            match self.write_at(buf, offset) {
143
                Ok(0) => {
144
                    return Err(io::Error::new(
145
                        io::ErrorKind::WriteZero,
146
                        "failed to write whole buffer",
147
                    ));
148
                }
149
                Ok(n) => {
150
                    buf = &buf[n..];
151
                    offset += n as u64
152
                }
153
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
154
                Err(e) => return Err(e),
155
            }
156
        }
157
        Ok(())
158
    }
159
160
    /// Adjust the flags associated with this file.
161
    fn fdstat_set_flags(&self, flags: u16) -> io::Result<()>;
162
163
    /// Adjust the rights associated with this file.
164
    fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()>;
165
166
    /// Provide file advisory information on a file descriptor.
167
    fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()>;
168
169
    /// Force the allocation of space in a file.
170
    fn allocate(&self, offset: u64, len: u64) -> io::Result<()>;
171
172
    /// Create a directory.
173
    fn create_directory<P: AsRef<std::path::Path>>(&self, dir: P) -> io::Result<()>;
174
175
    /// Read the contents of a symbolic link.
176
    fn read_link<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<std::path::PathBuf>;
177
178
    /// Return the attributes of a file or directory.
179
    fn metadata_at<P: AsRef<std::path::Path>>(
180
        &self,
181
        lookup_flags: u32,
182
        path: P,
183
    ) -> io::Result<std::fs::Metadata>;
184
185
    /// Unlink a file.
186
    fn remove_file<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<()>;
187
188
    /// Remove a directory.
189
    fn remove_directory<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<()>;
190
}
191
192
/// Windows-specific extensions to [`fs::File`].
193
#[cfg(windows)]
194
pub trait FileExt {
195
    /// Seeks to a given position and reads a number of bytes.
196
    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
197
198
    /// Seeks to a given position and writes a number of bytes.
199
    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
200
}