ex/
fs.rs

1// TODO: impl Debug to include extra info as well?
2
3use crate::io::{Error, Result};
4use crate::Wrapper;
5
6use std::fmt::Arguments;
7use std::io::{Read, Seek, SeekFrom, Write};
8use std::ops::{Deref, DerefMut};
9use std::path::{Path, PathBuf};
10use std::time::SystemTime;
11
12pub struct DirBuilder(::std::fs::DirBuilder);
13
14impl DirBuilder {
15    pub fn new() -> Self {
16        DirBuilder(::std::fs::DirBuilder::new())
17    }
18
19    pub fn recursive(&mut self, recursive: bool) -> &mut Self {
20        self.0.recursive(recursive);
21
22        self
23    }
24
25    pub fn create<P: AsRef<Path>>(&self, path: P) -> Result<()> {
26        let path = path.as_ref();
27
28        self.0.create(path).map_err(|x| {
29            Error::Filesystem(path.to_owned(), "creating directory", x)
30        })
31    }
32}
33
34impl Deref for DirBuilder {
35    type Target = ::std::fs::DirBuilder;
36
37    fn deref(&self) -> &Self::Target {
38        &self.0
39    }
40}
41
42impl DerefMut for DirBuilder {
43    fn deref_mut(&mut self) -> &mut Self::Target {
44        &mut self.0
45    }
46}
47
48impl Wrapper<::std::fs::DirBuilder> for DirBuilder {
49    fn into_inner(self) -> ::std::fs::DirBuilder {
50        self.0
51    }
52}
53
54pub struct DirEntry(::std::fs::DirEntry);
55
56impl DirEntry {
57    fn new(inner: ::std::fs::DirEntry) -> Self {
58        DirEntry(inner)
59    }
60
61    pub fn metadata(&self) -> Result<Metadata> {
62        self.0
63            .metadata()
64            .map(|x| Metadata::new(x, self.0.path()))
65            .map_err(|x| {
66                Error::Filesystem(self.0.path(), "getting metadata from", x)
67            })
68    }
69
70    pub fn file_type(&self) -> Result<FileType> {
71        self.0.file_type().map_err(|x| {
72            Error::Filesystem(self.0.path(), "getting the file type of", x)
73        })
74    }
75}
76
77impl Deref for DirEntry {
78    type Target = ::std::fs::DirEntry;
79
80    fn deref(&self) -> &Self::Target {
81        &self.0
82    }
83}
84
85impl DerefMut for DirEntry {
86    fn deref_mut(&mut self) -> &mut Self::Target {
87        &mut self.0
88    }
89}
90
91impl Wrapper<::std::fs::DirEntry> for DirEntry {
92    fn into_inner(self) -> ::std::fs::DirEntry {
93        self.0
94    }
95}
96
97pub struct File {
98    inner: ::std::fs::File,
99    // TODO: maybe Arc?
100    path: PathBuf,
101}
102
103impl File {
104    fn new(inner: ::std::fs::File, path: PathBuf) -> Self {
105        File { inner, path }
106    }
107
108    pub fn create<P: AsRef<Path>>(path: P) -> Result<File> {
109        let path = path.as_ref().to_owned();
110        let inner = ::std::fs::File::create(&path)
111            .map_err(|x| Error::Filesystem(path.clone(), "creating file", x))?;
112
113        Ok(Self::new(inner, path))
114    }
115
116    pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
117        let path = path.as_ref().to_owned();
118        let inner = ::std::fs::File::open(&path)
119            .map_err(|x| Error::Filesystem(path.clone(), "opening file", x))?;
120
121        Ok(Self::new(inner, path))
122    }
123
124    pub fn sync_all(&self) -> Result<()> {
125        self.inner
126            .sync_all()
127            .map_err(|x| Error::Filesystem(self.path.clone(), "synching", x))
128    }
129
130    pub fn sync_data(&self) -> Result<()> {
131        self.inner.sync_data().map_err(|x| {
132            Error::Filesystem(self.path.clone(), "synching data of", x)
133        })
134    }
135
136    pub fn set_len(&self, size: u64) -> Result<()> {
137        self.inner.set_len(size).map_err(|x| {
138            Error::Filesystem(self.path.clone(), "setting the length of", x)
139        })
140    }
141
142    pub fn metadata(&self) -> Result<Metadata> {
143        self.inner
144            .metadata()
145            .map(|x| Metadata::new(x, self.path.clone()))
146            .map_err(|x| {
147                Error::Filesystem(self.path.clone(), "getting metadata from", x)
148            })
149    }
150
151    pub fn try_clone(&self) -> Result<File> {
152        self.inner
153            .try_clone()
154            .map(|x| File::new(x, self.path.clone()))
155            .map_err(|x| {
156                Error::Filesystem(self.path.clone(), "cloning handle for", x)
157            })
158    }
159
160    pub fn set_permissions(&self, perm: Permissions) -> Result<()> {
161        // TODO: include `perm` in the error?
162        self.inner.set_permissions(perm).map_err(|x| {
163            Error::Filesystem(self.path.clone(), "setting permissions for", x)
164        })
165    }
166}
167
168impl Read for File {
169    fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
170        self.inner.read(buf).map_err(|x| {
171            ::std::io::Error::new(
172                x.kind(),
173                Error::Filesystem(self.path.clone(), "reading", x),
174            )
175        })
176    }
177
178    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> ::std::io::Result<usize> {
179        self.inner.read_to_end(buf).map_err(|x| {
180            ::std::io::Error::new(
181                x.kind(),
182                Error::Filesystem(self.path.clone(), "reading", x),
183            )
184        })
185    }
186
187    fn read_to_string(&mut self, buf: &mut String) -> ::std::io::Result<usize> {
188        self.inner.read_to_string(buf).map_err(|x| {
189            ::std::io::Error::new(
190                x.kind(),
191                Error::Filesystem(self.path.clone(), "reading", x),
192            )
193        })
194    }
195
196    fn read_exact(&mut self, buf: &mut [u8]) -> ::std::io::Result<()> {
197        self.inner.read_exact(buf).map_err(|x| {
198            ::std::io::Error::new(
199                x.kind(),
200                Error::Filesystem(self.path.clone(), "reading", x),
201            )
202        })
203    }
204}
205
206impl Write for File {
207    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
208        self.inner.write(buf).map_err(|x| {
209            ::std::io::Error::new(
210                x.kind(),
211                Error::Filesystem(self.path.clone(), "writing", x),
212            )
213        })
214    }
215
216    fn flush(&mut self) -> ::std::io::Result<()> {
217        self.inner.flush().map_err(|x| {
218            ::std::io::Error::new(
219                x.kind(),
220                Error::Filesystem(self.path.clone(), "flushing", x),
221            )
222        })
223    }
224
225    fn write_all(&mut self, buf: &[u8]) -> ::std::io::Result<()> {
226        self.inner.write_all(buf).map_err(|x| {
227            ::std::io::Error::new(
228                x.kind(),
229                Error::Filesystem(self.path.clone(), "writing", x),
230            )
231        })
232    }
233
234    fn write_fmt(&mut self, fmt: Arguments) -> ::std::io::Result<()> {
235        self.inner.write_fmt(fmt).map_err(|x| {
236            ::std::io::Error::new(
237                x.kind(),
238                Error::Filesystem(self.path.clone(), "writing", x),
239            )
240        })
241    }
242}
243
244impl Seek for File {
245    fn seek(&mut self, pos: SeekFrom) -> ::std::io::Result<u64> {
246        self.inner.seek(pos).map_err(|x| {
247            ::std::io::Error::new(
248                x.kind(),
249                Error::Filesystem(self.path.clone(), "seeking", x),
250            )
251        })
252    }
253}
254
255impl Deref for File {
256    type Target = ::std::fs::File;
257
258    fn deref(&self) -> &Self::Target {
259        &self.inner
260    }
261}
262
263impl DerefMut for File {
264    fn deref_mut(&mut self) -> &mut Self::Target {
265        &mut self.inner
266    }
267}
268
269impl Wrapper<::std::fs::File> for File {
270    fn into_inner(self) -> ::std::fs::File {
271        self.inner
272    }
273}
274
275pub type FileType = ::std::fs::FileType;
276
277pub struct Metadata {
278    inner: ::std::fs::Metadata,
279    path: PathBuf,
280}
281
282impl Metadata {
283    fn new(inner: ::std::fs::Metadata, path: PathBuf) -> Self {
284        Self { inner, path }
285    }
286
287    pub fn modified(&self) -> Result<SystemTime> {
288        self.inner.modified().map_err(|x| {
289            Error::Filesystem(
290                self.path.to_owned(),
291                "getting the modification time of",
292                x,
293            )
294        })
295    }
296
297    pub fn accessed(&self) -> Result<SystemTime> {
298        self.inner.accessed().map_err(|x| {
299            Error::Filesystem(
300                self.path.to_owned(),
301                "getting the access time of",
302                x,
303            )
304        })
305    }
306
307    pub fn created(&self) -> Result<SystemTime> {
308        self.inner.created().map_err(|x| {
309            Error::Filesystem(
310                self.path.to_owned(),
311                "getting the creation time of",
312                x,
313            )
314        })
315    }
316}
317
318impl Deref for Metadata {
319    type Target = ::std::fs::Metadata;
320
321    fn deref(&self) -> &Self::Target {
322        &self.inner
323    }
324}
325
326impl DerefMut for Metadata {
327    fn deref_mut(&mut self) -> &mut Self::Target {
328        &mut self.inner
329    }
330}
331
332impl Wrapper<::std::fs::Metadata> for Metadata {
333    fn into_inner(self) -> ::std::fs::Metadata {
334        self.inner
335    }
336}
337
338pub struct OpenOptions(::std::fs::OpenOptions);
339
340impl OpenOptions {
341    pub fn new() -> Self {
342        OpenOptions(::std::fs::OpenOptions::new())
343    }
344
345    pub fn read(&mut self, read: bool) -> &mut Self {
346        self.0.read(read);
347
348        self
349    }
350
351    pub fn write(&mut self, write: bool) -> &mut Self {
352        self.0.write(write);
353
354        self
355    }
356
357    pub fn append(&mut self, append: bool) -> &mut Self {
358        self.0.append(append);
359
360        self
361    }
362
363    pub fn truncate(&mut self, truncate: bool) -> &mut Self {
364        self.0.truncate(truncate);
365
366        self
367    }
368
369    pub fn create(&mut self, create: bool) -> &mut Self {
370        self.0.create(create);
371
372        self
373    }
374
375    pub fn create_new(&mut self, create_new: bool) -> &mut Self {
376        self.0.create_new(create_new);
377
378        self
379    }
380
381    pub fn open<P: AsRef<Path>>(&self, path: P) -> Result<File> {
382        let path = path.as_ref();
383
384        // TODO: include the opening options?
385        self.0
386            .open(path)
387            .map(|x| File::new(x, path.to_owned()))
388            .map_err(|x| Error::Filesystem(path.to_owned(), "opening file", x))
389    }
390}
391
392impl Deref for OpenOptions {
393    type Target = ::std::fs::OpenOptions;
394
395    fn deref(&self) -> &Self::Target {
396        &self.0
397    }
398}
399
400impl DerefMut for OpenOptions {
401    fn deref_mut(&mut self) -> &mut Self::Target {
402        &mut self.0
403    }
404}
405
406impl Wrapper<::std::fs::OpenOptions> for OpenOptions {
407    fn into_inner(self) -> ::std::fs::OpenOptions {
408        self.0
409    }
410}
411
412pub type Permissions = ::std::fs::Permissions;
413
414pub struct ReadDir {
415    inner: ::std::fs::ReadDir,
416    path: PathBuf,
417}
418
419impl ReadDir {
420    fn new(inner: ::std::fs::ReadDir, path: PathBuf) -> Self {
421        Self { inner, path }
422    }
423}
424
425impl Iterator for ReadDir {
426    type Item = Result<DirEntry>;
427
428    fn next(&mut self) -> Option<Self::Item> {
429        self.inner.next().map(|x| {
430            x.map(DirEntry::new).map_err(|err| {
431                Error::Filesystem(
432                    self.path.to_owned(),
433                    "iterating through directory",
434                    err,
435                )
436            })
437        })
438    }
439}
440
441impl Deref for ReadDir {
442    type Target = ::std::fs::ReadDir;
443
444    fn deref(&self) -> &Self::Target {
445        &self.inner
446    }
447}
448
449impl DerefMut for ReadDir {
450    fn deref_mut(&mut self) -> &mut Self::Target {
451        &mut self.inner
452    }
453}
454
455impl Wrapper<::std::fs::ReadDir> for ReadDir {
456    fn into_inner(self) -> ::std::fs::ReadDir {
457        self.inner
458    }
459}
460
461pub fn canonicalize<P: AsRef<Path>>(path: P) -> Result<PathBuf> {
462    let path = path.as_ref();
463
464    ::std::fs::canonicalize(path)
465        .map_err(|x| Error::Filesystem(path.to_owned(), "canonicalizing", x))
466}
467
468pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<u64> {
469    let from = from.as_ref();
470    let to = to.as_ref();
471
472    ::std::fs::copy(from, to).map_err(|x| {
473        Error::Filesystem2(from.to_owned(), to.to_owned(), "copying file", x)
474    })
475}
476
477pub fn create_dir<P: AsRef<Path>>(path: P) -> Result<()> {
478    let path = path.as_ref();
479
480    ::std::fs::create_dir(path).map_err(|x| {
481        Error::Filesystem(path.to_owned(), "creating directory", x)
482    })
483}
484
485pub fn create_dir_all<P: AsRef<Path>>(path: P) -> Result<()> {
486    let path = path.as_ref();
487
488    ::std::fs::create_dir_all(path).map_err(|x| {
489        Error::Filesystem(path.to_owned(), "recursively creating directory", x)
490    })
491}
492
493pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
494    let src = src.as_ref();
495    let dst = dst.as_ref();
496
497    ::std::fs::hard_link(src, dst).map_err(|x| {
498        Error::Filesystem2(src.to_owned(), dst.to_owned(), "hard linking", x)
499    })
500}
501
502pub fn metadata<P: AsRef<Path>>(path: P) -> Result<Metadata> {
503    let path = path.as_ref();
504
505    ::std::fs::metadata(path)
506        .map(|x| Metadata::new(x, path.to_owned()))
507        .map_err(|x| {
508            Error::Filesystem(path.to_owned(), "getting metadata from", x)
509        })
510}
511
512pub fn read<P: AsRef<Path>>(path: P) -> Result<Vec<u8>> {
513    let path = path.as_ref();
514
515    ::std::fs::read(path)
516        .map_err(|x| Error::Filesystem(path.to_owned(), "reading", x))
517}
518
519pub fn read_dir<P: AsRef<Path>>(path: P) -> Result<ReadDir> {
520    let path = path.as_ref();
521
522    ::std::fs::read_dir(path)
523        .map(|x| ReadDir::new(x, path.to_owned()))
524        .map_err(|x| Error::Filesystem(path.to_owned(), "reading directory", x))
525}
526
527pub fn read_link<P: AsRef<Path>>(path: P) -> Result<PathBuf> {
528    let path = path.as_ref();
529
530    ::std::fs::read_link(path)
531        .map_err(|x| Error::Filesystem(path.to_owned(), "reading link", x))
532}
533
534pub fn read_to_string<P: AsRef<Path>>(path: P) -> Result<String> {
535    let path = path.as_ref();
536
537    ::std::fs::read_to_string(path)
538        .map_err(|x| Error::Filesystem(path.to_owned(), "reading", x))
539}
540
541pub fn remove_dir<P: AsRef<Path>>(path: P) -> Result<()> {
542    let path = path.as_ref();
543
544    ::std::fs::remove_dir(path).map_err(|x| {
545        Error::Filesystem(path.to_owned(), "removing directory", x)
546    })
547}
548
549pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> Result<()> {
550    let path = path.as_ref();
551
552    ::std::fs::remove_dir_all(path).map_err(|x| {
553        Error::Filesystem(path.to_owned(), "recursively removing directory", x)
554    })
555}
556
557pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<()> {
558    let path = path.as_ref();
559
560    ::std::fs::remove_file(path)
561        .map_err(|x| Error::Filesystem(path.to_owned(), "removing file", x))
562}
563
564pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<()> {
565    let from = from.as_ref();
566    let to = to.as_ref();
567
568    ::std::fs::rename(from, to).map_err(|x| {
569        Error::Filesystem2(from.to_owned(), to.to_owned(), "renaming", x)
570    })
571}
572
573pub fn set_permissions<P: AsRef<Path>>(
574    path: P,
575    perm: Permissions,
576) -> Result<()> {
577    let path = path.as_ref();
578
579    // TODO: include `perm` in the error?
580    ::std::fs::set_permissions(path, perm).map_err(|x| {
581        Error::Filesystem(path.to_owned(), "setting permissions for", x)
582    })
583}
584
585pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
586    let src = src.as_ref();
587    let dst = dst.as_ref();
588
589    #[allow(deprecated)]
590    ::std::fs::soft_link(src, dst).map_err(|x| {
591        Error::Filesystem2(src.to_owned(), dst.to_owned(), "soft linking", x)
592    })
593}
594
595pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> Result<Metadata> {
596    let path = path.as_ref();
597
598    ::std::fs::metadata(path)
599        .map(|x| Metadata::new(x, path.to_owned()))
600        .map_err(|x| {
601            Error::Filesystem(
602                path.to_owned(),
603                "getting symlink metadata from",
604                x,
605            )
606        })
607}
608
609pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(
610    path: P,
611    contents: C,
612) -> Result<()> {
613    let path = path.as_ref();
614
615    ::std::fs::write(path, contents)
616        .map_err(|x| Error::Filesystem(path.to_owned(), "writing", x))
617}