1use super::frame;
8use crate::decoding;
9use crate::decoding::dictionary::Dictionary;
10use crate::decoding::errors::FrameDecoderError;
11use crate::decoding::scratch::DecoderScratch;
12use crate::io::{Error, Read, Write};
13use alloc::collections::BTreeMap;
14use alloc::vec::Vec;
15use core::convert::TryInto;
16
17pub const DEFAULT_MAX_WINDOW_SIZE: u64 = 1024 * 1024 * 100;
21
22pub struct FrameDecoder {
76 state: Option<FrameDecoderState>,
77 prepared_scratch: Option<DecoderScratch>,
78 dicts: BTreeMap<u32, Dictionary>,
79}
80
81struct FrameDecoderState {
82 pub frame_header: frame::FrameHeader,
83 decoder_scratch: DecoderScratch,
84 frame_finished: bool,
85 block_counter: usize,
86 bytes_read_counter: u64,
87 decoded_size_counter: u64,
88 check_sum: Option<u32>,
89 using_dict: Option<u32>,
90}
91
92#[derive(Clone, Copy)]
93pub(crate) enum PreparedDictionaryBytes<'a> {
94 Formatted(&'a [u8]),
95 Raw(&'a [u8]),
96}
97
98pub enum BlockDecodingStrategy {
99 All,
100 UptoBlocks(usize),
101 UptoBytes(usize),
102}
103
104impl FrameDecoderState {
105 fn from_header(
106 frame: frame::FrameHeader,
107 header_size: u8,
108 window_size: usize,
109 scratch: Option<DecoderScratch>,
110 ) -> FrameDecoderState {
111 let mut decoder_scratch = scratch.unwrap_or_else(|| DecoderScratch::new(window_size));
112 decoder_scratch.reset(window_size);
113 FrameDecoderState {
114 frame_header: frame,
115 frame_finished: false,
116 block_counter: 0,
117 decoder_scratch,
118 bytes_read_counter: u64::from(header_size),
119 decoded_size_counter: 0,
120 check_sum: None,
121 using_dict: None,
122 }
123 }
124
125 pub fn reset(
126 &mut self,
127 source: impl Read,
128 max_window_size: u64,
129 ) -> Result<(), FrameDecoderError> {
130 let (frame_header, header_size) = frame::read_frame_header(source)?;
131 let window_size = frame_header.window_size()?;
132
133 if window_size > max_window_size {
134 return Err(FrameDecoderError::WindowSizeTooBig {
135 requested: window_size,
136 });
137 }
138
139 self.frame_header = frame_header;
140 self.frame_finished = false;
141 self.block_counter = 0;
142 self.decoder_scratch.reset(window_size as usize);
143 self.bytes_read_counter = u64::from(header_size);
144 self.decoded_size_counter = 0;
145 self.check_sum = None;
146 self.using_dict = None;
147 Ok(())
148 }
149}
150
151impl Default for FrameDecoder {
152 fn default() -> Self {
153 Self::new()
154 }
155}
156
157impl FrameDecoder {
158 pub fn new() -> FrameDecoder {
162 FrameDecoder {
163 state: None,
164 prepared_scratch: None,
165 dicts: BTreeMap::new(),
166 }
167 }
168
169 pub(crate) fn prepare_workspace(&mut self, max_window_size: usize, max_dictionary_size: usize) {
170 let mut scratch = self
171 .state
172 .take()
173 .map(|state| state.decoder_scratch)
174 .or_else(|| self.prepared_scratch.take())
175 .unwrap_or_else(|| DecoderScratch::new(0));
176 scratch.reset(0);
177 scratch.reserve_workspace(max_window_size, max_dictionary_size);
178 self.prepared_scratch = Some(scratch);
179 }
180
181 pub(crate) fn install_prepared_scratch(&mut self, scratch: DecoderScratch) {
182 self.state = None;
183 self.prepared_scratch = Some(scratch);
184 }
185
186 pub fn init(&mut self, source: impl Read) -> Result<(), FrameDecoderError> {
193 self.reset(source)
194 }
195
196 pub fn reset(&mut self, source: impl Read) -> Result<(), FrameDecoderError> {
203 self.reset_with_window_limit(source, DEFAULT_MAX_WINDOW_SIZE)
204 }
205
206 pub(crate) fn reset_with_window_limit(
207 &mut self,
208 source: impl Read,
209 max_window_size: u64,
210 ) -> Result<(), FrameDecoderError> {
211 self.reset_with_window_limit_and_dictionary(source, max_window_size, None)
212 }
213
214 fn reset_with_window_limit_and_dictionary(
215 &mut self,
216 source: impl Read,
217 max_window_size: u64,
218 dictionary: Option<PreparedDictionaryBytes<'_>>,
219 ) -> Result<(), FrameDecoderError> {
220 use FrameDecoderError as err;
221 let state = match &mut self.state {
222 Some(s) => {
223 s.reset(source, max_window_size)?;
224 s
225 }
226 None => {
227 let (frame_header, header_size) = frame::read_frame_header(source)?;
231 let window_size = frame_header.window_size()?;
232 if window_size > max_window_size {
233 return Err(FrameDecoderError::WindowSizeTooBig {
234 requested: window_size,
235 });
236 }
237 self.state = Some(FrameDecoderState::from_header(
238 frame_header,
239 header_size,
240 window_size as usize,
241 self.prepared_scratch.take(),
242 ));
243 self.state.as_mut().unwrap()
244 }
245 };
246 if let Some(dict_id) = state.frame_header.dictionary_id() {
247 if let Some(PreparedDictionaryBytes::Formatted(dictionary)) = dictionary {
248 let provided_id = state.decoder_scratch.init_from_dict_bytes(dictionary)?;
249 if provided_id != dict_id {
250 return Err(err::DictNotProvided { dict_id });
251 }
252 } else if dictionary.is_some() {
253 return Err(err::DictNotProvided { dict_id });
254 } else {
255 let dict = self
256 .dicts
257 .get(&dict_id)
258 .ok_or(err::DictNotProvided { dict_id })?;
259 state.decoder_scratch.init_from_dict(dict);
260 }
261 state.using_dict = Some(dict_id);
262 } else if let Some(PreparedDictionaryBytes::Raw(dictionary)) = dictionary {
263 state.decoder_scratch.init_from_raw_dictionary(dictionary);
264 }
265 Ok(())
266 }
267
268 pub fn add_dict(&mut self, dict: Dictionary) -> Result<(), FrameDecoderError> {
270 self.dicts.insert(dict.id, dict);
271 Ok(())
272 }
273
274 pub fn force_dict(&mut self, dict_id: u32) -> Result<(), FrameDecoderError> {
275 use FrameDecoderError as err;
276 let Some(state) = self.state.as_mut() else {
277 return Err(err::NotYetInitialized);
278 };
279
280 let dict = self
281 .dicts
282 .get(&dict_id)
283 .ok_or(err::DictNotProvided { dict_id })?;
284 state.decoder_scratch.init_from_dict(dict);
285 state.using_dict = Some(dict_id);
286
287 Ok(())
288 }
289
290 pub fn content_size(&self) -> u64 {
292 match &self.state {
293 None => 0,
294 Some(s) => s.frame_header.frame_content_size(),
295 }
296 }
297
298 pub fn get_checksum_from_data(&self) -> Option<u32> {
300 let state = self.state.as_ref()?;
301
302 state.check_sum
303 }
304
305 #[cfg(feature = "hash")]
308 pub fn get_calculated_checksum(&self) -> Option<u32> {
309 use core::hash::Hasher;
310
311 let state = self.state.as_ref()?;
312 let cksum_64bit = state.decoder_scratch.buffer.hash.finish();
313 Some(cksum_64bit as u32)
315 }
316
317 pub fn bytes_read_from_source(&self) -> u64 {
319 let state = match &self.state {
320 None => return 0,
321 Some(s) => s,
322 };
323 state.bytes_read_counter
324 }
325
326 pub fn decoded_size(&self) -> u64 {
328 let state = match &self.state {
329 None => return 0,
330 Some(s) => s,
331 };
332 state.decoded_size_counter
333 }
334
335 pub fn is_finished(&self) -> bool {
339 let state = match &self.state {
340 None => return true,
341 Some(s) => s,
342 };
343 if state.frame_header.descriptor.content_checksum_flag() {
344 state.frame_finished && state.check_sum.is_some()
345 } else {
346 state.frame_finished
347 }
348 }
349
350 pub fn blocks_decoded(&self) -> usize {
352 let state = match &self.state {
353 None => return 0,
354 Some(s) => s,
355 };
356 state.block_counter
357 }
358
359 pub fn decode_blocks(
364 &mut self,
365 mut source: impl Read,
366 strat: BlockDecodingStrategy,
367 ) -> Result<bool, FrameDecoderError> {
368 use FrameDecoderError as err;
369 let state = self.state.as_mut().ok_or(err::NotYetInitialized)?;
370
371 let mut block_dec = decoding::block_decoder::new();
372
373 let buffer_size_before = state.decoder_scratch.buffer.len();
374 let block_counter_before = state.block_counter;
375 loop {
376 vprintln!("################");
377 vprintln!("Next Block: {}", state.block_counter);
378 vprintln!("################");
379 let (block_header, block_header_size) = block_dec
380 .read_block_header(&mut source)
381 .map_err(err::FailedToReadBlockHeader)?;
382 state.bytes_read_counter += u64::from(block_header_size);
383
384 vprintln!();
385 vprintln!(
386 "Found {} block with size: {}, which will be of size: {}",
387 block_header.block_type,
388 block_header.content_size,
389 block_header.decompressed_size
390 );
391
392 let decoded_size_before_block = state.decoder_scratch.buffer.len();
393 let bytes_read_in_block_body = block_dec
394 .decode_block_content(&block_header, &mut state.decoder_scratch, &mut source)
395 .map_err(err::FailedToReadBlockBody)?;
396 state.bytes_read_counter += bytes_read_in_block_body;
397 state.decoded_size_counter +=
398 (state.decoder_scratch.buffer.len() - decoded_size_before_block) as u64;
399
400 state.block_counter += 1;
401
402 vprintln!("Output: {}", state.decoder_scratch.buffer.len());
403
404 if block_header.last_block {
405 state.frame_finished = true;
406 if state.frame_header.descriptor.content_checksum_flag() {
407 let mut chksum = [0u8; 4];
408 source
409 .read_exact(&mut chksum)
410 .map_err(err::FailedToReadChecksum)?;
411 state.bytes_read_counter += 4;
412 let chksum = u32::from_le_bytes(chksum);
413 state.check_sum = Some(chksum);
414 }
415 break;
416 }
417
418 match strat {
419 BlockDecodingStrategy::All => { }
420 BlockDecodingStrategy::UptoBlocks(n) => {
421 if state.block_counter - block_counter_before >= n {
422 break;
423 }
424 }
425 BlockDecodingStrategy::UptoBytes(n) => {
426 if state.decoder_scratch.buffer.len() - buffer_size_before >= n {
427 break;
428 }
429 }
430 }
431 }
432
433 Ok(state.frame_finished)
434 }
435
436 pub fn collect(&mut self) -> Option<Vec<u8>> {
439 let finished = self.is_finished();
440 let state = self.state.as_mut()?;
441 if finished {
442 Some(state.decoder_scratch.buffer.drain())
443 } else {
444 state.decoder_scratch.buffer.drain_to_window_size()
445 }
446 }
447
448 pub fn collect_to_writer(&mut self, w: impl Write) -> Result<usize, Error> {
451 let finished = self.is_finished();
452 let state = match &mut self.state {
453 None => return Ok(0),
454 Some(s) => s,
455 };
456 if finished {
457 state.decoder_scratch.buffer.drain_to_writer(w)
458 } else {
459 state.decoder_scratch.buffer.drain_to_window_size_writer(w)
460 }
461 }
462
463 pub fn can_collect(&self) -> usize {
467 let finished = self.is_finished();
468 let state = match &self.state {
469 None => return 0,
470 Some(s) => s,
471 };
472 if finished {
473 state.decoder_scratch.buffer.can_drain()
474 } else {
475 state
476 .decoder_scratch
477 .buffer
478 .can_drain_to_window_size()
479 .unwrap_or(0)
480 }
481 }
482
483 pub fn decode_from_to(
497 &mut self,
498 source: &[u8],
499 target: &mut [u8],
500 ) -> Result<(usize, usize), FrameDecoderError> {
501 use FrameDecoderError as err;
502 let bytes_read_at_start = match &self.state {
503 Some(s) => s.bytes_read_counter,
504 None => 0,
505 };
506
507 if !self.is_finished() || self.state.is_none() {
508 let mut mt_source = source;
509
510 if self.state.is_none() {
511 self.init(&mut mt_source)?;
512 }
513
514 {
516 let state = match &mut self.state {
517 Some(s) => s,
518 None => panic!("Bug in library"),
519 };
520 let mut block_dec = decoding::block_decoder::new();
521
522 if state.frame_header.descriptor.content_checksum_flag()
523 && state.frame_finished
524 && state.check_sum.is_none()
525 {
526 if mt_source.len() >= 4 {
528 let chksum = mt_source[..4].try_into().expect("optimized away");
529 state.bytes_read_counter += 4;
530 let chksum = u32::from_le_bytes(chksum);
531 state.check_sum = Some(chksum);
532 }
533 return Ok((4, 0));
534 }
535
536 loop {
537 if mt_source.len() < 3 {
539 break;
540 }
541 let (block_header, block_header_size) = block_dec
542 .read_block_header(&mut mt_source)
543 .map_err(err::FailedToReadBlockHeader)?;
544
545 if mt_source.len() < block_header.content_size as usize {
548 break;
549 }
550 state.bytes_read_counter += u64::from(block_header_size);
551
552 let bytes_read_in_block_body = block_dec
553 .decode_block_content(
554 &block_header,
555 &mut state.decoder_scratch,
556 &mut mt_source,
557 )
558 .map_err(err::FailedToReadBlockBody)?;
559 state.bytes_read_counter += bytes_read_in_block_body;
560 state.block_counter += 1;
561
562 if block_header.last_block {
563 state.frame_finished = true;
564 if state.frame_header.descriptor.content_checksum_flag() {
565 if mt_source.len() >= 4 {
567 let chksum = mt_source[..4].try_into().expect("optimized away");
568 state.bytes_read_counter += 4;
569 let chksum = u32::from_le_bytes(chksum);
570 state.check_sum = Some(chksum);
571 }
572 }
573 break;
574 }
575 }
576 }
577 }
578
579 let result_len = self.read(target).map_err(err::FailedToDrainDecodebuffer)?;
580 let bytes_read_at_end = match &mut self.state {
581 Some(s) => s.bytes_read_counter,
582 None => panic!("Bug in library"),
583 };
584 let read_len = bytes_read_at_end - bytes_read_at_start;
585 Ok((read_len as usize, result_len))
586 }
587
588 pub fn decode_all(
599 &mut self,
600 input: &[u8],
601 output: &mut [u8],
602 ) -> Result<usize, FrameDecoderError> {
603 self.decode_all_with_window_limit(input, output, DEFAULT_MAX_WINDOW_SIZE)
604 }
605
606 pub(crate) fn decode_all_with_window_limit(
607 &mut self,
608 input: &[u8],
609 output: &mut [u8],
610 max_window_size: u64,
611 ) -> Result<usize, FrameDecoderError> {
612 self.decode_all_with_window_limit_and_dictionary(input, output, max_window_size, None)
613 }
614
615 pub(crate) fn decode_all_with_window_limit_and_dictionary(
616 &mut self,
617 mut input: &[u8],
618 mut output: &mut [u8],
619 max_window_size: u64,
620 dictionary: Option<PreparedDictionaryBytes<'_>>,
621 ) -> Result<usize, FrameDecoderError> {
622 let mut total_bytes_written = 0;
623 while !input.is_empty() {
624 match self.reset_with_window_limit_and_dictionary(
625 &mut input,
626 max_window_size,
627 dictionary,
628 ) {
629 Ok(_) => {}
630 Err(FrameDecoderError::ReadFrameHeaderError(
631 crate::decoding::errors::ReadFrameHeaderError::SkipFrame { length, .. },
632 )) => {
633 input = input
634 .get(length as usize..)
635 .ok_or(FrameDecoderError::FailedToSkipFrame)?;
636 continue;
637 }
638 Err(e) => return Err(e),
639 };
640 loop {
641 self.decode_blocks(&mut input, BlockDecodingStrategy::UptoBytes(1024 * 1024))?;
642 let bytes_written = self
643 .read(output)
644 .map_err(FrameDecoderError::FailedToDrainDecodebuffer)?;
645 output = &mut output[bytes_written..];
646 total_bytes_written += bytes_written;
647 if self.can_collect() != 0 {
648 return Err(FrameDecoderError::TargetTooSmall);
649 }
650 if self.is_finished() {
651 break;
652 }
653 }
654 }
655
656 Ok(total_bytes_written)
657 }
658
659 pub fn decode_all_to_vec(
672 &mut self,
673 input: &[u8],
674 output: &mut Vec<u8>,
675 ) -> Result<(), FrameDecoderError> {
676 let len = output.len();
677 let cap = output.capacity();
678 output.resize(cap, 0);
679 match self.decode_all(input, &mut output[len..]) {
680 Ok(bytes_written) => {
681 let new_len = core::cmp::min(len + bytes_written, cap); output.resize(new_len, 0);
683 Ok(())
684 }
685 Err(e) => {
686 output.resize(len, 0);
687 Err(e)
688 }
689 }
690 }
691}
692
693impl Read for FrameDecoder {
696 fn read(&mut self, target: &mut [u8]) -> Result<usize, Error> {
697 let state = match &mut self.state {
698 None => return Ok(0),
699 Some(s) => s,
700 };
701 if state.frame_finished {
702 state.decoder_scratch.buffer.read_all(target)
703 } else {
704 state.decoder_scratch.buffer.read(target)
705 }
706 }
707}