git_index/extension/
iter.rs

1use std::convert::TryInto;
2
3use crate::{extension, extension::Iter, util::from_be_u32};
4
5impl<'a> Iter<'a> {
6    /// Create a new extension iterator at the entrypoint for extensions until the end of the extensions.
7    pub fn new(data_at_beginning_of_extensions_and_truncated: &'a [u8]) -> Self {
8        Iter {
9            data: data_at_beginning_of_extensions_and_truncated,
10            consumed: 0,
11        }
12    }
13
14    /// Create a new iterator at with a data block to the end of the file, and we automatically remove the trailing
15    /// hash of type `object_hash`.
16    pub fn new_without_checksum(
17        data_at_beginning_of_extensions: &'a [u8],
18        object_hash: git_hash::Kind,
19    ) -> Option<Self> {
20        let end = data_at_beginning_of_extensions
21            .len()
22            .checked_sub(object_hash.len_in_bytes())?;
23        Iter {
24            data: &data_at_beginning_of_extensions[..end],
25            consumed: 0,
26        }
27        .into()
28    }
29}
30
31impl<'a> Iterator for Iter<'a> {
32    type Item = (extension::Signature, &'a [u8]);
33
34    fn next(&mut self) -> Option<Self::Item> {
35        if self.data.len() < 4 + 4 {
36            return None;
37        }
38
39        let (signature, data) = self.data.split_at(4);
40        let (size, data) = data.split_at(4);
41        self.data = data;
42        self.consumed += 4 + 4;
43
44        let size = from_be_u32(size) as usize;
45
46        match data.get(..size) {
47            Some(ext_data) => {
48                self.data = &data[size..];
49                self.consumed += size;
50                Some((signature.try_into().unwrap(), ext_data))
51            }
52            None => {
53                self.data = &[];
54                None
55            }
56        }
57    }
58}