1use super::*;
2use std::path::PathBuf;
3
4pub const DEFAULT_READ_MAX_BYTES: usize = 16 * 1024 * 1024;
6
7pub const DEFAULT_READ_STREAM_CHUNK_BYTES: usize = 1024 * 1024;
9
10pub const DEFAULT_READ_ALLV_MAX_TOTAL_BYTES: usize = DEFAULT_READ_MAX_BYTES;
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub struct ReadStreamOptions {
16 chunk_size: usize,
17}
18
19impl ReadStreamOptions {
20 pub const fn new() -> Self {
21 Self {
22 chunk_size: DEFAULT_READ_STREAM_CHUNK_BYTES,
23 }
24 }
25
26 pub const fn chunk_size(mut self, bytes: usize) -> Self {
31 self.chunk_size = bytes;
32 self
33 }
34
35 pub const fn chunk_size_bytes(self) -> usize {
36 self.chunk_size
37 }
38}
39
40impl Default for ReadStreamOptions {
41 fn default() -> Self {
42 Self::new()
43 }
44}
45
46pub const DEFAULT_DIRECTORY_MAX_ENTRIES: usize = 100_000;
48
49pub const DEFAULT_DIRECTORY_MAX_PATH_BYTES: usize = 16 * 1024 * 1024;
51
52pub const DEFAULT_WALK_MAX_DEPTH: usize = 128;
54
55#[derive(Clone, Copy, Debug, PartialEq, Eq)]
57pub struct ReadDirOptions {
58 max_entries: usize,
59 max_path_bytes: usize,
60}
61
62impl ReadDirOptions {
63 pub const fn new() -> Self {
64 Self {
65 max_entries: DEFAULT_DIRECTORY_MAX_ENTRIES,
66 max_path_bytes: DEFAULT_DIRECTORY_MAX_PATH_BYTES,
67 }
68 }
69
70 pub const fn unlimited() -> Self {
72 Self {
73 max_entries: usize::MAX,
74 max_path_bytes: usize::MAX,
75 }
76 }
77
78 pub const fn max_entries(mut self, entries: usize) -> Self {
79 self.max_entries = entries;
80 self
81 }
82
83 pub const fn max_path_bytes(mut self, bytes: usize) -> Self {
84 self.max_path_bytes = bytes;
85 self
86 }
87
88 pub const fn entry_limit(self) -> usize {
89 self.max_entries
90 }
91
92 pub const fn path_byte_limit(self) -> usize {
93 self.max_path_bytes
94 }
95}
96
97impl Default for ReadDirOptions {
98 fn default() -> Self {
99 Self::new()
100 }
101}
102
103#[bitfields::bitfield(u8)]
104#[derive(PartialEq, Eq)]
105struct WalkFlags {
106 truncate: bool,
107 #[bits(7)]
108 _reserved: u8,
109}
110
111#[repr(transparent)]
115#[derive(Clone, Copy, Debug, PartialEq, Eq)]
116pub struct DepthLimit(std::num::NonZeroU8);
117
118impl DepthLimit {
119 pub const fn new(depth: usize) -> Self {
121 let encoded = if depth <= 200 { (depth + 1) as u8 } else { 202 };
122 Self(std::num::NonZeroU8::new(encoded).expect("depth encoding is nonzero"))
123 }
124 pub const fn unlimited() -> Self {
126 Self::new(usize::MAX)
127 }
128 pub const fn get(self) -> usize {
130 if self.is_unlimited() {
131 usize::MAX
132 } else {
133 self.0.get() as usize - 1
134 }
135 }
136 pub const fn is_unlimited(self) -> bool {
138 self.0.get() == 202
139 }
140}
141
142#[derive(Clone, Copy, Debug, PartialEq, Eq)]
144pub struct WalkOptions {
145 directory: ReadDirOptions,
146 max_depth: DepthLimit,
147 flags: WalkFlags,
148}
149
150impl WalkOptions {
151 pub const fn new() -> Self {
152 Self {
153 directory: ReadDirOptions::new(),
154 max_depth: DepthLimit::new(DEFAULT_WALK_MAX_DEPTH),
155 flags: WalkFlags::new(),
156 }
157 }
158
159 pub const fn unlimited() -> Self {
161 Self {
162 directory: ReadDirOptions::unlimited(),
163 max_depth: DepthLimit::unlimited(),
164 flags: WalkFlags::new(),
165 }
166 }
167
168 pub const fn max_entries(mut self, entries: usize) -> Self {
169 self.directory = self.directory.max_entries(entries);
170 self
171 }
172
173 pub const fn max_path_bytes(mut self, bytes: usize) -> Self {
174 self.directory = self.directory.max_path_bytes(bytes);
175 self
176 }
177
178 pub const fn max_depth(mut self, depth: usize) -> Self {
181 self.max_depth = DepthLimit::new(depth);
182 self
183 }
184
185 pub const fn truncate_at_max_depth(mut self, truncate: bool) -> Self {
188 self.flags.set_truncate(truncate);
189 self
190 }
191
192 pub const fn entry_limit(self) -> usize {
193 self.directory.entry_limit()
194 }
195
196 pub const fn path_byte_limit(self) -> usize {
197 self.directory.path_byte_limit()
198 }
199
200 pub const fn depth_limit(self) -> usize {
202 self.max_depth.get()
203 }
204
205 pub const fn truncates_at_depth_limit(self) -> bool {
206 self.flags.truncate()
207 }
208}
209
210impl Default for WalkOptions {
211 fn default() -> Self {
212 Self::new()
213 }
214}
215
216pub const DEFAULT_READV_MAX_TOTAL_BYTES: usize = DEFAULT_READ_MAX_BYTES;
218
219#[derive(Debug, Clone, PartialEq, Eq)]
221pub struct FsReadResult {
222 pub offset: u64,
223 pub data: Vec<u8>,
224 pub eof: bool,
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
229pub struct ReadIntoResult {
230 pub offset: u64,
231 pub read: usize,
232 pub eof: bool,
233}
234
235#[derive(Debug, Clone, Copy, PartialEq, Eq)]
237pub struct WriteResult {
238 pub offset: u64,
239 pub written: usize,
240 pub stable: bool,
241}
242
243#[derive(Debug, Clone, Copy, PartialEq, Eq)]
245pub enum StreamCompletion {
246 Complete,
247 Stopped { next_offset: u64 },
248}
249
250#[derive(Debug, Clone, Copy, PartialEq, Eq)]
252pub enum TraversalCompletion {
253 Complete,
254 Stopped,
255}
256
257#[derive(Debug, Clone, Copy, PartialEq, Eq)]
260pub struct ResourceLimits {
261 pub max_read_bytes: usize,
265 pub stream_chunk_bytes: usize,
267 pub max_directory_entries: usize,
269 pub max_directory_path_bytes: usize,
271 pub max_walk_depth: usize,
273}
274
275impl Default for ResourceLimits {
276 fn default() -> Self {
277 Self {
278 max_read_bytes: DEFAULT_READ_MAX_BYTES,
279 stream_chunk_bytes: crate::api::DEFAULT_READ_STREAM_CHUNK_BYTES,
280 max_directory_entries: crate::api::DEFAULT_DIRECTORY_MAX_ENTRIES,
281 max_directory_path_bytes: crate::api::DEFAULT_DIRECTORY_MAX_PATH_BYTES,
282 max_walk_depth: crate::api::DEFAULT_WALK_MAX_DEPTH,
283 }
284 }
285}
286
287impl ResourceLimits {
288 pub fn directory_options(self) -> ReadDirOptions {
289 ReadDirOptions::new()
290 .max_entries(self.max_directory_entries)
291 .max_path_bytes(self.max_directory_path_bytes)
292 }
293
294 pub fn walk_options(self) -> crate::api::WalkOptions {
295 crate::api::WalkOptions::new()
296 .max_entries(self.max_directory_entries)
297 .max_path_bytes(self.max_directory_path_bytes)
298 .max_depth(self.max_walk_depth)
299 }
300}
301
302#[derive(Clone, Debug, PartialEq, Eq)]
304pub struct DirectoryListing {
305 pub path: PathBuf,
306 pub entries: Vec<DirEntry>,
307}