Skip to main content

diskit/
std_diskit.rs

1//! [Stdlib](std) passthrough diskit
2//!
3//! For more information see the [struct level documentation](StdDiskit).
4
5use std::{
6    env::{current_dir, set_current_dir},
7    fs::{self, create_dir, create_dir_all},
8    io::{Error, Read, Seek, SeekFrom, Write},
9    path::{Path, PathBuf},
10};
11
12use crate::{
13    dir_entry::{DirEntry, WorkaroundResult},
14    file::{File, FileInner},
15    metadata::Metadata,
16    open_options::OpenOptions,
17    walkdir::{WalkDir, WalkdirIterator, WalkdirIteratorInner},
18    Diskit,
19};
20
21/// [Stdlib](std) passthrough diskit
22///
23/// This diskit passes all requests directly to the corresponding
24/// standard functions through.  This is useful if you normally want
25/// to access the disk (then you can use this diskit), but sometimes
26/// redirect your requests somewhere else (then you should use the
27/// appropriate other diskit), or as a last element in a diskit chain
28/// (like in [`LogDiskit<StdDiskit>`](crate::LogDiskit)).
29///
30/// Thanks to special optimizations of this library this diskit is
31/// (nearly) overhead-free.
32#[derive(Debug, Clone, Copy)]
33pub struct StdDiskit;
34
35impl Default for StdDiskit
36{
37    fn default() -> Self
38    {
39        Self
40    }
41}
42
43impl Diskit for StdDiskit
44{
45    fn set_pwd_inner(&self, path: &Path) -> Result<(), Error>
46    {
47        set_current_dir(path)
48    }
49
50    fn get_pwd(&self) -> Result<PathBuf, Error>
51    {
52        current_dir()
53    }
54
55    fn open_inner(&self, path: &Path) -> Result<File<Self>, Error>
56    {
57        Ok(File {
58            inner: FileInner {
59                file: Some(fs::File::open(path)?),
60                val: 0,
61            },
62            diskit: *self,
63        })
64    }
65
66    fn create_inner(&self, path: &Path) -> Result<File<Self>, Error>
67    {
68        Ok(File {
69            inner: FileInner {
70                file: Some(fs::File::create(path)?),
71                val: 0,
72            },
73            diskit: *self,
74        })
75    }
76
77    fn open_with_options_inner(
78        &self,
79        path: &Path,
80        options: OpenOptions,
81    ) -> Result<File<Self>, Error>
82    {
83        Ok(File {
84            inner: FileInner {
85                file: Some(Into::<fs::OpenOptions>::into(options).open(path)?),
86                val: 0,
87            },
88            diskit: *self,
89        })
90    }
91
92    fn read_inner(&self, file: &FileInner, buf: &mut [u8]) -> Result<usize, Error>
93    {
94        file.file
95            .as_ref()
96            .expect("StdDiskit's Files are never None")
97            .read(buf)
98    }
99
100    fn read_to_end_inner(&self, file: &mut FileInner, buf: &mut Vec<u8>) -> Result<usize, Error>
101    {
102        file.file
103            .as_ref()
104            .expect("StdDiskit's Files are never None")
105            .read_to_end(buf)
106    }
107
108    fn read_to_string_inner(&self, file: &mut FileInner, buf: &mut String) -> Result<usize, Error>
109    {
110        file.file
111            .as_ref()
112            .expect("StdDiskit's Files are never None")
113            .read_to_string(buf)
114    }
115
116    fn write_inner(&self, file: &mut FileInner, buf: &[u8]) -> Result<usize, Error>
117    {
118        file.file
119            .as_ref()
120            .expect("StdDiskit's Files are never None")
121            .write(buf)
122    }
123
124    fn write_all_inner(&self, file: &mut FileInner, buf: &[u8]) -> Result<(), Error>
125    {
126        file.file
127            .as_ref()
128            .expect("StdDiskit's Files are never None")
129            .write_all(buf)
130    }
131
132    fn flush_inner(&self, file: &mut FileInner) -> Result<(), Error>
133    {
134        file.file
135            .as_ref()
136            .expect("StdDiskit's Files are never None")
137            .flush()
138    }
139
140    fn metadata_inner(&self, file: &FileInner) -> Result<Metadata, Error>
141    {
142        file.file
143            .as_ref()
144            .expect("StdDiskit's Files are never None")
145            .metadata()
146            .map(Into::into)
147    }
148
149    fn seek_inner(&self, file: &mut FileInner, pos: SeekFrom) -> Result<u64, Error>
150    {
151        file.file
152            .as_ref()
153            .expect("StdDiskit's Files are never None")
154            .seek(pos)
155    }
156
157    fn create_dir_inner(&self, path: &Path) -> Result<(), Error>
158    {
159        create_dir(path)
160    }
161
162    fn create_dir_all_inner(&self, path: &Path) -> Result<(), Error>
163    {
164        create_dir_all(path)
165    }
166
167    fn close_inner(&self, _: FileInner) -> Result<(), Error>
168    {
169        Ok(())
170    }
171
172    fn walkdir_inner(&self, path: &Path) -> WalkDir<Self>
173    {
174        WalkDir::new_default(*self, path.to_owned())
175    }
176
177    fn walkdir_next_inner(
178        &self,
179        inner: &mut WalkdirIteratorInner,
180    ) -> Option<Result<DirEntry, Error>>
181    {
182        inner
183            .walkdir
184            .as_mut()
185            .expect("StdDiskit's Walkdirs are never None")
186            .next()
187            .map(|x| {
188                x.map_err(Into::into).and_then(|y| {
189                    // I know that it looks awful.  TODO: Fix
190                    <_ as Into<WorkaroundResult<_, _>>>::into(y).deworkaround()
191                })
192            })
193    }
194
195    fn into_walkdir_iterator(&self, walkdir: WalkDir<Self>) -> WalkdirIterator<Self>
196    {
197        WalkdirIterator {
198            inner: Ok((
199                WalkdirIteratorInner {
200                    walkdir: Some(walkdir.to_original().into_iter()),
201                    val: 0,
202                    original: walkdir.options,
203                },
204                walkdir.diskit,
205            )),
206        }
207    }
208
209    #[cfg(feature = "trash")]
210    fn trash_delete_inner(&self, path: &Path) -> Result<(), trash::Error>
211    {
212        trash::delete(path)
213    }
214}