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>> {}