gix_odb/store_impls/loose/
iter.rs

1use gix_features::fs;
2
3use crate::store_impls::loose;
4
5/// Returned by [`loose::Store::iter()`]
6pub type Error = gix_features::fs::walkdir::Error;
7
8impl loose::Iter {
9    fn path_to_id(
10        &self,
11        res: Result<fs::walkdir::DirEntry, fs::walkdir::Error>,
12    ) -> Option<Result<gix_hash::ObjectId, Error>> {
13        use std::path::Component::Normal;
14
15        match res {
16            Ok(e) => {
17                let p = e.path();
18                let mut ci = p.components();
19                let (c2, c1) = (ci.next_back(), ci.next_back());
20                if let (Some(Normal(c1)), Some(Normal(c2))) = (c1, c2) {
21                    if c1.len() == 2 && c2.len() == self.hash_hex_len - 2 {
22                        if let (Some(c1), Some(c2)) = (c1.to_str(), c2.to_str()) {
23                            let mut buf = gix_hash::Kind::hex_buf();
24                            {
25                                let (first_byte, rest) = buf[..self.hash_hex_len].split_at_mut(2);
26                                first_byte.copy_from_slice(c1.as_bytes());
27                                rest.copy_from_slice(c2.as_bytes());
28                            }
29                            if let Ok(b) = gix_hash::ObjectId::from_hex(&buf[..self.hash_hex_len]) {
30                                return Some(Ok(b));
31                            }
32                        }
33                    }
34                }
35            }
36            Err(err) => return Some(Err(err)),
37        };
38        None
39    }
40}
41
42impl Iterator for loose::Iter {
43    type Item = Result<gix_hash::ObjectId, Error>;
44
45    fn next(&mut self) -> Option<Self::Item> {
46        while let Some(res) = self.inner.next() {
47            if let Some(res) = self.path_to_id(res) {
48                return Some(res);
49            }
50        }
51        None
52    }
53}
54
55/// Iteration and traversal
56impl loose::Store {
57    /// Return an iterator over all objects contained in the database.
58    ///
59    /// The [`Id`][gix_hash::ObjectId]s returned by the iterator can typically be used in the [`locate(…)`][loose::Store::try_find()] method.
60    /// _Note_ that the result is not sorted or stable, thus ordering can change between runs.
61    ///
62    /// # Notes
63    ///
64    /// [`loose::Iter`] is used instead of `impl Iterator<…>` to allow using this iterator in struct fields, as is currently
65    /// needed if iterators need to be implemented by hand in the absence of generators.
66    pub fn iter(&self) -> loose::Iter {
67        loose::Iter {
68            inner: fs::walkdir_new(
69                &self.path,
70                fs::walkdir::Parallelism::ThreadPoolPerTraversal {
71                    thread_name: "gix_odb::loose::Store::iter: fs-walk",
72                },
73                false,
74            )
75            .min_depth(2)
76            .max_depth(3)
77            .follow_links(false)
78            .into_iter(),
79            hash_hex_len: self.object_hash.len_in_hex(),
80        }
81    }
82}