65 lines · 1.9 KB · Rust
RawDownload
use crate::pack::data;use byteorder::{BigEndian, ByteOrder};use filebuffer::FileBuffer;use git_object::SHA1_SIZE;use quick_error::quick_error;use std::{convert::TryFrom, mem::size_of, path::Path}; quick_error! {    #[derive(Debug)]    pub enum Error {        Io(err: std::io::Error, path: std::path::PathBuf) {            display("Could not open pack file at '{}'", path.display())            cause(err)        }        Corrupt(msg: String) {            display("{}", msg)        }        UnsupportedVersion(version: u32) {            display("Unsupported pack version: {}", version)        }    }} const N32_SIZE: usize = size_of::<u32>(); /// Instantiationimpl data::File {    pub fn at(path: impl AsRef<Path>) -> Result<data::File, Error> {        data::File::try_from(path.as_ref())    }} impl TryFrom<&Path> for data::File {    type Error = Error;     fn try_from(path: &Path) -> Result<Self, Self::Error> {        let data = FileBuffer::open(path).map_err(|e| Error::Io(e, path.to_owned()))?;        let pack_len = data.len();        if pack_len < N32_SIZE * 3 + SHA1_SIZE {            return Err(Error::Corrupt(format!(                "Pack data of size {} is too small for even an empty pack",                pack_len            )));        }        let mut ofs = 0;        if &data[ofs..ofs + b"PACK".len()] != b"PACK" {            return Err(Error::Corrupt("Pack data type not recognized".into()));        }        ofs += N32_SIZE;        let kind = match BigEndian::read_u32(&data[ofs..ofs + N32_SIZE]) {            2 => data::Kind::V2,            3 => data::Kind::V3,            v => return Err(Error::UnsupportedVersion(v)),        };        ofs += N32_SIZE;        let num_objects = BigEndian::read_u32(&data[ofs..ofs + N32_SIZE]);         Ok(data::File {            data,            path: path.to_owned(),            kind,            num_objects,        })    }}