1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use std::fs;
use std::path::PathBuf;

pub struct IterDir {
    start_path: Option<PathBuf>,
    dir_stack: Vec<fs::ReadDir>,
}

impl IterDir {
    pub fn new(path: &PathBuf) -> IterDir {
        IterDir {
            start_path: Some(path.to_path_buf()),
            dir_stack: vec![],
        }
    }
}

impl Iterator for IterDir {
    type Item = fs::DirEntry;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(start_path) = self.start_path.take() {
            let readdir = fs::read_dir(start_path).expect("Err: could not read directory");
            self.dir_stack.push(readdir);
        }

        while !self.dir_stack.is_empty() {
            let curr = self
                .dir_stack
                .last_mut()
                .expect("Err: stack is empty")
                .next();

            match curr {
                None => {
                    self.dir_stack.pop().expect("Err: could not pop stack");
                }
                Some(Ok(dent)) => {
                    let ftype = dent.file_type().expect("Err: could not get file type");

                    if ftype.is_dir() {
                        let readdir =
                            fs::read_dir(dent.path()).expect("Err: could not read directory");
                        self.dir_stack.push(readdir);
                    }

                    return Some(dent);
                }
                Some(Err(_)) => return None,
            }
        }

        None
    }
}