Skip to main content

path_extra/std/
fs.rs

1#[cfg(unix)]
2use std::os::unix::fs::PermissionsExt as _;
3use std::{
4    fs::{File, OpenOptions},
5    io,
6    path::Path,
7};
8
9pub trait FileExt {
10    fn open_if_exists(path: impl AsRef<Path>) -> io::Result<Option<Self>>
11    where
12        Self: Sized;
13
14    fn create_if_not_exists(path: impl AsRef<Path>) -> io::Result<Option<Self>>
15    where
16        Self: Sized;
17
18    fn create_new_if_not_exists(path: impl AsRef<Path>) -> io::Result<Option<Self>>
19    where
20        Self: Sized;
21
22    #[cfg(unix)]
23    fn set_permissions_mode(&self, permissions_mode: u32) -> io::Result<&Self>;
24    #[cfg(unix)]
25    fn add_permissions_mode(&self, permissions_mode: u32) -> io::Result<&Self>;
26    #[cfg(unix)]
27    fn remove_permissions_mode(&self, permissions_mode: u32) -> io::Result<&Self>;
28}
29
30impl FileExt for File {
31    #[inline]
32    fn open_if_exists(path: impl AsRef<Path>) -> io::Result<Option<Self>> {
33        match Self::open(path) {
34            Ok(file) => Ok(Some(file)),
35            Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
36            Err(err) => Err(err),
37        }
38    }
39
40    #[inline]
41    fn create_if_not_exists(path: impl AsRef<Path>) -> io::Result<Option<Self>> {
42        let mut options = Self::options();
43
44        options.write(true).create_new(true);
45
46        options.open_if_not_exists(path)
47    }
48
49    #[inline]
50    fn create_new_if_not_exists(path: impl AsRef<Path>) -> io::Result<Option<Self>> {
51        match Self::create_new(path) {
52            Ok(file) => Ok(Some(file)),
53            Err(err) if err.kind() == io::ErrorKind::AlreadyExists => Ok(None),
54            Err(err) => Err(err),
55        }
56    }
57
58    #[cfg(unix)]
59    #[inline]
60    fn set_permissions_mode(&self, permissions_mode: u32) -> io::Result<&Self> {
61        let metadata = self.metadata()?;
62
63        let mut permissions = metadata.permissions();
64
65        permissions.set_mode(permissions_mode);
66
67        self.set_permissions(permissions)?;
68
69        Ok(self)
70    }
71
72    #[cfg(unix)]
73    #[inline]
74    fn add_permissions_mode(&self, permissions_mode: u32) -> io::Result<&Self> {
75        let metadata = self.metadata()?;
76
77        let mut permissions = metadata.permissions();
78
79        permissions.set_mode(permissions.mode() | permissions_mode);
80
81        self.set_permissions(permissions)?;
82
83        Ok(self)
84    }
85
86    #[cfg(unix)]
87    #[inline]
88    fn remove_permissions_mode(&self, permissions_mode: u32) -> io::Result<&Self> {
89        let metadata = self.metadata()?;
90
91        let mut permissions = metadata.permissions();
92
93        permissions.set_mode(permissions.mode() & !permissions_mode);
94
95        self.set_permissions(permissions)?;
96
97        Ok(self)
98    }
99}
100
101pub trait OpenOptionsExt {
102    fn open_if_exists(&self, path: impl AsRef<Path>) -> io::Result<Option<File>>;
103
104    fn open_if_not_exists(&self, path: impl AsRef<Path>) -> io::Result<Option<File>>;
105}
106
107impl OpenOptionsExt for OpenOptions {
108    #[inline]
109    fn open_if_exists(&self, path: impl AsRef<Path>) -> io::Result<Option<File>> {
110        match self.open(path) {
111            Ok(file) => Ok(Some(file)),
112            Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
113            Err(err) => Err(err),
114        }
115    }
116
117    #[inline]
118    fn open_if_not_exists(&self, path: impl AsRef<Path>) -> io::Result<Option<File>> {
119        match self.open(path) {
120            Ok(file) => Ok(Some(file)),
121            Err(err) if err.kind() == io::ErrorKind::AlreadyExists => Ok(None),
122            Err(err) => Err(err),
123        }
124    }
125}