gix_pack/data/file/
init.rs

1use std::path::Path;
2
3use crate::data;
4
5/// Instantiation
6impl data::File {
7    /// Try opening a data file at the given `path`.
8    ///
9    /// The `object_hash` is a way to read (and write) the same file format with different hashes, as the hash kind
10    /// isn't stored within the file format itself.
11    pub fn at(path: impl AsRef<Path>, object_hash: gix_hash::Kind) -> Result<data::File, data::header::decode::Error> {
12        Self::at_inner(path.as_ref(), object_hash)
13    }
14
15    fn at_inner(path: &Path, object_hash: gix_hash::Kind) -> Result<data::File, data::header::decode::Error> {
16        use crate::data::header::N32_SIZE;
17        let hash_len = object_hash.len_in_bytes();
18
19        let data = crate::mmap::read_only(path).map_err(|e| data::header::decode::Error::Io {
20            source: e,
21            path: path.to_owned(),
22        })?;
23        let pack_len = data.len();
24        if pack_len < N32_SIZE * 3 + hash_len {
25            return Err(data::header::decode::Error::Corrupt(format!(
26                "Pack data of size {pack_len} is too small for even an empty pack with shortest hash"
27            )));
28        }
29        let (kind, num_objects) =
30            data::header::decode(&data[..12].try_into().expect("enough data after previous check"))?;
31        Ok(data::File {
32            data,
33            path: path.to_owned(),
34            id: gix_features::hash::crc32(path.as_os_str().to_string_lossy().as_bytes()),
35            version: kind,
36            num_objects,
37            hash_len,
38            object_hash,
39        })
40    }
41}