git_index/extension/
decode.rs1use std::convert::TryInto;
2
3use crate::{extension, extension::Signature, util::from_be_u32};
4
5pub(crate) fn header(data: &[u8]) -> (Signature, u32, &[u8]) {
6 let (signature, data) = data.split_at(4);
7 let (size, data) = data.split_at(4);
8 (signature.try_into().unwrap(), from_be_u32(size), data)
9}
10
11mod error {
12 use crate::extension;
13
14 #[derive(Debug, thiserror::Error)]
16 #[allow(missing_docs)]
17 pub enum Error {
18 #[error(
19 "Encountered mandatory extension '{}' which isn't implemented yet",
20 String::from_utf8_lossy(signature)
21 )]
22 MandatoryUnimplemented { signature: extension::Signature },
23 #[error("Could not parse mandatory link extension")]
24 Link(#[from] extension::link::decode::Error),
25 }
26}
27pub use error::Error;
28
29pub(crate) fn all(
30 maybe_beginning_of_extensions: &[u8],
31 object_hash: git_hash::Kind,
32) -> Result<(Outcome, &[u8]), Error> {
33 let mut ext_iter = match extension::Iter::new_without_checksum(maybe_beginning_of_extensions, object_hash) {
34 Some(iter) => iter,
35 None => return Ok((Outcome::default(), maybe_beginning_of_extensions)),
36 };
37
38 let mut ext = Outcome::default();
39 for (signature, ext_data) in ext_iter.by_ref() {
40 match signature {
41 extension::tree::SIGNATURE => {
42 ext.tree = extension::tree::decode(ext_data, object_hash);
43 }
44 extension::resolve_undo::SIGNATURE => {
45 ext.resolve_undo = extension::resolve_undo::decode(ext_data, object_hash);
46 }
47 extension::untracked_cache::SIGNATURE => {
48 ext.untracked = extension::untracked_cache::decode(ext_data, object_hash);
49 }
50 extension::fs_monitor::SIGNATURE => {
51 ext.fs_monitor = extension::fs_monitor::decode(ext_data);
52 }
53 extension::end_of_index_entry::SIGNATURE => {} extension::index_entry_offset_table::SIGNATURE => {} mandatory if mandatory[0].is_ascii_lowercase() => match mandatory {
56 extension::link::SIGNATURE => ext.link = extension::link::decode(ext_data, object_hash)?.into(),
57 extension::sparse::SIGNATURE => {
58 if !ext_data.is_empty() {
59 return Err(Error::MandatoryUnimplemented { signature: mandatory });
61 }
62 ext.is_sparse = true
63 }
64 unknown => return Err(Error::MandatoryUnimplemented { signature: unknown }),
65 },
66 _unknown => {} }
68 }
69 Ok((ext, &maybe_beginning_of_extensions[ext_iter.consumed..]))
70}
71
72#[derive(Default)]
73pub(crate) struct Outcome {
74 pub tree: Option<extension::Tree>,
75 pub link: Option<extension::Link>,
76 pub resolve_undo: Option<extension::resolve_undo::Paths>,
77 pub untracked: Option<extension::UntrackedCache>,
78 pub fs_monitor: Option<extension::FsMonitor>,
79 pub is_sparse: bool,
80}