Skip to main content

pawkit_fs/
list_files_recursive.rs

1use crate::{Vfs, VfsError, VfsListDirectories, VfsListFiles};
2
3pub struct VfsListFilesRecursive {
4    pub(crate) stack: Vec<(Vfs, VfsListDirectories)>,
5    pub(crate) files: Option<VfsListFiles>,
6    pub(crate) prefix: Box<str>,
7}
8
9impl VfsListFilesRecursive {
10    fn next_file(&mut self) -> Option<<Self as Iterator>::Item> {
11        if let Some(files) = &mut self.files {
12            if let Some(file) = files.next() {
13                match file {
14                    Ok(file) => {
15                        let prefix = self
16                            .stack
17                            .last()
18                            .map(|it| it.0.subdirectory.as_ref())
19                            .unwrap_or(None)
20                            .unwrap_or(&self.prefix);
21
22                        let prefix = &prefix[self.prefix.len()..];
23
24                        let prefix = prefix.strip_prefix("/").unwrap_or(prefix);
25
26                        return Some(Ok(if prefix.is_empty() {
27                            file
28                        } else {
29                            format!("{}/{}", prefix, file)
30                        }));
31                    }
32                    Err(err) => return Some(Err(err)),
33                }
34            }
35        }
36
37        return None;
38    }
39
40    fn next_dir(&mut self) -> Option<<Self as Iterator>::Item> {
41        while let Some((vfs, dirs)) = self.stack.last_mut() {
42            match dirs.next() {
43                Some(Ok(dir)) => {
44                    let new_vfs = match vfs.subdirectory(&dir) {
45                        Ok(value) => value,
46                        Err(err) => return Some(Err(err)),
47                    };
48
49                    let new_dirs = match new_vfs.list_subdirectories() {
50                        Ok(value) => value,
51                        Err(err) => return Some(Err(err)),
52                    };
53
54                    let new_files = match new_vfs.list_files() {
55                        Ok(value) => value,
56                        Err(err) => return Some(Err(err)),
57                    };
58
59                    self.stack.push((new_vfs, new_dirs));
60                    self.files = Some(new_files);
61                    break;
62                }
63
64                Some(Err(err)) => return Some(Err(err)),
65
66                None => {
67                    self.stack.pop();
68                }
69            }
70        }
71
72        return None;
73    }
74}
75
76impl Iterator for VfsListFilesRecursive {
77    type Item = Result<String, VfsError>;
78
79    fn next(&mut self) -> Option<Self::Item> {
80        while !self.stack.is_empty() {
81            if let Some(value) = self.next_file() {
82                return Some(value);
83            }
84
85            if let Some(value) = self.next_dir() {
86                return Some(value);
87            }
88        }
89
90        return None;
91    }
92}