fast_walker/dir_walker/sync_iter/
mod.rs1use super::*;
2
3impl<'i> IntoIterator for &'i WalkPlan {
4 type Item = Result<WalkItem, WalkError>;
5 type IntoIter = LinearWalker<'i>;
6
7 fn into_iter(self) -> Self::IntoIter {
8 LinearWalker {
9 config: &self,
10 tasks: self.check_list.iter().map(|s| WalkItem::from(s.as_path())).collect(),
11 results: vec![],
12 found_files: 0,
13 }
14 }
15}
16
17pub struct LinearWalker<'i> {
18 config: &'i WalkPlan,
19 tasks: VecDeque<WalkItem>,
20 results: Vec<Result<WalkItem, WalkError>>,
21 found_files: usize,
22}
23
24impl<'i> LinearWalker<'i> {
25 fn pop(&mut self) -> Option<WalkItem> {
26 if self.config.depth_first { self.tasks.pop_back() } else { self.tasks.pop_front() }
27 }
28 fn read_item(&mut self, entry: WalkItem) {
29 if (self.config.finish_when)(&entry) {
30 self.tasks.clear();
31 self.results.push(Ok(entry));
32 return;
33 }
34 if entry.path.is_symlink() {
35 self.read_link(entry);
36 return;
37 }
38 if entry.is_directory() {
39 self.read_directory(entry);
40 return;
41 }
42 self.read_file(entry)
43 }
44 fn read_link(&mut self, entry: WalkItem) {
45 if self.config.follow_symlinks {
46 match entry.read_link() {
47 Ok(o) => {
48 self.tasks.push_back(WalkItem::from(o).with_depth(entry.depth + 1));
49 }
50 Err(e) => {
51 self.results.push(Err(WalkError::io_error(entry.path, e)));
52 }
53 }
54 }
55 }
56 fn read_directory(&mut self, entry: WalkItem) {
57 if (self.config.ignore_when)(&entry) {
58 return;
59 }
60 match entry.read_directory() {
61 Ok(dir) => {
62 for result in dir {
63 match result {
64 Ok(child) => {
65 self.tasks.push_back(WalkItem::from(child).with_depth(entry.depth + 1));
66 }
67 Err(e) => {
68 self.results.push(Err(WalkError::io_error(entry.path.clone(), e)));
69 continue;
70 }
71 }
72 }
73 }
74 Err(e) => {
75 self.results.push(Err(WalkError::io_error(entry.path, e)));
76 }
77 }
78 }
79 fn read_file(&mut self, entry: WalkItem) {
80 debug_assert!(entry.is_file());
81 if (self.config.reject_when)(&entry) {
82 return;
83 }
84 self.found_files += 1;
85 self.results.push(Ok(entry));
86 }
87}
88
89impl<'i> Iterator for LinearWalker<'i> {
90 type Item = Result<WalkItem, WalkError>;
91
92 fn next(&mut self) -> Option<Self::Item> {
93 match self.results.pop() {
94 Some(s) => {
95 return Some(s);
96 }
97 None => match self.pop() {
98 Some(s) => {
99 self.read_item(s);
100 self.next()
101 }
102 None => None,
103 },
104 }
105 }
106}
107
108#[test]
109fn run() {
110 let plan = WalkPlan {
111 check_list: vec![
112 PathBuf::from(r#"C:\Users\Dell\CLionProjects\fast-walker"#),
113 PathBuf::from(r#"C:\Users\Dell\CLionProjects\faster-pest"#),
114 ],
115 follow_symlinks: true,
116 depth_first: true,
117 capacity: 4,
118 threads: 4,
119 reject_when: |_| false,
120 ignore_when: |_| false,
121 finish_when: |_| false,
122 };
123
124 for item in plan.into_iter().take(10) {
125 match item {
126 Ok(o) => {
127 println!("File: {:?}", o);
128 }
129 Err(e) => {
130 println!("Error: {:?}", e);
131 }
132 }
133 }
134}