sys_traits/
boxed.rs

1use std::borrow::Cow;
2use std::ffi::OsStr;
3use std::io;
4use std::path::Path;
5use std::time::SystemTime;
6
7use crate::BaseFsMetadata;
8use crate::BaseFsOpen;
9use crate::BaseFsReadDir;
10use crate::FileType;
11use crate::FsDirEntry;
12use crate::FsFile;
13use crate::FsFileAsRaw;
14use crate::FsFileIsTerminal;
15use crate::FsFileLock;
16use crate::FsFileLockMode;
17use crate::FsFileSetLen;
18use crate::FsFileSetPermissions;
19use crate::FsFileSetTimes;
20use crate::FsFileSyncAll;
21use crate::FsFileSyncData;
22use crate::FsFileTimes;
23use crate::FsMetadataValue;
24use crate::OpenOptions;
25
26// == FsOpenBoxed ==
27
28pub struct BoxedFsFile(pub Box<dyn FsFile + 'static>);
29
30impl io::Read for BoxedFsFile {
31  #[inline]
32  fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
33    self.0.read(buf)
34  }
35}
36
37impl io::Seek for BoxedFsFile {
38  #[inline]
39  fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
40    self.0.seek(pos)
41  }
42}
43
44impl io::Write for BoxedFsFile {
45  #[inline]
46  fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
47    self.0.write(buf)
48  }
49
50  #[inline]
51  fn flush(&mut self) -> io::Result<()> {
52    self.0.flush()
53  }
54}
55
56impl FsFileAsRaw for BoxedFsFile {
57  #[cfg(windows)]
58  #[inline]
59  fn fs_file_as_raw_handle(&self) -> Option<std::os::windows::io::RawHandle> {
60    self.0.fs_file_as_raw_handle()
61  }
62
63  /// Returns the raw file descriptor on Unix platforms only
64  /// or `None` when the file doesn't support it (ex. in-memory file system).
65  #[cfg(unix)]
66  #[inline]
67  fn fs_file_as_raw_fd(&self) -> Option<std::os::fd::RawFd> {
68    self.0.fs_file_as_raw_fd()
69  }
70}
71
72impl FsFileIsTerminal for BoxedFsFile {
73  #[inline]
74  fn fs_file_is_terminal(&self) -> bool {
75    self.0.fs_file_is_terminal()
76  }
77}
78
79impl FsFileLock for BoxedFsFile {
80  #[inline]
81  fn fs_file_lock(&mut self, mode: FsFileLockMode) -> io::Result<()> {
82    self.0.fs_file_lock(mode)
83  }
84  #[inline]
85  fn fs_file_try_lock(&mut self, mode: FsFileLockMode) -> io::Result<()> {
86    self.0.fs_file_try_lock(mode)
87  }
88  #[inline]
89  fn fs_file_unlock(&mut self) -> io::Result<()> {
90    self.0.fs_file_unlock()
91  }
92}
93
94impl FsFileSetLen for BoxedFsFile {
95  #[inline]
96  fn fs_file_set_len(&mut self, size: u64) -> io::Result<()> {
97    self.0.fs_file_set_len(size)
98  }
99}
100
101impl FsFileSetPermissions for BoxedFsFile {
102  #[inline]
103  fn fs_file_set_permissions(&mut self, perm: u32) -> io::Result<()> {
104    self.0.fs_file_set_permissions(perm)
105  }
106}
107
108impl FsFileSetTimes for BoxedFsFile {
109  #[inline]
110  fn fs_file_set_times(&mut self, times: FsFileTimes) -> io::Result<()> {
111    self.0.fs_file_set_times(times)
112  }
113}
114
115impl FsFileSyncAll for BoxedFsFile {
116  #[inline]
117  fn fs_file_sync_all(&mut self) -> io::Result<()> {
118    self.0.fs_file_sync_all()
119  }
120}
121
122impl FsFileSyncData for BoxedFsFile {
123  #[inline]
124  fn fs_file_sync_data(&mut self) -> io::Result<()> {
125    self.0.fs_file_sync_data()
126  }
127}
128
129impl FsFile for BoxedFsFile {}
130
131pub trait FsOpenBoxed {
132  fn fs_open_boxed(
133    &self,
134    path: &Path,
135    open_options: &OpenOptions,
136  ) -> io::Result<BoxedFsFile>;
137}
138
139impl<TFile: FsFile + 'static, T: BaseFsOpen<File = TFile>> FsOpenBoxed for T {
140  fn fs_open_boxed(
141    &self,
142    path: &Path,
143    open_options: &OpenOptions,
144  ) -> io::Result<BoxedFsFile> {
145    self
146      .base_fs_open(path, open_options)
147      .map(|file| BoxedFsFile(Box::new(file)))
148  }
149}
150
151// == FsMetadataBoxed ==
152
153#[derive(Debug)]
154pub struct BoxedFsMetadataValue(pub Box<dyn FsMetadataValue>);
155
156impl BoxedFsMetadataValue {
157  pub fn new<T: FsMetadataValue + 'static>(metadata: T) -> Self {
158    Self(Box::new(metadata))
159  }
160}
161
162impl FsMetadataValue for BoxedFsMetadataValue {
163  #[inline]
164  fn file_type(&self) -> FileType {
165    self.0.file_type()
166  }
167
168  #[inline]
169  fn len(&self) -> u64 {
170    self.0.len()
171  }
172
173  #[inline]
174  fn accessed(&self) -> io::Result<SystemTime> {
175    self.0.accessed()
176  }
177
178  #[inline]
179  fn changed(&self) -> io::Result<SystemTime> {
180    self.0.changed()
181  }
182
183  #[inline]
184  fn created(&self) -> io::Result<SystemTime> {
185    self.0.created()
186  }
187
188  #[inline]
189  fn modified(&self) -> io::Result<SystemTime> {
190    self.0.modified()
191  }
192
193  #[inline]
194  fn dev(&self) -> io::Result<u64> {
195    self.0.dev()
196  }
197
198  #[inline]
199  fn ino(&self) -> io::Result<u64> {
200    self.0.ino()
201  }
202
203  #[inline]
204  fn mode(&self) -> io::Result<u32> {
205    self.0.mode()
206  }
207
208  #[inline]
209  fn nlink(&self) -> io::Result<u64> {
210    self.0.nlink()
211  }
212
213  #[inline]
214  fn uid(&self) -> io::Result<u32> {
215    self.0.uid()
216  }
217
218  #[inline]
219  fn gid(&self) -> io::Result<u32> {
220    self.0.gid()
221  }
222
223  #[inline]
224  fn rdev(&self) -> io::Result<u64> {
225    self.0.rdev()
226  }
227
228  #[inline]
229  fn blksize(&self) -> io::Result<u64> {
230    self.0.blksize()
231  }
232
233  #[inline]
234  fn blocks(&self) -> io::Result<u64> {
235    self.0.blocks()
236  }
237
238  #[inline]
239  fn is_block_device(&self) -> io::Result<bool> {
240    self.0.is_block_device()
241  }
242
243  #[inline]
244  fn is_char_device(&self) -> io::Result<bool> {
245    self.0.is_char_device()
246  }
247
248  #[inline]
249  fn is_fifo(&self) -> io::Result<bool> {
250    self.0.is_fifo()
251  }
252
253  #[inline]
254  fn is_socket(&self) -> io::Result<bool> {
255    self.0.is_socket()
256  }
257
258  #[inline]
259  fn file_attributes(&self) -> io::Result<u32> {
260    self.0.file_attributes()
261  }
262}
263
264pub trait FsMetadataBoxed {
265  fn fs_metadata_boxed(&self, path: &Path) -> io::Result<BoxedFsMetadataValue>;
266  fn fs_symlink_metadata_boxed(
267    &self,
268    path: &Path,
269  ) -> io::Result<BoxedFsMetadataValue>;
270}
271
272impl<T: BaseFsMetadata + 'static> FsMetadataBoxed for T {
273  fn fs_metadata_boxed(&self, path: &Path) -> io::Result<BoxedFsMetadataValue> {
274    let metadata = self.base_fs_metadata(path)?;
275    Ok(BoxedFsMetadataValue(Box::new(metadata)))
276  }
277
278  fn fs_symlink_metadata_boxed(
279    &self,
280    path: &Path,
281  ) -> io::Result<BoxedFsMetadataValue> {
282    let metadata = self.base_fs_symlink_metadata(path)?;
283    Ok(BoxedFsMetadataValue(Box::new(metadata)))
284  }
285}
286
287// == FsReadDirBoxed ==
288
289#[derive(Debug)]
290struct MappedMetadataFsDirEntry<T: FsDirEntry + 'static>(T);
291
292impl<T: FsDirEntry + 'static> FsDirEntry for MappedMetadataFsDirEntry<T> {
293  type Metadata = BoxedFsMetadataValue;
294
295  #[inline]
296  fn file_name(&self) -> Cow<OsStr> {
297    self.0.file_name()
298  }
299
300  #[inline]
301  fn file_type(&self) -> io::Result<FileType> {
302    self.0.file_type()
303  }
304
305  #[inline]
306  fn metadata(&self) -> io::Result<Self::Metadata> {
307    self
308      .0
309      .metadata()
310      .map(|metadata| BoxedFsMetadataValue(Box::new(metadata)))
311  }
312
313  #[inline]
314  fn path(&self) -> Cow<Path> {
315    self.0.path()
316  }
317}
318
319#[derive(Debug)]
320pub struct BoxedFsDirEntry(
321  pub Box<dyn FsDirEntry<Metadata = BoxedFsMetadataValue>>,
322);
323
324impl BoxedFsDirEntry {
325  pub fn new<T: FsDirEntry + 'static>(entry: T) -> Self {
326    Self(Box::new(MappedMetadataFsDirEntry(entry)))
327  }
328}
329
330impl FsDirEntry for BoxedFsDirEntry {
331  type Metadata = BoxedFsMetadataValue;
332
333  #[inline]
334  fn file_name(&self) -> Cow<OsStr> {
335    self.0.file_name()
336  }
337
338  #[inline]
339  fn file_type(&self) -> io::Result<FileType> {
340    self.0.file_type()
341  }
342
343  #[inline]
344  fn metadata(&self) -> io::Result<Self::Metadata> {
345    self.0.metadata()
346  }
347
348  #[inline]
349  fn path(&self) -> Cow<Path> {
350    self.0.path()
351  }
352}
353
354pub trait FsReadDirBoxed {
355  fn fs_read_dir_boxed(
356    &self,
357    path: &Path,
358  ) -> io::Result<Box<dyn Iterator<Item = io::Result<BoxedFsDirEntry>> + '_>>;
359}
360
361impl<T: BaseFsReadDir> FsReadDirBoxed for T {
362  fn fs_read_dir_boxed(
363    &self,
364    path: &Path,
365  ) -> io::Result<Box<dyn Iterator<Item = io::Result<BoxedFsDirEntry>> + '_>>
366  {
367    let iter = self.base_fs_read_dir(path)?;
368    Ok(Box::new(
369      iter.map(|result| result.map(BoxedFsDirEntry::new)),
370    ))
371  }
372}