gix_pack/data/
header.rs

1use crate::data;
2
3pub(crate) const N32_SIZE: usize = std::mem::size_of::<u32>();
4
5/// Parses the first 12 bytes of a pack file, returning the pack version as well as the number of objects contained in the pack.
6pub fn decode(data: &[u8; 12]) -> Result<(data::Version, u32), decode::Error> {
7    let mut ofs = 0;
8    if &data[ofs..ofs + b"PACK".len()] != b"PACK" {
9        return Err(decode::Error::Corrupt("Pack data type not recognized".into()));
10    }
11    ofs += N32_SIZE;
12    let kind = match crate::read_u32(&data[ofs..ofs + N32_SIZE]) {
13        2 => data::Version::V2,
14        3 => data::Version::V3,
15        v => return Err(decode::Error::UnsupportedVersion(v)),
16    };
17    ofs += N32_SIZE;
18    let num_objects = crate::read_u32(&data[ofs..ofs + N32_SIZE]);
19
20    Ok((kind, num_objects))
21}
22
23/// Write a pack data header at `version` with `num_objects` and return a buffer.
24pub fn encode(version: data::Version, num_objects: u32) -> [u8; 12] {
25    use crate::data::Version::*;
26    let mut buf = [0u8; 12];
27    buf[..4].copy_from_slice(b"PACK");
28    buf[4..8].copy_from_slice(
29        &match version {
30            V2 => 2u32,
31            V3 => 3,
32        }
33        .to_be_bytes()[..],
34    );
35    buf[8..].copy_from_slice(&num_objects.to_be_bytes()[..]);
36    buf
37}
38
39///
40pub mod decode {
41    /// Returned by [`decode()`][super::decode()].
42    #[derive(thiserror::Error, Debug)]
43    #[allow(missing_docs)]
44    pub enum Error {
45        #[error("Could not open pack file at '{path}'")]
46        Io {
47            source: std::io::Error,
48            path: std::path::PathBuf,
49        },
50        #[error("{0}")]
51        Corrupt(String),
52        #[error("Unsupported pack version: {0}")]
53        UnsupportedVersion(u32),
54    }
55}