1use std::{
2 fs,
3 io::{Error, ErrorKind},
4 path::{Path, PathBuf},
5};
6
7pub type WalkdirPathBuf = (PathBuf, PathBuf);
16
17struct WalkDir {
18 skip: Vec<PathBuf>,
19}
20
21impl WalkDir {
22 pub fn new(skip: Option<Vec<PathBuf>>) -> WalkDir {
23 WalkDir {
24 skip: skip.unwrap_or_else(|| Vec::new()),
25 }
26 }
27
28 pub fn walk(&self, path: &Path, dir: Option<PathBuf>) -> std::io::Result<Vec<WalkdirPathBuf>> {
29 if path.is_file() {
30 return Ok(vec![self.walk_file(path, &dir.unwrap_or("".into()))]);
32 }
33 let mut dirs: Vec<WalkdirPathBuf> = Vec::new();
34 self.walk_dir(&path, &dir.unwrap_or("".into()), &mut dirs)?;
35
36 Ok(dirs)
37 }
38
39 fn walk_file(&self, path: &Path, dir: &Path) -> WalkdirPathBuf {
40 (path.to_owned(), dir.to_owned())
41 }
42
43 fn walk_dir(
44 &self,
45 path: &Path,
46 dir: &Path,
47 dirs: &mut Vec<WalkdirPathBuf>,
48 ) -> std::io::Result<()> {
49 for entry in fs::read_dir(path)? {
50 let entry = entry?;
51 let path = entry.path();
52
53 if self.skip.contains(&path) {
54 continue;
55 }
56
57 let file_name = path.file_name().ok_or_else(|| {
58 Error::new(
59 ErrorKind::InvalidInput,
60 "File does not have a valid filename",
61 )
62 })?;
63 let dir = dir.join(file_name);
64 dirs.extend(self.walk(&path, Some(dir))?);
65 }
66 Ok(())
67 }
68}
69
70pub fn walk_dir_skip(path: &Path, skip: Vec<PathBuf>) -> std::io::Result<Vec<WalkdirPathBuf>> {
71 let wd = WalkDir::new(Some(skip));
72 let paths = wd.walk(path, None )?;
73 Ok(paths)
74}
75
76pub fn walk_dir(path: &Path) -> std::io::Result<Vec<WalkdirPathBuf>> {
77 let wd = WalkDir::new(None );
78 let paths = wd.walk(path, None )?;
79 Ok(paths)
80}