veloren_common_assets/
walk.rs

1use std::{
2    io,
3    path::{Path, PathBuf},
4};
5
6/// Represent tree of directory, result of [generate_tree].
7///
8/// Note that paths are always relative to root it was generated from.
9#[derive(Debug, Clone)]
10pub enum Walk {
11    /// Represents file node, path is relative to directory root Walk was
12    /// generated from.
13    File(PathBuf),
14    /// Represents directory subtree, path is relative to directory root Walk
15    /// was generated from.
16    Dir { path: PathBuf, content: Vec<Walk> },
17}
18
19impl Walk {
20    /// Utility function to build a tree of directory, recursively
21    ///
22    /// Path needs to be absolute.
23    pub fn generate(root: &Path) -> io::Result<Walk> {
24        let trees = walk_tree(root, root);
25        Ok(Walk::Dir {
26            path: Path::new("").to_owned(),
27            content: trees?,
28        })
29    }
30
31    // TODO: implement iterator?
32    pub fn for_each_file<F>(&self, root: &Path, f: &mut F)
33    where
34        F: FnMut(&Path),
35    {
36        match self {
37            Self::File(filepath) => {
38                let path = root.join(filepath);
39                f(&path);
40            },
41            Self::Dir {
42                path: _,
43                content: files,
44            } => {
45                for path in files {
46                    path.for_each_file(root, f);
47                }
48            },
49        }
50    }
51}
52
53/// Helper function to [Walk::generate()], prefer using it instead.
54pub fn walk_tree(dir: &Path, root: &Path) -> io::Result<Vec<Walk>> {
55    let mut buff = Vec::new();
56    for entry in std::fs::read_dir(dir)? {
57        let entry = entry?;
58        let path = entry.path();
59        if path.is_dir() {
60            buff.push(Walk::Dir {
61                path: path
62                    .strip_prefix(root)
63                    .expect("strip can't fail, this path is created from root")
64                    .to_owned(),
65                content: walk_tree(&path, root)?,
66            });
67        } else {
68            let filename = path
69                .strip_prefix(root)
70                .expect("strip can't fail, this file is created from root")
71                .to_owned();
72            buff.push(Walk::File(filename));
73        }
74    }
75
76    Ok(buff)
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn trie() {
85        let root = crate::find_root().unwrap();
86        let assets = Path::new(&root).join("assets/");
87        Walk::generate(&assets).unwrap();
88    }
89}