git_zero_core/zlib/
stored.rs1use super::adler::Adler32;
4use crate::{Error, Result, io::Write};
5
6pub struct StoredEncoder {
7 remaining: u64,
8 block: u16,
9 adler: Adler32,
10 finished: bool,
11 failure: Option<Error>,
12}
13impl StoredEncoder {
14 pub fn encoded_size(size: u64) -> Result<u64> {
15 let blocks = size / 65535 + u64::from(size % 65535 != 0);
16 size.checked_add(blocks.checked_mul(5).ok_or(Error::LimitExceeded)?)
17 .and_then(|size| size.checked_add(11))
18 .ok_or(Error::LimitExceeded)
19 }
20 pub fn new(size: u64, output: &mut impl Write) -> Result<Self> {
21 Self::encoded_size(size)?;
22 output.write_all(&[0x78, 0x01])?;
23 Ok(Self {
24 remaining: size,
25 block: 0,
26 adler: Adler32::new(),
27 finished: false,
28 failure: None,
29 })
30 }
31 pub fn write(&mut self, bytes: &[u8], output: &mut impl Write) -> Result<()> {
32 let result = self.copy(bytes, output);
33 if let Err(error) = result {
34 self.failure = Some(error);
35 }
36 result
37 }
38 fn ready(&self) -> Result<()> {
39 if let Some(error) = self.failure {
40 return Err(error);
41 }
42 if self.finished {
43 return Err(Error::InvalidRequest);
44 }
45 Ok(())
46 }
47 fn copy(&mut self, mut bytes: &[u8], output: &mut impl Write) -> Result<()> {
48 self.ready()?;
49 if bytes.len() as u64 > self.remaining {
50 return Err(Error::InvalidObject);
51 }
52 while !bytes.is_empty() {
53 if self.block == 0 {
54 self.block = self.remaining.min(65535) as u16;
55 output.write_all(&[0])?;
56 output.write_all(&self.block.to_le_bytes())?;
57 output.write_all(&(!self.block).to_le_bytes())?;
58 }
59 let count = bytes.len().min(usize::from(self.block));
60 output.write_all(&bytes[..count])?;
61 self.adler.update(&bytes[..count]);
62 self.block -= count as u16;
63 self.remaining -= count as u64;
64 bytes = &bytes[count..];
65 }
66 Ok(())
67 }
68 pub fn finish(&mut self, output: &mut impl Write) -> Result<()> {
69 let result = (|| {
70 self.ready()?;
71 if self.remaining != 0 {
72 return Err(Error::InvalidObject);
73 }
74 output.write_all(&[1, 0, 0, 0xff, 0xff])?;
75 output.write_all(&self.adler.value().to_be_bytes())?;
76 self.finished = true;
77 Ok(())
78 })();
79 if let Err(error) = result {
80 self.failure = Some(error);
81 }
82 result
83 }
84}