gix_pack/data/input/
entry.rs1use std::io::Write;
2
3use crate::data::{entry::Header, input};
4
5impl input::Entry {
6 pub fn from_data_obj(obj: &gix_object::Data<'_>, pack_offset: u64) -> Result<Self, input::Error> {
10 let header = to_header(obj.kind);
11 let compressed = compress_data(obj)?;
12 let compressed_size = compressed.len() as u64;
13 let mut entry = input::Entry {
14 header,
15 header_size: header.size(obj.data.len() as u64) as u16,
16 pack_offset,
17 compressed: Some(compressed),
18 compressed_size,
19 crc32: None,
20 decompressed_size: obj.data.len() as u64,
21 trailer: None,
22 };
23 entry.crc32 = Some(entry.compute_crc32());
24 Ok(entry)
25 }
26 pub fn bytes_in_pack(&self) -> u64 {
28 u64::from(self.header_size) + self.compressed_size
29 }
30
31 pub fn compute_crc32(&self) -> u32 {
33 let mut header_buf = [0u8; 12 + gix_hash::Kind::longest().len_in_bytes()];
34 let header_len = self
35 .header
36 .write_to(self.decompressed_size, &mut header_buf.as_mut())
37 .expect("write to memory will not fail");
38 let state = gix_features::hash::crc32_update(0, &header_buf[..header_len]);
39 gix_features::hash::crc32_update(state, self.compressed.as_ref().expect("we always set it"))
40 }
41}
42
43fn to_header(kind: gix_object::Kind) -> Header {
44 use gix_object::Kind::*;
45 match kind {
46 Tree => Header::Tree,
47 Blob => Header::Blob,
48 Commit => Header::Commit,
49 Tag => Header::Tag,
50 }
51}
52
53fn compress_data(obj: &gix_object::Data<'_>) -> Result<Vec<u8>, input::Error> {
54 let mut out = gix_features::zlib::stream::deflate::Write::new(Vec::new());
55 if let Err(err) = std::io::copy(&mut &*obj.data, &mut out) {
56 match err.kind() {
57 std::io::ErrorKind::Other => return Err(input::Error::Io(err)),
58 err => {
59 unreachable!("Should never see other errors than zlib, but got {:?}", err,)
60 }
61 }
62 };
63 out.flush().expect("zlib flush should never fail");
64 Ok(out.into_inner())
65}