fast_walker/dir_walker/
mod.rs

1use crate::{WalkError, WalkItem};
2use std::{
3    collections::VecDeque,
4    path::{Path, PathBuf},
5};
6pub mod rev_iter;
7pub mod sync_iter;
8#[cfg(feature = "tokio")]
9pub mod tokio_iter;
10
11/// Start a directory walk plan
12#[derive(Clone)]
13pub struct WalkPlan {
14    /// Initial paths to search
15    pub check_list: Vec<PathBuf>,
16    /// Follow symlinks
17    pub follow_symlinks: bool,
18    /// Depth first search or breadth first search
19    pub depth_first: bool,
20    /// Max number of items in the buffer
21    pub capacity: usize,
22    /// Number of threads to use
23    pub threads: usize,
24    /// Check if a directory should be rejected
25    pub reject_when: fn(&WalkItem) -> bool,
26    /// Ignore a file if it matches the condition
27    pub ignore_when: fn(&WalkItem) -> bool,
28    /// Stop if a item matches the condition
29    pub finish_when: fn(&WalkItem) -> bool,
30}
31
32impl Default for WalkPlan {
33    fn default() -> Self {
34        Self {
35            check_list: vec![],
36            follow_symlinks: false,
37            depth_first: false,
38            capacity: 256,
39            threads: 8,
40            reject_when: |_| false,
41            ignore_when: |_| false,
42            finish_when: |_| false,
43        }
44    }
45}
46
47impl WalkPlan {
48    /// Create a new plan with initial path
49    pub fn new<P: AsRef<Path>>(path: P) -> Self {
50        Self { check_list: vec![path.as_ref().to_path_buf()], ..Default::default() }
51    }
52    /// Create a new plan with initial paths
53    pub fn roots<I>(roots: I) -> Self
54    where
55        I: IntoIterator,
56        I::Item: AsRef<Path>,
57    {
58        Self { check_list: roots.into_iter().map(|p| p.as_ref().to_path_buf()).collect(), ..Default::default() }
59    }
60    /// Search all subdirectories with breadth first
61    pub fn breadth_first_search(mut self) -> Self {
62        self.depth_first = false;
63        self
64    }
65    /// Search all subdirectories with depth first
66    pub fn depth_first_search(mut self) -> Self {
67        self.depth_first = true;
68        self
69    }
70    /// Search with threads
71    pub fn with_threads(mut self, threads: usize) -> Self {
72        self.threads = threads;
73        self
74    }
75    /// Reject directories if it matches the condition
76    ///
77    /// # Examples
78    ///
79    /// - ignore hidden directories
80    ///
81    /// ```
82    /// # use fast_walker::WalkPlan;
83    /// let plan = WalkPlan::new(".").reject_if(|item| item.path.starts_with("."));
84    /// ```
85    pub fn reject_if(mut self, f: fn(&WalkItem) -> bool) -> Self {
86        self.reject_when = f;
87        self
88    }
89    /// Ignore files if it's name matches the condition
90    ///
91    /// Notice that it does not ignore directories whose name matches the condition
92    ///
93    /// # Examples
94    ///
95    /// - ignore non-ascii files
96    ///
97    /// ```
98    /// # use fast_walker::WalkPlan;
99    /// let plan = WalkPlan::new(".").ignore_if(|path| !path.is_ascii());
100    /// ```
101    pub fn ignore_if(mut self, f: fn(&WalkItem) -> bool) -> Self {
102        self.ignore_when = f;
103        self
104    }
105    pub fn finish_if(mut self, f: fn(&WalkItem) -> bool) -> Self {
106        self.finish_when = f;
107        self
108    }
109}