1use super::frame;
8use crate::decoding::dictionary::Dictionary;
9use crate::decoding::scratch::DecoderScratch;
10use crate::decoding::{self, dictionary};
11use crate::io::{Error, Read, Write};
12use alloc::collections::BTreeMap;
13use alloc::vec::Vec;
14use core::convert::TryInto;
15#[cfg(feature = "std")]
16use std::error::Error as StdError;
17
18pub struct FrameDecoder {
72 state: Option<FrameDecoderState>,
73 dicts: BTreeMap<u32, Dictionary>,
74}
75
76struct FrameDecoderState {
77 pub frame: frame::Frame,
78 decoder_scratch: DecoderScratch,
79 frame_finished: bool,
80 block_counter: usize,
81 bytes_read_counter: u64,
82 check_sum: Option<u32>,
83 using_dict: Option<u32>,
84}
85
86pub enum BlockDecodingStrategy {
87 All,
88 UptoBlocks(usize),
89 UptoBytes(usize),
90}
91
92#[derive(Debug)]
93#[non_exhaustive]
94pub enum FrameDecoderError {
95 ReadFrameHeaderError(frame::ReadFrameHeaderError),
96 FrameHeaderError(frame::FrameHeaderError),
97 WindowSizeTooBig { requested: u64 },
98 DictionaryDecodeError(dictionary::DictionaryDecodeError),
99 FailedToReadBlockHeader(decoding::block_decoder::BlockHeaderReadError),
100 FailedToReadBlockBody(decoding::block_decoder::DecodeBlockContentError),
101 FailedToReadChecksum(Error),
102 NotYetInitialized,
103 FailedToInitialize(frame::FrameHeaderError),
104 FailedToDrainDecodebuffer(Error),
105 FailedToSkipFrame,
106 TargetTooSmall,
107 DictNotProvided { dict_id: u32 },
108}
109
110#[cfg(feature = "std")]
111impl StdError for FrameDecoderError {
112 fn source(&self) -> Option<&(dyn StdError + 'static)> {
113 match self {
114 FrameDecoderError::ReadFrameHeaderError(source) => Some(source),
115 FrameDecoderError::FrameHeaderError(source) => Some(source),
116 FrameDecoderError::DictionaryDecodeError(source) => Some(source),
117 FrameDecoderError::FailedToReadBlockHeader(source) => Some(source),
118 FrameDecoderError::FailedToReadBlockBody(source) => Some(source),
119 FrameDecoderError::FailedToReadChecksum(source) => Some(source),
120 FrameDecoderError::FailedToInitialize(source) => Some(source),
121 FrameDecoderError::FailedToDrainDecodebuffer(source) => Some(source),
122 _ => None,
123 }
124 }
125}
126
127impl core::fmt::Display for FrameDecoderError {
128 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result {
129 match self {
130 FrameDecoderError::ReadFrameHeaderError(e) => {
131 write!(f, "{:?}", e)
132 }
133 FrameDecoderError::FrameHeaderError(e) => {
134 write!(f, "{:?}", e)
135 }
136 FrameDecoderError::WindowSizeTooBig { requested } => {
137 write!(
138 f,
139 "Specified window_size is too big; Requested: {}, Max: {}",
140 requested, MAX_WINDOW_SIZE,
141 )
142 }
143 FrameDecoderError::DictionaryDecodeError(e) => {
144 write!(f, "{:?}", e)
145 }
146 FrameDecoderError::FailedToReadBlockHeader(e) => {
147 write!(f, "Failed to parse/decode block body: {}", e)
148 }
149 FrameDecoderError::FailedToReadBlockBody(e) => {
150 write!(f, "Failed to parse block header: {}", e)
151 }
152 FrameDecoderError::FailedToReadChecksum(e) => {
153 write!(f, "Failed to read checksum: {}", e)
154 }
155 FrameDecoderError::NotYetInitialized => {
156 write!(f, "Decoder must initialized or reset before using it",)
157 }
158 FrameDecoderError::FailedToInitialize(e) => {
159 write!(f, "Decoder encountered error while initializing: {}", e)
160 }
161 FrameDecoderError::FailedToDrainDecodebuffer(e) => {
162 write!(
163 f,
164 "Decoder encountered error while draining the decodebuffer: {}",
165 e,
166 )
167 }
168 FrameDecoderError::FailedToSkipFrame => {
169 write!(
170 f,
171 "Failed to skip bytes for the length given in the frame header"
172 )
173 }
174 FrameDecoderError::TargetTooSmall => {
175 write!(f, "Target must have at least as many bytes as the contentsize of the frame reports")
176 }
177 FrameDecoderError::DictNotProvided { dict_id } => {
178 write!(f, "Frame header specified dictionary id 0x{:X} that wasnt provided by add_dict() or reset_with_dict()", dict_id)
179 }
180 }
181 }
182}
183
184impl From<dictionary::DictionaryDecodeError> for FrameDecoderError {
185 fn from(val: dictionary::DictionaryDecodeError) -> Self {
186 Self::DictionaryDecodeError(val)
187 }
188}
189
190impl From<decoding::block_decoder::BlockHeaderReadError> for FrameDecoderError {
191 fn from(val: decoding::block_decoder::BlockHeaderReadError) -> Self {
192 Self::FailedToReadBlockHeader(val)
193 }
194}
195
196impl From<frame::FrameHeaderError> for FrameDecoderError {
197 fn from(val: frame::FrameHeaderError) -> Self {
198 Self::FrameHeaderError(val)
199 }
200}
201
202impl From<frame::ReadFrameHeaderError> for FrameDecoderError {
203 fn from(val: frame::ReadFrameHeaderError) -> Self {
204 Self::ReadFrameHeaderError(val)
205 }
206}
207
208const MAX_WINDOW_SIZE: u64 = 1024 * 1024 * 100;
209
210impl FrameDecoderState {
211 pub fn new(source: impl Read) -> Result<FrameDecoderState, FrameDecoderError> {
212 let (frame, header_size) = frame::read_frame_header(source)?;
213 let window_size = frame.header.window_size()?;
214 Ok(FrameDecoderState {
215 frame,
216 frame_finished: false,
217 block_counter: 0,
218 decoder_scratch: DecoderScratch::new(window_size as usize),
219 bytes_read_counter: u64::from(header_size),
220 check_sum: None,
221 using_dict: None,
222 })
223 }
224
225 pub fn reset(&mut self, source: impl Read) -> Result<(), FrameDecoderError> {
226 let (frame, header_size) = frame::read_frame_header(source)?;
227 let window_size = frame.header.window_size()?;
228
229 if window_size > MAX_WINDOW_SIZE {
230 return Err(FrameDecoderError::WindowSizeTooBig {
231 requested: window_size,
232 });
233 }
234
235 self.frame = frame;
236 self.frame_finished = false;
237 self.block_counter = 0;
238 self.decoder_scratch.reset(window_size as usize);
239 self.bytes_read_counter = u64::from(header_size);
240 self.check_sum = None;
241 self.using_dict = None;
242 Ok(())
243 }
244}
245
246impl Default for FrameDecoder {
247 fn default() -> Self {
248 Self::new()
249 }
250}
251
252impl FrameDecoder {
253 pub fn new() -> FrameDecoder {
257 FrameDecoder {
258 state: None,
259 dicts: BTreeMap::new(),
260 }
261 }
262
263 pub fn init(&mut self, source: impl Read) -> Result<(), FrameDecoderError> {
270 self.reset(source)
271 }
272
273 pub fn reset(&mut self, source: impl Read) -> Result<(), FrameDecoderError> {
280 use FrameDecoderError as err;
281 let state = match &mut self.state {
282 Some(s) => {
283 s.reset(source)?;
284 s
285 }
286 None => {
287 self.state = Some(FrameDecoderState::new(source)?);
288 self.state.as_mut().unwrap()
289 }
290 };
291 if let Some(dict_id) = state.frame.header.dictionary_id() {
292 let dict = self
293 .dicts
294 .get(&dict_id)
295 .ok_or(err::DictNotProvided { dict_id })?;
296 state.decoder_scratch.init_from_dict(dict);
297 state.using_dict = Some(dict_id);
298 }
299 Ok(())
300 }
301
302 pub fn add_dict(&mut self, dict: Dictionary) -> Result<(), FrameDecoderError> {
304 self.dicts.insert(dict.id, dict);
305 Ok(())
306 }
307
308 pub fn force_dict(&mut self, dict_id: u32) -> Result<(), FrameDecoderError> {
309 use FrameDecoderError as err;
310 let Some(state) = self.state.as_mut() else {
311 return Err(err::NotYetInitialized);
312 };
313
314 let dict = self
315 .dicts
316 .get(&dict_id)
317 .ok_or(err::DictNotProvided { dict_id })?;
318 state.decoder_scratch.init_from_dict(dict);
319 state.using_dict = Some(dict_id);
320
321 Ok(())
322 }
323
324 pub fn content_size(&self) -> u64 {
326 match &self.state {
327 None => 0,
328 Some(s) => s.frame.header.frame_content_size(),
329 }
330 }
331
332 pub fn get_checksum_from_data(&self) -> Option<u32> {
334 let state = match &self.state {
335 None => return None,
336 Some(s) => s,
337 };
338
339 state.check_sum
340 }
341
342 #[cfg(feature = "hash")]
345 pub fn get_calculated_checksum(&self) -> Option<u32> {
346 use core::hash::Hasher;
347
348 let state = match &self.state {
349 None => return None,
350 Some(s) => s,
351 };
352 let cksum_64bit = state.decoder_scratch.buffer.hash.finish();
353 Some(cksum_64bit as u32)
355 }
356
357 pub fn bytes_read_from_source(&self) -> u64 {
359 let state = match &self.state {
360 None => return 0,
361 Some(s) => s,
362 };
363 state.bytes_read_counter
364 }
365
366 pub fn is_finished(&self) -> bool {
370 let state = match &self.state {
371 None => return true,
372 Some(s) => s,
373 };
374 if state.frame.header.descriptor.content_checksum_flag() {
375 state.frame_finished && state.check_sum.is_some()
376 } else {
377 state.frame_finished
378 }
379 }
380
381 pub fn blocks_decoded(&self) -> usize {
383 let state = match &self.state {
384 None => return 0,
385 Some(s) => s,
386 };
387 state.block_counter
388 }
389
390 pub fn decode_blocks(
395 &mut self,
396 mut source: impl Read,
397 strat: BlockDecodingStrategy,
398 ) -> Result<bool, FrameDecoderError> {
399 use FrameDecoderError as err;
400 let state = self.state.as_mut().ok_or(err::NotYetInitialized)?;
401
402 let mut block_dec = decoding::block_decoder::new();
403
404 let buffer_size_before = state.decoder_scratch.buffer.len();
405 let block_counter_before = state.block_counter;
406 loop {
407 vprintln!("################");
408 vprintln!("Next Block: {}", state.block_counter);
409 vprintln!("################");
410 let (block_header, block_header_size) = block_dec
411 .read_block_header(&mut source)
412 .map_err(err::FailedToReadBlockHeader)?;
413 state.bytes_read_counter += u64::from(block_header_size);
414
415 vprintln!();
416 vprintln!(
417 "Found {} block with size: {}, which will be of size: {}",
418 block_header.block_type,
419 block_header.content_size,
420 block_header.decompressed_size
421 );
422
423 let bytes_read_in_block_body = block_dec
424 .decode_block_content(&block_header, &mut state.decoder_scratch, &mut source)
425 .map_err(err::FailedToReadBlockBody)?;
426 state.bytes_read_counter += bytes_read_in_block_body;
427
428 state.block_counter += 1;
429
430 vprintln!("Output: {}", state.decoder_scratch.buffer.len());
431
432 if block_header.last_block {
433 state.frame_finished = true;
434 if state.frame.header.descriptor.content_checksum_flag() {
435 let mut chksum = [0u8; 4];
436 source
437 .read_exact(&mut chksum)
438 .map_err(err::FailedToReadChecksum)?;
439 state.bytes_read_counter += 4;
440 let chksum = u32::from_le_bytes(chksum);
441 state.check_sum = Some(chksum);
442 }
443 break;
444 }
445
446 match strat {
447 BlockDecodingStrategy::All => { }
448 BlockDecodingStrategy::UptoBlocks(n) => {
449 if state.block_counter - block_counter_before >= n {
450 break;
451 }
452 }
453 BlockDecodingStrategy::UptoBytes(n) => {
454 if state.decoder_scratch.buffer.len() - buffer_size_before >= n {
455 break;
456 }
457 }
458 }
459 }
460
461 Ok(state.frame_finished)
462 }
463
464 pub fn collect(&mut self) -> Option<Vec<u8>> {
467 let finished = self.is_finished();
468 let state = self.state.as_mut()?;
469 if finished {
470 Some(state.decoder_scratch.buffer.drain())
471 } else {
472 state.decoder_scratch.buffer.drain_to_window_size()
473 }
474 }
475
476 pub fn collect_to_writer(&mut self, w: impl Write) -> Result<usize, Error> {
479 let finished = self.is_finished();
480 let state = match &mut self.state {
481 None => return Ok(0),
482 Some(s) => s,
483 };
484 if finished {
485 state.decoder_scratch.buffer.drain_to_writer(w)
486 } else {
487 state.decoder_scratch.buffer.drain_to_window_size_writer(w)
488 }
489 }
490
491 pub fn can_collect(&self) -> usize {
495 let finished = self.is_finished();
496 let state = match &self.state {
497 None => return 0,
498 Some(s) => s,
499 };
500 if finished {
501 state.decoder_scratch.buffer.can_drain()
502 } else {
503 state
504 .decoder_scratch
505 .buffer
506 .can_drain_to_window_size()
507 .unwrap_or(0)
508 }
509 }
510
511 pub fn decode_from_to(
525 &mut self,
526 source: &[u8],
527 target: &mut [u8],
528 ) -> Result<(usize, usize), FrameDecoderError> {
529 use FrameDecoderError as err;
530 let bytes_read_at_start = match &self.state {
531 Some(s) => s.bytes_read_counter,
532 None => 0,
533 };
534
535 if !self.is_finished() || self.state.is_none() {
536 let mut mt_source = source;
537
538 if self.state.is_none() {
539 self.init(&mut mt_source)?;
540 }
541
542 {
544 let state = match &mut self.state {
545 Some(s) => s,
546 None => panic!("Bug in library"),
547 };
548 let mut block_dec = decoding::block_decoder::new();
549
550 if state.frame.header.descriptor.content_checksum_flag()
551 && state.frame_finished
552 && state.check_sum.is_none()
553 {
554 if mt_source.len() >= 4 {
556 let chksum = mt_source[..4].try_into().expect("optimized away");
557 state.bytes_read_counter += 4;
558 let chksum = u32::from_le_bytes(chksum);
559 state.check_sum = Some(chksum);
560 }
561 return Ok((4, 0));
562 }
563
564 loop {
565 if mt_source.len() < 3 {
567 break;
568 }
569 let (block_header, block_header_size) = block_dec
570 .read_block_header(&mut mt_source)
571 .map_err(err::FailedToReadBlockHeader)?;
572
573 if mt_source.len() < block_header.content_size as usize {
576 break;
577 }
578 state.bytes_read_counter += u64::from(block_header_size);
579
580 let bytes_read_in_block_body = block_dec
581 .decode_block_content(
582 &block_header,
583 &mut state.decoder_scratch,
584 &mut mt_source,
585 )
586 .map_err(err::FailedToReadBlockBody)?;
587 state.bytes_read_counter += bytes_read_in_block_body;
588 state.block_counter += 1;
589
590 if block_header.last_block {
591 state.frame_finished = true;
592 if state.frame.header.descriptor.content_checksum_flag() {
593 if mt_source.len() >= 4 {
595 let chksum = mt_source[..4].try_into().expect("optimized away");
596 state.bytes_read_counter += 4;
597 let chksum = u32::from_le_bytes(chksum);
598 state.check_sum = Some(chksum);
599 }
600 }
601 break;
602 }
603 }
604 }
605 }
606
607 let result_len = self.read(target).map_err(err::FailedToDrainDecodebuffer)?;
608 let bytes_read_at_end = match &mut self.state {
609 Some(s) => s.bytes_read_counter,
610 None => panic!("Bug in library"),
611 };
612 let read_len = bytes_read_at_end - bytes_read_at_start;
613 Ok((read_len as usize, result_len))
614 }
615
616 pub fn decode_all(
627 &mut self,
628 mut input: &[u8],
629 mut output: &mut [u8],
630 ) -> Result<usize, FrameDecoderError> {
631 let mut total_bytes_written = 0;
632 while !input.is_empty() {
633 match self.init(&mut input) {
634 Ok(_) => {}
635 Err(FrameDecoderError::ReadFrameHeaderError(
636 frame::ReadFrameHeaderError::SkipFrame { length, .. },
637 )) => {
638 input = input
639 .get(length as usize..)
640 .ok_or(FrameDecoderError::FailedToSkipFrame)?;
641 continue;
642 }
643 Err(e) => return Err(e),
644 };
645 loop {
646 self.decode_blocks(&mut input, BlockDecodingStrategy::UptoBlocks(1))?;
647 let bytes_written = self
648 .read(output)
649 .map_err(FrameDecoderError::FailedToDrainDecodebuffer)?;
650 output = &mut output[bytes_written..];
651 total_bytes_written += bytes_written;
652 if self.can_collect() != 0 {
653 return Err(FrameDecoderError::TargetTooSmall);
654 }
655 if self.is_finished() {
656 break;
657 }
658 }
659 }
660
661 Ok(total_bytes_written)
662 }
663
664 pub fn decode_all_to_vec(
677 &mut self,
678 input: &[u8],
679 output: &mut Vec<u8>,
680 ) -> Result<(), FrameDecoderError> {
681 let len = output.len();
682 let cap = output.capacity();
683 output.resize(cap, 0);
684 match self.decode_all(input, &mut output[len..]) {
685 Ok(bytes_written) => {
686 let new_len = core::cmp::min(len + bytes_written, cap); output.resize(new_len, 0);
688 Ok(())
689 }
690 Err(e) => {
691 output.resize(len, 0);
692 Err(e)
693 }
694 }
695 }
696}
697
698impl Read for FrameDecoder {
701 fn read(&mut self, target: &mut [u8]) -> Result<usize, Error> {
702 let state = match &mut self.state {
703 None => return Ok(0),
704 Some(s) => s,
705 };
706 if state.frame_finished {
707 state.decoder_scratch.buffer.read_all(target)
708 } else {
709 state.decoder_scratch.buffer.read(target)
710 }
711 }
712}