jwalk/core/
dir_entry_iter.rs1use std::iter::Peekable;
2
3use super::*;
4use crate::Result;
5
6pub struct DirEntryIter<C: ClientState> {
10 min_depth: usize,
11 pub(crate) read_dir_iter: Option<Peekable<ReadDirIter<C>>>,
13 read_dir_results_stack: Vec<vec::IntoIter<Result<DirEntry<C>>>>,
15}
16
17impl<C: ClientState> DirEntryIter<C> {
18 pub(crate) fn new(
19 root_entry_results: Vec<Result<DirEntry<C>>>,
20 parallelism: Parallelism,
21 min_depth: usize,
22 root_read_dir_state: C::ReadDirState,
23 core_read_dir_callback: Arc<ReadDirCallback<C>>,
24 ) -> DirEntryIter<C> {
25 let read_dir_specs: Vec<_> = root_entry_results
27 .iter()
28 .flat_map(|dir_entry_result| {
29 dir_entry_result
30 .as_ref()
31 .ok()?
32 .read_children_spec(root_read_dir_state.clone())
33 })
34 .collect();
35
36 let read_dir_iter =
38 ReadDirIter::try_new(read_dir_specs, parallelism, core_read_dir_callback)
39 .map(|iter| iter.peekable());
40
41 DirEntryIter {
44 min_depth,
45 read_dir_iter,
46 read_dir_results_stack: vec![root_entry_results.into_iter()],
47 }
48 }
49
50 fn push_next_read_dir_results(
51 iter: &mut Peekable<ReadDirIter<C>>,
52 results: &mut Vec<vec::IntoIter<Result<DirEntry<C>>>>,
53 ) -> Result<()> {
54 let read_dir_result = iter.next().unwrap();
56 let read_dir = match read_dir_result {
57 Ok(read_dir) => read_dir,
58 Err(err) => return Err(err),
59 };
60
61 let ReadDir { results_list, .. } = read_dir;
62 results.push(results_list.into_iter());
63
64 Ok(())
65 }
66}
67
68impl<C: ClientState> Iterator for DirEntryIter<C> {
69 type Item = Result<DirEntry<C>>;
70 fn next(&mut self) -> Option<Self::Item> {
71 loop {
72 let top_read_dir_results = self.read_dir_results_stack.last_mut()?;
74
75 if let Some(dir_entry_result) = top_read_dir_results.next() {
77 let mut dir_entry = match dir_entry_result {
79 Ok(dir_entry) => dir_entry,
80 Err(err) => return Some(Err(err)),
81 };
82 if dir_entry.read_children_path.is_some() {
85 let iter = match self.read_dir_iter.as_mut().ok_or_else(Error::busy) {
86 Ok(iter) => iter,
87 Err(err) => return Some(Err(err)),
88 };
89 if let Err(err) =
90 Self::push_next_read_dir_results(iter, &mut self.read_dir_results_stack)
91 {
92 dir_entry.read_children_error = Some(err);
93 }
94 }
95
96 if dir_entry.depth >= self.min_depth {
97 return Some(Ok(dir_entry));
99 }
100 } else {
101 self.read_dir_results_stack.pop();
103 }
104 }
105 }
106}