filesystem/lib.rs
1#[cfg(any(feature = "mock", test))]
2extern crate pseudo;
3#[cfg(feature = "temp")]
4extern crate rand;
5#[cfg(feature = "temp")]
6extern crate tempdir;
7
8use std::ffi::OsString;
9use std::io::Result;
10use std::path::{Path, PathBuf};
11
12#[cfg(feature = "fake")]
13pub use fake::{FakeFileSystem, FakeTempDir};
14#[cfg(any(feature = "mock", test))]
15pub use mock::{FakeError, MockFileSystem};
16pub use os::OsFileSystem;
17#[cfg(feature = "temp")]
18pub use os::OsTempDir;
19
20#[cfg(feature = "fake")]
21mod fake;
22#[cfg(any(feature = "mock", test))]
23mod mock;
24mod os;
25
26/// Provides standard file system operations.
27pub trait FileSystem {
28 type DirEntry: DirEntry;
29 type ReadDir: ReadDir<Self::DirEntry>;
30
31 /// Returns the current working directory.
32 /// This is based on [`std::env::current_dir`].
33 ///
34 /// [`std::env::current_dir`]: https://doc.rust-lang.org/std/env/fn.current_dir.html
35 fn current_dir(&self) -> Result<PathBuf>;
36 /// Updates the current working directory.
37 /// This is based on [`std::env::set_current_dir`].
38 ///
39 /// [`std::env::set_current_dir`]: https://doc.rust-lang.org/std/env/fn.set_current_dir.html
40 fn set_current_dir<P: AsRef<Path>>(&self, path: P) -> Result<()>;
41
42 /// Determines whether the path exists and points to a directory.
43 fn is_dir<P: AsRef<Path>>(&self, path: P) -> bool;
44 /// Determines whether the path exists and points to a file.
45 fn is_file<P: AsRef<Path>>(&self, path: P) -> bool;
46
47 /// Creates a new directory.
48 /// This is based on [`std::fs::create_dir`].
49 ///
50 /// [`std::fs::create_dir`]: https://doc.rust-lang.org/std/fs/fn.create_dir.html
51 fn create_dir<P: AsRef<Path>>(&self, path: P) -> Result<()>;
52 /// Recursively creates a directory and any missing parents.
53 /// This is based on [`std::fs::create_dir`].
54 ///
55 /// [`std::fs::create_dir_all`]: https://doc.rust-lang.org/std/fs/fn.create_dir_all.html
56 fn create_dir_all<P: AsRef<Path>>(&self, path: P) -> Result<()>;
57 /// Removes an empty directory.
58 /// This is based on [`std::fs::remove_dir`].
59 ///
60 /// [`std::fs::remove_dir`]: https://doc.rust-lang.org/std/fs/fn.remove_dir.html
61 fn remove_dir<P: AsRef<Path>>(&self, path: P) -> Result<()>;
62 /// Removes a directory and any child files or directories.
63 /// This is based on [`std::fs::remove_dir_all`].
64 ///
65 /// [`std::fs::remove_dir_all`]: https://doc.rust-lang.org/std/fs/fn.remove_dir_all.html
66 fn remove_dir_all<P: AsRef<Path>>(&self, path: P) -> Result<()>;
67 /// Returns an iterator over the entries in a directory.
68 /// This is based on [`std::fs::read_dir`].
69 ///
70 /// [`std::fs::read_dir`]: https://doc.rust-lang.org/std/fs/fn.read_dir.html
71 fn read_dir<P: AsRef<Path>>(&self, path: P) -> Result<Self::ReadDir>;
72
73 /// Writes `buf` to a new file at `path`.
74 ///
75 /// # Errors
76 ///
77 /// * A file or directory already exists at `path`.
78 /// * The parent directory of `path` does not exist.
79 /// * Current user has insufficient permissions.
80 fn create_file<P, B>(&self, path: P, buf: B) -> Result<()>
81 where
82 P: AsRef<Path>,
83 B: AsRef<[u8]>;
84 /// Writes `buf` to a new or existing file at `buf`.
85 /// This will overwrite any contents that already exist.
86 ///
87 /// # Errors
88 ///
89 /// * The parent directory of `path` does not exist.
90 /// * Current user has insufficient permissions.
91 fn write_file<P, B>(&self, path: P, buf: B) -> Result<()>
92 where
93 P: AsRef<Path>,
94 B: AsRef<[u8]>;
95 /// Writes `buf` to an existing file at `buf`.
96 /// This will overwrite any contents that already exist.
97 ///
98 /// # Errors
99 ///
100 /// * No file `file` does not exist.
101 /// * The node at `file` is a directory.
102 /// * Current user has insufficient permissions.
103 fn overwrite_file<P, B>(&self, path: P, buf: B) -> Result<()>
104 where
105 P: AsRef<Path>,
106 B: AsRef<[u8]>;
107 /// Returns the contents of `path`.
108 ///
109 /// # Errors
110 ///
111 /// * `path` does not exist.
112 /// * `path` is a directory.
113 /// * Current user has insufficient permissions.
114 fn read_file<P: AsRef<Path>>(&self, path: P) -> Result<Vec<u8>>;
115 /// Returns the contents of `path` as a string.
116 ///
117 /// # Errors
118 ///
119 /// * `path` does not exist.
120 /// * `path` is a directory.
121 /// * Current user has insufficient permissions.
122 /// * Contents are not valid UTF-8
123 fn read_file_to_string<P: AsRef<Path>>(&self, path: P) -> Result<String>;
124 /// Writes the contents of `path` into the buffer. If successful, returns
125 /// the number of bytes that were read.
126 ///
127 /// # Errors
128 ///
129 /// * `path` does not exist.
130 /// * `path` is a directory.
131 /// * Current user has insufficient permissions.
132 fn read_file_into<P, B>(&self, path: P, buf: B) -> Result<usize>
133 where
134 P: AsRef<Path>,
135 B: AsMut<Vec<u8>>;
136 /// Removes the file at `path`.
137 /// This is based on [`std::fs::remove_file`].
138 ///
139 /// [`std::fs::remove_file`]: https://doc.rust-lang.org/std/fs/fn.remove_file.html
140 fn remove_file<P: AsRef<Path>>(&self, path: P) -> Result<()>;
141 /// Copies the file at path `from` to the path `to`.
142 /// This is based on [`std::fs::copy`].
143 ///
144 /// [`std::fs::copy`]: https://doc.rust-lang.org/std/fs/fn.copy.html
145 fn copy_file<P, Q>(&self, from: P, to: Q) -> Result<()>
146 where
147 P: AsRef<Path>,
148 Q: AsRef<Path>;
149
150 /// Renames a file or directory.
151 /// If both `from` and `to` are files, `to` will be replaced.
152 /// Based on [`std::fs::rename`].
153 ///
154 /// [`std::fs::rename`]: https://doc.rust-lang.org/std/fs/fn.rename.html
155 fn rename<P, Q>(&self, from: P, to: Q) -> Result<()>
156 where
157 P: AsRef<Path>,
158 Q: AsRef<Path>;
159
160 /// Returns `true` if `path` is a readonly file.
161 ///
162 /// # Errors
163 ///
164 /// * `path` does not exist.
165 /// * Current user has insufficient permissions.
166 fn readonly<P: AsRef<Path>>(&self, path: P) -> Result<bool>;
167 /// Sets or unsets the readonly flag of `path`.
168 ///
169 /// # Errors
170 ///
171 /// * `path` does not exist.
172 /// * Current user has insufficient permissions.
173 fn set_readonly<P: AsRef<Path>>(&self, path: P, readonly: bool) -> Result<()>;
174
175 /// Returns the length of the node at the path
176 /// or 0 if the node does not exist.
177 fn len<P: AsRef<Path>>(&self, path: P) -> u64;
178}
179
180#[cfg(unix)]
181pub trait UnixFileSystem {
182 /// Returns the current mode bits of `path`.
183 ///
184 /// # Errors
185 ///
186 /// * `path` does not exist.
187 /// * Current user has insufficient permissions.
188 fn mode<P: AsRef<Path>>(&self, path: P) -> Result<u32>;
189 /// Sets the mode bits of `path`.
190 ///
191 /// # Errors
192 ///
193 /// * `path` does not exist.
194 /// * Current user has insufficient permissions.
195 fn set_mode<P: AsRef<Path>>(&self, path: P, mode: u32) -> Result<()>;
196}
197
198#[cfg(feature = "temp")]
199/// Tracks a temporary directory that will be deleted once the struct goes out of scope.
200pub trait TempDir {
201 /// Returns the [`Path`] of the temporary directory.
202 ///
203 /// [`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html
204 fn path(&self) -> &Path;
205}
206
207#[cfg(feature = "temp")]
208pub trait TempFileSystem {
209 type TempDir: TempDir;
210
211 /// Creates a new temporary directory.
212 fn temp_dir<S: AsRef<str>>(&self, prefix: S) -> Result<Self::TempDir>;
213}
214
215pub trait DirEntry {
216 fn file_name(&self) -> OsString;
217 fn path(&self) -> PathBuf;
218}
219
220pub trait ReadDir<T: DirEntry>: Iterator<Item = Result<T>> {}