diff options
Diffstat (limited to 'vendor/gix-index/src/extension/iter.rs')
-rw-r--r-- | vendor/gix-index/src/extension/iter.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/vendor/gix-index/src/extension/iter.rs b/vendor/gix-index/src/extension/iter.rs new file mode 100644 index 000000000..f791b064e --- /dev/null +++ b/vendor/gix-index/src/extension/iter.rs @@ -0,0 +1,58 @@ +use std::convert::TryInto; + +use crate::{extension, extension::Iter, util::from_be_u32}; + +impl<'a> Iter<'a> { + /// Create a new extension iterator at the entrypoint for extensions until the end of the extensions. + pub fn new(data_at_beginning_of_extensions_and_truncated: &'a [u8]) -> Self { + Iter { + data: data_at_beginning_of_extensions_and_truncated, + consumed: 0, + } + } + + /// Create a new iterator at with a data block to the end of the file, and we automatically remove the trailing + /// hash of type `object_hash`. + pub fn new_without_checksum( + data_at_beginning_of_extensions: &'a [u8], + object_hash: gix_hash::Kind, + ) -> Option<Self> { + let end = data_at_beginning_of_extensions + .len() + .checked_sub(object_hash.len_in_bytes())?; + Iter { + data: &data_at_beginning_of_extensions[..end], + consumed: 0, + } + .into() + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = (extension::Signature, &'a [u8]); + + fn next(&mut self) -> Option<Self::Item> { + if self.data.len() < 4 + 4 { + return None; + } + + let (signature, data) = self.data.split_at(4); + let (size, data) = data.split_at(4); + self.data = data; + self.consumed += 4 + 4; + + let size = from_be_u32(size) as usize; + + match data.get(..size) { + Some(ext_data) => { + self.data = &data[size..]; + self.consumed += size; + Some((signature.try_into().unwrap(), ext_data)) + } + None => { + self.data = &[]; + None + } + } + } +} |