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