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