Skip to main content

selene_core/
utils.rs

1use std::{
2    collections::VecDeque,
3    path::{Path, PathBuf},
4};
5
6use blake3::{Hash, Hasher};
7
8pub fn hash_file(path: impl AsRef<Path>) -> std::io::Result<Hash> {
9    let mut hasher = Hasher::new();
10    hasher.update_mmap(path)?;
11    Ok(hasher.finalize())
12}
13
14pub fn recurse_list_from_root<P: AsRef<Path>>(
15    root: P,
16    yield_dirs: bool,
17) -> impl Iterator<Item = PathBuf> {
18    let mut stack = VecDeque::new();
19    stack.push_back(root.as_ref().to_owned());
20
21    std::iter::from_fn(move || {
22        while let Some(path) = stack.pop_back() {
23            if path.is_dir() {
24                if let Ok(entries) = path.read_dir() {
25                    let filtered = entries.filter_map(Result::ok).map(|a| a.path());
26
27                    stack.extend(filtered);
28                }
29
30                if yield_dirs {
31                    return Some(path);
32                }
33            } else if path.is_file() {
34                return Some(path);
35            }
36        }
37
38        None
39    })
40}
41
42pub fn recurse_list_dirs<P: AsRef<Path>>(root: P) -> impl Iterator<Item = PathBuf> {
43    let mut stack = VecDeque::new();
44    stack.push_back(root.as_ref().to_owned());
45
46    std::iter::from_fn(move || {
47        while let Some(path) = stack.pop_back() {
48            if path.is_dir() {
49                if let Ok(entries) = path.read_dir() {
50                    let filtered = entries.filter_map(Result::ok).map(|a| a.path());
51                    stack.extend(filtered);
52                }
53
54                return Some(path);
55            }
56        }
57
58        None
59    })
60}