76 lines · 3.1 KB · Rust
RawDownload
use std::convert::TryInto; use crate::{extension, extension::Signature, util::from_be_u32}; pub fn header(data: &[u8]) -> (Signature, u32, &[u8]) {    let (signature, data) = data.split_at(4);    let (size, data) = data.split_at(4);    (signature.try_into().unwrap(), from_be_u32(size), data)} mod error {    use crate::extension;     /// The error returned by [extension::decode::all()][extension::decode::all()].    #[derive(Debug, thiserror::Error)]    pub enum Error {        #[error(            "Encountered mandatory extension '{}' which isn't implemented yet",            String::from_utf8_lossy(signature)        )]        MandatoryUnimplemented { signature: extension::Signature },        #[error("Could not parse mandatory link extension")]        Link(#[from] extension::link::decode::Error),    }}pub use error::Error; pub fn all(maybe_beginning_of_extensions: &[u8], object_hash: git_hash::Kind) -> Result<(Outcome, &[u8]), Error> {    let mut ext_iter = match extension::Iter::new_without_checksum(maybe_beginning_of_extensions, object_hash) {        Some(iter) => iter,        None => return Ok((Outcome::default(), maybe_beginning_of_extensions)),    };     let mut ext = Outcome::default();    for (signature, ext_data) in ext_iter.by_ref() {        match signature {            extension::tree::SIGNATURE => {                ext.tree = extension::tree::decode(ext_data, object_hash);            }            extension::resolve_undo::SIGNATURE => {                ext.resolve_undo = extension::resolve_undo::decode(ext_data, object_hash);            }            extension::untracked_cache::SIGNATURE => {                ext.untracked = extension::untracked_cache::decode(ext_data, object_hash);            }            extension::fs_monitor::SIGNATURE => {                ext.fs_monitor = extension::fs_monitor::decode(ext_data);            }            extension::end_of_index_entry::SIGNATURE => {} // skip already done            extension::index_entry_offset_table::SIGNATURE => {} // not relevant/obtained already            mandatory if mandatory[0].is_ascii_lowercase() => match mandatory {                extension::link::SIGNATURE => ext.link = extension::link::decode(ext_data, object_hash)?.into(),                extension::sparse::SIGNATURE => {                    if !ext_data.is_empty() {                        // only used as a marker, if this changes we need this implementation.                        return Err(Error::MandatoryUnimplemented { signature: mandatory });                    }                    ext.is_sparse = true                }                unknown => return Err(Error::MandatoryUnimplemented { signature: unknown }),            },            _unknown => {} // skip unknown extensions, too        }    }    Ok((ext, &maybe_beginning_of_extensions[ext_iter.consumed..]))} #[derive(Default)]pub struct Outcome {    pub tree: Option<extension::Tree>,    pub link: Option<extension::Link>,    pub resolve_undo: Option<extension::resolve_undo::Paths>,    pub untracked: Option<extension::UntrackedCache>,    pub fs_monitor: Option<extension::FsMonitor>,    pub is_sparse: bool,}