weavatrix_scan/
walk_iter.rs1use crate::walk_types::{WalkEntry, WalkError, WalkOperation};
2use crate::walker::Walker;
3
4impl Iterator for Walker {
5 type Item = Result<WalkEntry, WalkError>;
6
7 fn next(&mut self) -> Option<Self::Item> {
8 'walk: loop {
9 if self.finished {
10 return None;
11 }
12 if self.yield_root {
13 self.yield_root = false;
14 let root = self.root.as_ref().clone();
15 let entry = self.visit(
16 root,
17 0,
18 Some(self.root_file_type.expect("root metadata is present")),
19 None,
20 );
21 match entry {
22 Ok(entry) if entry.depth() >= self.options.min_depth => {
23 return Some(Ok(entry));
24 }
25 Ok(_) => continue,
26 Err(error) => return Some(self.yield_error(error)),
27 }
28 }
29 if let Some(error) = self.schedule_pending_directory() {
30 return Some(self.yield_error(error));
31 }
32 loop {
33 let frame = self.frames.last_mut()?;
34 let depth = frame.depth + 1;
35 let entry = match frame.entries.next() {
36 Some(Ok(entry)) => entry,
37 Some(Err(source)) => {
38 let error =
39 WalkError::new(&frame.path, depth, WalkOperation::ReadEntry, source);
40 return Some(self.yield_error(error));
41 }
42 None => {
43 let was_open = frame.entries.is_open();
44 let identity = frame.identity;
45 self.frames.pop();
46 if was_open {
47 self.open_handles -= 1;
48 }
49 if let Some(identity) = identity {
50 self.active_directories.remove(&identity);
51 }
52 continue;
53 }
54 };
55 let path = entry.path();
56 let file_type = match entry.file_type() {
57 Ok(file_type) => file_type,
58 Err(source) => {
59 let error =
60 WalkError::new(path, depth, WalkOperation::ReadMetadata, source);
61 return Some(self.yield_error(error));
62 }
63 };
64 let bytes = if self.options.collect_metadata && file_type.is_file() {
65 match entry.metadata() {
66 Ok(metadata) => Some(metadata.len()),
67 Err(source) => {
68 let error =
69 WalkError::new(path, depth, WalkOperation::ReadMetadata, source);
70 return Some(self.yield_error(error));
71 }
72 }
73 } else {
74 None
75 };
76 match self.visit(path, depth, Some(file_type), bytes) {
77 Ok(entry) if entry.depth() >= self.options.min_depth => {
78 return Some(Ok(entry));
79 }
80 Ok(_) => continue 'walk,
81 Err(error) => return Some(self.yield_error(error)),
82 }
83 }
84 }
85 }
86}