1use super::{DeltaLimits, decode::variable_byte};
3use crate::{Error, Result};
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum DeltaStatus<'input> {
8 NeedInput,
9 Header { base_size: u64, result_size: u64 },
10 Copy { offset: u64, length: u64 },
11 Insert(&'input [u8]),
12 Finished,
13}
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct DeltaProgress<'input> {
17 pub consumed: usize,
18 pub status: DeltaStatus<'input>,
19}
20
21#[derive(Clone, Copy)]
22enum State {
23 Base,
24 Size,
25 Opcode,
26 Copy(CopyFields),
27 Insert(u8),
28 Done,
29 Failed(Error),
30}
31
32#[derive(Clone, Copy)]
33struct CopyFields {
34 flags: u8,
35 index: u8,
36 offset: u32,
37 length: u32,
38}
39
40impl CopyFields {
41 fn read(&mut self, input: &[u8]) -> (usize, bool) {
42 let mut consumed = 0;
43 while self.index < 7 {
44 if self.flags & (1 << self.index) != 0 {
45 let Some(&byte) = input.get(consumed) else {
46 return (consumed, false);
47 };
48 consumed += 1;
49 if self.index < 4 {
50 self.offset |= u32::from(byte) << (self.index * 8);
51 } else {
52 self.length |= u32::from(byte) << ((self.index - 4) * 8);
53 }
54 }
55 self.index += 1;
56 }
57 (consumed, true)
58 }
59}
60
61pub struct DeltaDecoder {
70 state: State,
71 limits: DeltaLimits,
72 base_size: u64,
73 result_size: u64,
74 position: u64,
75 instructions: u64,
76 variable: u64,
77 shift: u32,
78 depth: u32,
79}
80
81impl DeltaDecoder {
82 pub fn new(base_size: u64, base_depth: u32, limits: DeltaLimits) -> Result<Self> {
83 if base_depth >= limits.max_depth {
84 return Err(Error::LimitExceeded);
85 }
86 Ok(Self {
87 state: State::Base,
88 limits,
89 base_size,
90 result_size: 0,
91 position: 0,
92 instructions: 0,
93 variable: 0,
94 shift: 0,
95 depth: base_depth + 1,
96 })
97 }
98
99 pub fn position(&self) -> u64 {
100 self.position
101 }
102 pub fn depth(&self) -> u32 {
103 self.depth
104 }
105
106 pub fn update<'input>(
111 &mut self,
112 input: &'input [u8],
113 end_of_input: bool,
114 ) -> Result<DeltaProgress<'input>> {
115 let result = self.advance(input, end_of_input);
116 if let Err(error) = result {
117 self.state = State::Failed(error);
118 }
119 result
120 }
121
122 pub fn finish(&self) -> Result<()> {
123 match self.state {
124 State::Done => Ok(()),
125 State::Failed(error) => Err(error),
126 _ => Err(Error::CorruptPack),
127 }
128 }
129
130 fn advance<'input>(&mut self, input: &'input [u8], eof: bool) -> Result<DeltaProgress<'input>> {
131 let mut consumed = 0;
132 loop {
133 let status = match self.state {
134 State::Failed(error) => return Err(error),
135 State::Done => {
136 if !input.is_empty() {
137 return Err(Error::CorruptPack);
138 }
139 Some(DeltaStatus::Finished)
140 }
141 State::Opcode if self.position == self.result_size => {
142 if consumed != input.len() {
143 return Err(Error::CorruptPack);
144 }
145 if eof {
146 self.state = State::Done;
147 Some(DeltaStatus::Finished)
148 } else {
149 Some(DeltaStatus::NeedInput)
150 }
151 }
152 State::Copy(mut fields) => {
153 let (read, complete) = fields.read(&input[consumed..]);
154 consumed += read;
155 if complete {
156 Some(self.copy(fields.offset, fields.length)?)
157 } else {
158 self.state = State::Copy(fields);
159 if eof {
160 return Err(Error::CorruptPack);
161 }
162 Some(DeltaStatus::NeedInput)
163 }
164 }
165 _ if consumed == input.len() => {
166 if eof {
167 return Err(Error::CorruptPack);
168 }
169 Some(DeltaStatus::NeedInput)
170 }
171 State::Base | State::Size => {
172 let byte = input[consumed];
173 consumed += 1;
174 self.size_byte(byte)?
175 }
176 State::Opcode => {
177 self.opcode(input[consumed])?;
178 consumed += 1;
179 None
180 }
181 State::Insert(remaining) => {
182 let length = usize::from(remaining).min(input.len() - consumed);
183 let bytes = &input[consumed..consumed + length];
184 consumed += length;
185 self.emit(length as u64)?;
186 self.state = if length == usize::from(remaining) {
187 State::Opcode
188 } else {
189 State::Insert(remaining - length as u8)
190 };
191 Some(DeltaStatus::Insert(bytes))
192 }
193 };
194 if let Some(status) = status {
195 return Ok(DeltaProgress { consumed, status });
196 }
197 }
198 }
199
200 fn size_byte(&mut self, byte: u8) -> Result<Option<DeltaStatus<'static>>> {
201 let Some(value) = variable_byte(&mut self.variable, &mut self.shift, byte)? else {
202 return Ok(None);
203 };
204 self.variable = 0;
205 self.shift = 0;
206 if matches!(self.state, State::Base) {
207 if value != self.base_size {
208 return Err(Error::CorruptPack);
209 }
210 self.state = State::Size;
211 return Ok(None);
212 }
213 if value > self.limits.max_output {
214 return Err(Error::LimitExceeded);
215 }
216 self.result_size = value;
217 self.state = State::Opcode;
218 Ok(Some(DeltaStatus::Header {
219 base_size: self.base_size,
220 result_size: value,
221 }))
222 }
223
224 fn opcode(&mut self, opcode: u8) -> Result<()> {
225 if self.instructions == self.limits.max_instructions {
226 return Err(Error::LimitExceeded);
227 }
228 self.instructions += 1;
229 self.state = match opcode {
230 0 => return Err(Error::CorruptPack),
231 1..=127 => {
232 if u64::from(opcode) > self.result_size - self.position {
233 return Err(Error::CorruptPack);
234 }
235 State::Insert(opcode)
236 }
237 _ => State::Copy(CopyFields {
238 flags: opcode,
239 index: 0,
240 offset: 0,
241 length: 0,
242 }),
243 };
244 Ok(())
245 }
246
247 fn copy(&mut self, offset: u32, length: u32) -> Result<DeltaStatus<'static>> {
248 let length = if length == 0 {
249 65536
250 } else {
251 u64::from(length)
252 };
253 let offset = u64::from(offset);
254 if offset + length > self.base_size {
255 return Err(Error::CorruptPack);
256 }
257 self.emit(length)?;
258 self.state = State::Opcode;
259 Ok(DeltaStatus::Copy { offset, length })
260 }
261
262 fn emit(&mut self, length: u64) -> Result<()> {
263 if length > self.result_size - self.position {
264 return Err(Error::CorruptPack);
265 }
266 self.position += length;
267 Ok(())
268 }
269}