1use crate::error;
2use crate::file;
3use crate::file::File;
4use crate::path_stuff;
5use fs_extra;
6use std::collections::{HashMap, HashSet};
7use std::ffi::OsString;
8use std::fs;
9use std::path::{Path, PathBuf};
10
11#[derive(Debug, Clone)]
14pub struct Dir {
15 pub path: PathBuf,
17}
18
19#[derive(Debug)]
22#[allow(missing_docs)]
23pub enum DirEntry {
24 File(File),
25 Dir(Dir),
26}
27
28impl DirEntry {
29 pub fn path(&self) -> PathBuf {
31 match self {
32 DirEntry::File(entry) => entry.path.clone(),
33 DirEntry::Dir(entry) => entry.path.clone(),
34 }
35 }
36 pub fn file_name(&self) -> OsString {
38 match self {
39 DirEntry::File(entry) => entry.path.file_name().unwrap().to_os_string(),
40 DirEntry::Dir(entry) => entry.path.file_name().unwrap().to_os_string(),
41 }
42 }
43 #[allow(dead_code)]
45 pub fn is_file(&self) -> bool {
46 if let DirEntry::File(_) = self {
47 true
48 } else {
49 false
50 }
51 }
52 #[allow(dead_code)]
54 pub fn is_dir(&self) -> bool {
55 if let DirEntry::Dir(_) = self {
56 true
57 } else {
58 false
59 }
60 }
61}
62
63impl AsRef<Path> for Dir {
64 fn as_ref(&self) -> &Path {
65 self.path.as_path()
66 }
67}
68
69#[allow(dead_code)]
71impl Dir {
72 pub fn new<'a, P: 'a + AsRef<Path>>(path: P) -> error::Result<Dir> {
84 let mut path_buf = PathBuf::new();
85 path_buf.push(path);
86 let real_path = path_buf.as_path();
87 if real_path.exists() && real_path.is_file() {
88 Err(error::Error::new_from_kind(error::ErrorKind::InvalidFolder))
89 } else {
90 Ok(Dir { path: path_buf })
91 }
92 }
93 pub fn temp_dir<'a, P: 'a + AsRef<Path>>(name: P) -> error::Result<Dir> {
100 let dir = Dir::temp_dir_no_create(name)?;
101 dir.create()?;
102 Ok(dir)
103 }
104 pub fn temp_dir_no_create<'a, P: 'a + AsRef<Path>>(name: P) -> error::Result<Dir> {
111 let mut tmp_dir = std::env::temp_dir();
112 tmp_dir.push(name);
113 let dir = Dir::new(tmp_dir)?;
114 Ok(dir)
115 }
116 pub fn temp_dir_rand() -> error::Result<Dir> {
123 Ok(Dir::temp_dir(path_stuff::get_rand_chars(10))?)
124 }
125 pub fn temp_dir_rand_no_create() -> error::Result<Dir> {
132 Ok(Dir::temp_dir_no_create(path_stuff::get_rand_chars(10))?)
133 }
134 pub fn parent(&self) -> error::Result<&str> {
142 path_stuff::parent(self.path.as_path())
143 }
144 pub fn name(&self) -> error::Result<&str> {
152 path_stuff::name(self.path.as_path())
153 }
154 pub fn parse_path(&self) -> error::Result<path_stuff::ParsedPathDir<'_>> {
156 path_stuff::parse_path_dir(self.path.as_path())
157 }
158 pub fn size(&self) -> error::Result<u64> {
160 Ok(error::result_from_fse(fs_extra::dir::get_size(&self.path))?)
161 }
162}
163
164#[allow(dead_code)]
165impl Dir {
166 pub fn exists(&self) -> bool {
168 self.path.exists()
169 }
170 pub fn create(&self) -> error::Result<()> {
172 if self.path.exists() {
173 Ok(())
174 } else {
175 error::result_from_io(fs::create_dir(&self.path))
176 }
177 }
178 pub fn create_all(&self) -> error::Result<()> {
180 error::result_from_io(fs::create_dir_all(&self.path))?;
181 Ok(())
182 }
183 pub fn delete(&self) -> error::Result<()> {
185 error::result_from_fse(fs_extra::dir::remove(&self.path))
186 }
187 pub fn create_file<P: AsRef<Path>>(&self, name: P) -> error::Result<file::File> {
194 let mut file_path = PathBuf::new();
195 file_path.push(&self.path);
196 file_path.push(name);
197 let file = file::File::new(file_path)?;
198 file.create()?;
199 Ok(file)
200 }
201 pub fn create_dir<P: AsRef<Path>>(&self, name: P) -> error::Result<Dir> {
208 let mut file_path = PathBuf::new();
209 file_path.push(&self.path);
210 file_path.push(name);
211 let dir = Dir::new(file_path)?;
212 dir.create()?;
213 Ok(dir)
214 }
215 pub fn delete_file<P: AsRef<Path>>(&self, name: P) -> error::Result<()> {
220 let mut file_path = PathBuf::new();
221 file_path.push(&self.path);
222 file_path.push(name);
223 error::result_from_io(fs::remove_file(file_path))
224 }
225 pub fn delete_dir<P: AsRef<Path>>(&self, name: P) -> error::Result<()> {
230 let mut file_path = PathBuf::new();
231 file_path.push(&self.path);
232 file_path.push(name);
233 error::result_from_fse(fs_extra::dir::remove(file_path))
234 }
235 pub fn get_file<P: AsRef<Path>>(&self, name: P) -> error::Result<file::File> {
242 let mut file_path = PathBuf::new();
243 file_path.push(&self.path);
244 file_path.push(name);
245 Ok(file::File::new(file_path)?)
246 }
247 pub fn get_dir<P: AsRef<Path>>(&self, name: P) -> error::Result<Dir> {
254 let mut file_path = PathBuf::new();
255 file_path.push(&self.path);
256 file_path.push(name);
257 Ok(Dir::new(file_path)?)
258 }
259 pub fn copy<P: AsRef<Path>>(
266 &self,
267 to: P,
268 options: &fs_extra::dir::CopyOptions,
269 ) -> error::Result<Dir> {
270 let mut dest = PathBuf::new();
271 dest.push(to);
272 if !dest.exists() {
273 error::result_from_io(fs::create_dir(&dest))?;
274 }
275 error::result_from_fse(fs_extra::dir::copy(&self.path, &dest, options))?;
276 Ok(Dir::new(dest)?)
277 }
278 pub fn copy_with_progress<
291 P: AsRef<Path>,
292 F: FnMut(fs_extra::dir::TransitProcess) -> fs_extra::dir::TransitProcessResult,
293 >(
294 &self,
295 to: P,
296 options: &fs_extra::dir::CopyOptions,
297 progress_handler: F,
298 ) -> error::Result<Dir> {
299 let mut dest = PathBuf::new();
300 dest.push(to);
301 if !dest.exists() {
302 error::result_from_io(fs::create_dir(&dest))?;
303 }
304 error::result_from_fse(fs_extra::dir::copy_with_progress(
305 &self.path,
306 &dest,
307 options,
308 progress_handler,
309 ))?;
310 Ok(Dir::new(dest)?)
311 }
312 pub fn move_to<P: AsRef<Path>>(
319 &self,
320 to: P,
321 options: &fs_extra::dir::CopyOptions,
322 ) -> error::Result<Dir> {
323 let mut dest = PathBuf::new();
324 dest.push(to);
325 if !dest.exists() {
326 error::result_from_io(fs::create_dir(&dest))?;
327 }
328 error::result_from_fse(fs_extra::dir::move_dir(&self.path, &dest, options))?;
329 Ok(Dir::new(dest)?)
330 }
331 pub fn move_to_with_progress<
344 P: AsRef<Path>,
345 F: FnMut(fs_extra::dir::TransitProcess) -> fs_extra::dir::TransitProcessResult,
346 >(
347 &self,
348 to: P,
349 options: &fs_extra::dir::CopyOptions,
350 progress_handler: F,
351 ) -> error::Result<Dir> {
352 let mut dest = PathBuf::new();
353 dest.push(to);
354 if !dest.exists() {
355 error::result_from_io(fs::create_dir(&dest))?;
356 }
357 error::result_from_fse(fs_extra::dir::move_dir_with_progress(
358 &self.path,
359 &dest,
360 options,
361 progress_handler,
362 ))?;
363 Ok(Dir::new(dest)?)
364 }
365 pub fn get_content(&self) -> error::Result<fs_extra::dir::DirContent> {
374 error::result_from_fse(fs_extra::dir::get_dir_content(&self.path))
375 }
376 pub fn get_content2(
390 &self,
391 options: &fs_extra::dir::DirOptions,
392 ) -> error::Result<fs_extra::dir::DirContent> {
393 error::result_from_fse(fs_extra::dir::get_dir_content2(&self.path, options))
394 }
395 pub fn get_details_entry(
410 &self,
411 config: &HashSet<fs_extra::dir::DirEntryAttr>,
412 ) -> error::Result<HashMap<fs_extra::dir::DirEntryAttr, fs_extra::dir::DirEntryValue>> {
413 error::result_from_fse(fs_extra::dir::get_details_entry(&self.path, config))
414 }
415 pub fn create_dir_all<P: AsRef<Path>>(&self, path: P) -> error::Result<Dir> {
420 let mut path_buf = PathBuf::new();
421 path_buf.push(&self.path);
422 path_buf.push(path);
423 error::result_from_fse(fs_extra::dir::create_all(&path_buf, false))?;
424 Ok(Dir::new(path_buf)?)
425 }
426 pub fn create_file_all<P: AsRef<Path>>(&self, path: P) -> error::Result<file::File> {
431 let mut path_buf = PathBuf::new();
432 path_buf.push(&self.path);
433 path_buf.push(path);
434 let path_buf_parent =
435 error::result_from_option2(path_buf.parent(), error::ErrorKind::PathNoParentFound)?;
436 error::result_from_fse(fs_extra::dir::create_all(path_buf_parent, false))?;
437 let file = file::File::new(path_buf)?;
438 file.create()?;
439 Ok(file)
440 }
441 pub fn ls(
457 &self,
458 config: &HashSet<fs_extra::dir::DirEntryAttr>,
459 ) -> error::Result<fs_extra::dir::LsResult> {
460 error::result_from_fse(fs_extra::dir::ls(&self.path, config))
461 }
462 pub fn read(&self) -> error::Result<Vec<DirEntry>> {
477 let mut result: Vec<DirEntry> = vec![];
478 for entry in error::result_from_io(fs::read_dir(self.path.as_path()))? {
479 let entry = error::result_from_io(entry)?;
480 if entry.path().is_file() {
481 result.push(DirEntry::File(File::new(entry.path())?));
482 } else {
483 result.push(DirEntry::Dir(Dir::new(entry.path())?));
484 }
485 }
486 Ok(result)
487 }
488 pub fn read_as_osstring_vec(&self) -> error::Result<Vec<OsString>> {
490 let mut result: Vec<OsString> = vec![];
491 for entry in error::result_from_io(fs::read_dir(self.path.as_path()))? {
492 let entry = error::result_from_io(entry)?;
493 result.push(entry.file_name());
494 }
495 Ok(result)
496 }
497 pub fn read_as_pathbuf_vec(&self) -> error::Result<Vec<PathBuf>> {
499 let mut result: Vec<PathBuf> = vec![];
500 for entry in error::result_from_io(fs::read_dir(self.path.as_path()))? {
501 let entry = error::result_from_io(entry)?;
502 result.push(entry.path());
503 }
504 Ok(result)
505 }
506 pub fn entry_exists<P: AsRef<Path>>(&self, path: P) -> bool {
508 self.path.join(path).exists()
509 }
510}