engine/snapshot/compression/
decoder.rs1use thiserror::Error as DeriveError;
5
6#[derive(Debug, DeriveError)]
7#[error("Lz4 Decode Failed: {0}")]
8pub struct Lz4DecodeError(String);
9
10pub fn decompress_into(input: &[u8], output: &mut Vec<u8>) -> Result<(), Lz4DecodeError> {
12 Lz4Decoder {
13 input,
14 output,
15 token: 0,
16 }
17 .complete()?;
18
19 Ok(())
20}
21
22pub fn decompress(input: &[u8]) -> Result<Vec<u8>, Lz4DecodeError> {
24 let mut vec = Vec::with_capacity(4096);
25
26 decompress_into(input, &mut vec)?;
27
28 Ok(vec)
29}
30
31struct Lz4Decoder<'a> {
33 input: &'a [u8],
34 output: &'a mut Vec<u8>,
35 token: u8,
36}
37
38impl<'a> Lz4Decoder<'a> {
39 fn take(&mut self, size: usize) -> Result<&[u8], Lz4DecodeError> {
40 Self::take_internal(&mut self.input, size)
41 }
42
43 #[inline]
44 fn take_internal(input: &mut &'a [u8], size: usize) -> Result<&'a [u8], Lz4DecodeError> {
45 if input.len() < size {
46 Err(Lz4DecodeError("Unexpected End".into()))
47 } else {
48 let res = Ok(&input[..size]);
49
50 *input = &input[size..];
51
52 res
53 }
54 }
55
56 fn output(output: &mut Vec<u8>, buf: &[u8]) {
57 output.extend_from_slice(&buf[..buf.len()]);
58 }
59
60 fn duplicate(&mut self, start: usize, length: usize) {
61 for i in start..start + length {
62 let b = self.output[i];
63 self.output.push(b);
64 }
65 }
66
67 #[inline]
68 fn read_int(&mut self) -> Result<usize, Lz4DecodeError> {
69 let mut size = 0;
70
71 loop {
72 let extra = self.take(1)?[0];
73 size += extra as usize;
74
75 if extra != 0xFF {
76 break;
77 }
78 }
79
80 Ok(size)
81 }
82
83 fn read_u16(&mut self) -> Result<u16, Lz4DecodeError> {
84 let bytes = self.take(2)?.try_into().expect("Conversion can never fail.");
85 Ok(u16::from_le_bytes(bytes))
86 }
87
88 fn read_literal(&mut self) -> Result<(), Lz4DecodeError> {
89 let mut literal = (self.token >> 4) as usize;
90
91 if literal == 15 {
92 literal += self.read_int()?;
93 }
94
95 Self::output(self.output, Self::take_internal(&mut self.input, literal)?);
96
97 Ok(())
98 }
99
100 fn read_duplicate(&mut self) -> Result<(), Lz4DecodeError> {
101 let offset = self.read_u16()?;
102
103 let mut length = (4 + (self.token & 0xF)) as usize;
104
105 if length == 4 + 15 {
106 length += self.read_int()?;
107 }
108
109 let start = self.output.len().wrapping_sub(offset as usize);
110
111 if start < self.output.len() {
112 self.duplicate(start, length);
113
114 Ok(())
115 } else {
116 Err(Lz4DecodeError("Invalid Duplicate".into()))
117 }
118 }
119
120 #[inline]
121 fn complete(&mut self) -> Result<(), Lz4DecodeError> {
122 while !self.input.is_empty() {
123 self.token = self.take(1)?[0];
124
125 self.read_literal()?;
126
127 if self.input.is_empty() {
128 break;
129 }
130
131 self.read_duplicate()?;
132 }
133
134 Ok(())
135 }
136}