gix_index/decode/
header.rs

1pub(crate) const SIZE: usize = 4 /*signature*/ + 4 /*version*/ + 4 /* num entries */;
2
3use crate::{util::from_be_u32, Version};
4
5pub(crate) const SIGNATURE: &[u8] = b"DIRC";
6
7mod error {
8
9    /// The error produced when failing to decode an index header.
10    #[derive(Debug, thiserror::Error)]
11    #[allow(missing_docs)]
12    pub enum Error {
13        #[error("{0}")]
14        Corrupt(&'static str),
15        #[error("Index version {0} is not supported")]
16        UnsupportedVersion(u32),
17    }
18}
19pub use error::Error;
20
21pub(crate) fn decode(data: &[u8], object_hash: gix_hash::Kind) -> Result<(Version, u32, &[u8]), Error> {
22    if data.len() < (3 * 4) + object_hash.len_in_bytes() {
23        return Err(Error::Corrupt(
24            "File is too small even for header with zero entries and smallest hash",
25        ));
26    }
27
28    let (signature, data) = data.split_at(4);
29    if signature != SIGNATURE {
30        return Err(Error::Corrupt(
31            "Signature mismatch - this doesn't claim to be a header file",
32        ));
33    }
34
35    let (version, data) = data.split_at(4);
36    let version = match from_be_u32(version) {
37        2 => Version::V2,
38        3 => Version::V3,
39        4 => Version::V4,
40        unknown => return Err(Error::UnsupportedVersion(unknown)),
41    };
42    let (entries, data) = data.split_at(4);
43    let entries = from_be_u32(entries);
44
45    Ok((version, entries, data))
46}