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
56
57
58
59
60
61
62
use std::collections::btree_map::{ IntoIter };
use std::path::{ PathBuf };
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;

use crate::objects::tree::{ TreeEntry, FileMode };
use crate::stores::{ StorageSet, Queryable };
use crate::objects::blob::Blob;
use crate::objects::Object;

pub struct TreeIterator<'a, S: Queryable> {
    storage_set: &'a StorageSet<S>,
    layers: Vec<IntoIter<Vec<u8>, TreeEntry>>,
    path_segments: PathBuf
}

impl<'a, S: Queryable> TreeIterator<'a, S> {
    pub fn new(storage_set: &'a StorageSet<S>, layers: Vec<IntoIter<Vec<u8>, TreeEntry>>) -> TreeIterator<S> {
        TreeIterator {
            path_segments: PathBuf::from("."),
            storage_set,
            layers
        }
    }
}

impl<'a, S: Queryable> Iterator for TreeIterator<'a, S> {
    type Item = (PathBuf, FileMode, Blob);

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            let current_iter = self.layers.last_mut()?;
            let next = current_iter.next();
            if next.is_none() {
                self.layers.pop();
                self.path_segments.pop();
                continue
            }

            let (key, entry) = next.unwrap();
            let item = self.storage_set.get_and_load(&entry.id).ok().unwrap_or(None);
            if let Some(xs) = item {
                match xs {
                    Object::Tree(xs) => {
                        self.path_segments.push(OsStr::from_bytes(&key));
                        self.layers.push(xs.into_iter());
                    },

                    Object::Blob(xs) => {
                        let mut pb = self.path_segments.clone();
                        pb.push(OsStr::from_bytes(&key));
                        return Some(
                            (pb, entry.mode, xs)
                        )
                    },

                    _ => continue
                }
            }
        }
    }
}