1use super::frame;
8use crate::decoding;
9use crate::decoding::block_decoder::BlockDecoder;
10use crate::decoding::decode_buffer::DecodeBuffer;
11use crate::decoding::dictionary::{Dictionary, DictionaryHandle};
12use crate::decoding::errors::{DecodeBlockContentError, FrameDecoderError};
13use crate::decoding::flat_buf::FlatBuf;
14use crate::decoding::ringbuffer::RingBuffer;
15use crate::decoding::scratch::DecoderScratch;
16use crate::io::{Error, Read, Write};
17use alloc::collections::BTreeMap;
18use alloc::vec::Vec;
19use core::convert::TryInto;
20
21use crate::common::MAXIMUM_ALLOWED_WINDOW_SIZE;
22
23pub struct FrameDecoder {
77 state: Option<FrameDecoderState>,
78 owned_dicts: BTreeMap<u32, Dictionary>,
79 #[cfg(target_has_atomic = "ptr")]
80 shared_dicts: BTreeMap<u32, DictionaryHandle>,
81 #[cfg(not(target_has_atomic = "ptr"))]
82 shared_dicts: (),
83}
84
85enum DecoderScratchKind {
93 Ring(DecoderScratch<RingBuffer>),
94 Flat(DecoderScratch<FlatBuf>),
95}
96
97impl DecoderScratchKind {
98 fn new_ring(window_size: usize) -> Self {
99 let mut s = DecoderScratch::<RingBuffer>::new(window_size);
100 s.buffer.reserve(window_size);
101 Self::Ring(s)
102 }
103
104 fn new_flat(frame_content_size: usize) -> Self {
108 let flat = FlatBuf::with_capacity(frame_content_size);
109 let mut s = DecoderScratch::<FlatBuf>::new(frame_content_size);
113 s.buffer = DecodeBuffer::from_backend(flat, frame_content_size);
114 Self::Flat(s)
115 }
116
117 fn reset(&mut self, frame: &frame::FrameHeader, window_size: usize) {
125 if frame.descriptor.single_segment_flag() {
126 match self {
127 Self::Flat(s) => {
128 s.reset(window_size);
129 }
135 Self::Ring(_) => *self = Self::new_flat(window_size),
136 }
137 } else {
138 match self {
139 Self::Ring(s) => s.reset(window_size),
140 Self::Flat(_) => *self = Self::new_ring(window_size),
141 }
142 }
143 }
144
145 fn init_from_dict(&mut self, dict: &Dictionary) {
146 match self {
147 Self::Ring(s) => s.init_from_dict(dict),
148 Self::Flat(s) => s.init_from_dict(dict),
149 }
150 }
151
152 #[inline]
153 fn buffer_len(&self) -> usize {
154 match self {
155 Self::Ring(s) => s.buffer.len(),
156 Self::Flat(s) => s.buffer.len(),
157 }
158 }
159
160 fn buffer_drain(&mut self) -> Vec<u8> {
161 match self {
162 Self::Ring(s) => s.buffer.drain(),
163 Self::Flat(s) => s.buffer.drain(),
164 }
165 }
166
167 fn buffer_drain_to_window_size(&mut self) -> Option<Vec<u8>> {
168 match self {
169 Self::Ring(s) => s.buffer.drain_to_window_size(),
170 Self::Flat(s) => s.buffer.drain_to_window_size(),
171 }
172 }
173
174 fn buffer_drain_to_writer(&mut self, sink: impl Write) -> Result<usize, Error> {
175 match self {
176 Self::Ring(s) => s.buffer.drain_to_writer(sink),
177 Self::Flat(s) => s.buffer.drain_to_writer(sink),
178 }
179 }
180
181 fn buffer_drain_to_window_size_writer(&mut self, sink: impl Write) -> Result<usize, Error> {
182 match self {
183 Self::Ring(s) => s.buffer.drain_to_window_size_writer(sink),
184 Self::Flat(s) => s.buffer.drain_to_window_size_writer(sink),
185 }
186 }
187
188 fn buffer_can_drain(&self) -> usize {
189 match self {
190 Self::Ring(s) => s.buffer.can_drain(),
191 Self::Flat(s) => s.buffer.can_drain(),
192 }
193 }
194
195 fn buffer_can_drain_to_window_size(&self) -> Option<usize> {
196 match self {
197 Self::Ring(s) => s.buffer.can_drain_to_window_size(),
198 Self::Flat(s) => s.buffer.can_drain_to_window_size(),
199 }
200 }
201
202 fn buffer_read(&mut self, target: &mut [u8]) -> Result<usize, Error> {
203 match self {
204 Self::Ring(s) => s.buffer.read(target),
205 Self::Flat(s) => s.buffer.read(target),
206 }
207 }
208
209 fn buffer_read_all(&mut self, target: &mut [u8]) -> Result<usize, Error> {
210 match self {
211 Self::Ring(s) => s.buffer.read_all(target),
212 Self::Flat(s) => s.buffer.read_all(target),
213 }
214 }
215
216 fn decode_block_content<R: Read>(
217 &mut self,
218 decoder: &mut BlockDecoder,
219 header: &crate::blocks::block::BlockHeader,
220 source: R,
221 ) -> Result<u64, DecodeBlockContentError> {
222 match self {
223 Self::Ring(s) => decoder.decode_block_content(header, s, source),
224 Self::Flat(s) => decoder.decode_block_content(header, s, source),
225 }
226 }
227
228 #[cfg(feature = "hash")]
229 fn hash_finish(&self) -> u64 {
230 use core::hash::Hasher;
231 match self {
232 Self::Ring(s) => s.buffer.hash.finish(),
233 Self::Flat(s) => s.buffer.hash.finish(),
234 }
235 }
236}
237
238struct FrameDecoderState {
239 pub frame_header: frame::FrameHeader,
240 decoder_scratch: DecoderScratchKind,
241 frame_finished: bool,
242 block_counter: usize,
243 bytes_read_counter: u64,
244 check_sum: Option<u32>,
245 using_dict: Option<u32>,
246}
247
248pub enum BlockDecodingStrategy {
249 All,
250 UptoBlocks(usize),
251 UptoBytes(usize),
252}
253
254impl FrameDecoderState {
255 pub fn new(source: impl Read) -> Result<FrameDecoderState, FrameDecoderError> {
260 let (frame, header_size) = frame::read_frame_header(source)?;
261 let window_size = frame.window_size()?;
262
263 if window_size > MAXIMUM_ALLOWED_WINDOW_SIZE {
264 return Err(FrameDecoderError::WindowSizeTooBig {
265 requested: window_size,
266 });
267 }
268
269 let decoder_scratch = if frame.descriptor.single_segment_flag() {
270 DecoderScratchKind::new_flat(window_size as usize)
271 } else {
272 DecoderScratchKind::new_ring(window_size as usize)
273 };
274 Ok(FrameDecoderState {
275 frame_header: frame,
276 frame_finished: false,
277 block_counter: 0,
278 decoder_scratch,
279 bytes_read_counter: u64::from(header_size),
280 check_sum: None,
281 using_dict: None,
282 })
283 }
284
285 pub fn reset(&mut self, source: impl Read) -> Result<(), FrameDecoderError> {
291 let (frame_header, header_size) = frame::read_frame_header(source)?;
292 let window_size = frame_header.window_size()?;
293
294 if window_size > MAXIMUM_ALLOWED_WINDOW_SIZE {
295 return Err(FrameDecoderError::WindowSizeTooBig {
296 requested: window_size,
297 });
298 }
299
300 self.decoder_scratch
301 .reset(&frame_header, window_size as usize);
302 self.frame_header = frame_header;
303 self.frame_finished = false;
304 self.block_counter = 0;
305 self.bytes_read_counter = u64::from(header_size);
306 self.check_sum = None;
307 self.using_dict = None;
308 Ok(())
309 }
310}
311
312impl Default for FrameDecoder {
313 fn default() -> Self {
314 Self::new()
315 }
316}
317
318impl FrameDecoder {
319 pub fn new() -> FrameDecoder {
323 FrameDecoder {
324 state: None,
325 owned_dicts: BTreeMap::new(),
326 #[cfg(target_has_atomic = "ptr")]
327 shared_dicts: BTreeMap::new(),
328 #[cfg(not(target_has_atomic = "ptr"))]
329 shared_dicts: (),
330 }
331 }
332
333 #[cfg(target_has_atomic = "ptr")]
334 fn shared_dict_exists(&self, dict_id: u32) -> bool {
335 self.shared_dicts.contains_key(&dict_id)
336 }
337
338 #[cfg(not(target_has_atomic = "ptr"))]
339 fn shared_dict_exists(&self, _dict_id: u32) -> bool {
340 false
341 }
342
343 fn validate_registered_dictionary(dict: &Dictionary) -> Result<(), FrameDecoderError> {
344 use crate::decoding::errors::DictionaryDecodeError as dict_err;
345
346 if dict.id == 0 {
347 return Err(FrameDecoderError::from(dict_err::ZeroDictionaryId));
348 }
349 if let Some(index) = dict.offset_hist.iter().position(|&rep| rep == 0) {
350 return Err(FrameDecoderError::from(
351 dict_err::ZeroRepeatOffsetInDictionary { index: index as u8 },
352 ));
353 }
354 Ok(())
355 }
356
357 pub fn init(&mut self, source: impl Read) -> Result<(), FrameDecoderError> {
364 self.reset(source)
365 }
366
367 pub fn init_with_dict_handle(
386 &mut self,
387 source: impl Read,
388 dict: &DictionaryHandle,
389 ) -> Result<(), FrameDecoderError> {
390 self.reset_with_dict_handle(source, dict)
391 }
392
393 pub fn reset(&mut self, source: impl Read) -> Result<(), FrameDecoderError> {
400 use FrameDecoderError as err;
401 let dict_id = match &mut self.state {
402 Some(s) => {
403 s.reset(source)?;
404 s.frame_header.dictionary_id()
405 }
406 None => {
407 self.state = Some(FrameDecoderState::new(source)?);
408 self.state
409 .as_ref()
410 .and_then(|state| state.frame_header.dictionary_id())
411 }
412 };
413 if let Some(dict_id) = dict_id {
414 let state = self.state.as_mut().expect("state initialized");
415 let owned_dicts = &self.owned_dicts;
416 #[cfg(target_has_atomic = "ptr")]
417 let shared_dicts = &self.shared_dicts;
418 let dict = owned_dicts
419 .get(&dict_id)
420 .or_else(|| {
421 #[cfg(target_has_atomic = "ptr")]
422 {
423 shared_dicts.get(&dict_id).map(DictionaryHandle::as_dict)
424 }
425 #[cfg(not(target_has_atomic = "ptr"))]
426 {
427 None
428 }
429 })
430 .ok_or(err::DictNotProvided { dict_id })?;
431 state.decoder_scratch.init_from_dict(dict);
432 state.using_dict = Some(dict_id);
433 }
434 Ok(())
435 }
436
437 pub fn reset_with_dict_handle(
456 &mut self,
457 source: impl Read,
458 dict: &DictionaryHandle,
459 ) -> Result<(), FrameDecoderError> {
460 use FrameDecoderError as err;
461 Self::validate_registered_dictionary(dict.as_dict())?;
462 let state = match &mut self.state {
463 Some(s) => {
464 s.reset(source)?;
465 s
466 }
467 None => {
468 self.state = Some(FrameDecoderState::new(source)?);
469 self.state.as_mut().unwrap()
470 }
471 };
472 if let Some(dict_id) = state.frame_header.dictionary_id()
473 && dict_id != dict.id()
474 {
475 return Err(err::DictIdMismatch {
476 expected: dict_id,
477 provided: dict.id(),
478 });
479 }
480 state.decoder_scratch.init_from_dict(dict.as_dict());
481 state.using_dict = Some(dict.id());
482 Ok(())
483 }
484
485 pub fn add_dict(&mut self, dict: Dictionary) -> Result<(), FrameDecoderError> {
490 Self::validate_registered_dictionary(&dict)?;
491 let dict_id = dict.id;
492 if self.owned_dicts.contains_key(&dict_id) || self.shared_dict_exists(dict_id) {
493 return Err(FrameDecoderError::DictAlreadyRegistered { dict_id });
494 }
495 self.owned_dicts.insert(dict_id, dict);
496 Ok(())
497 }
498
499 pub fn add_dict_from_bytes(&mut self, raw_dictionary: &[u8]) -> Result<(), FrameDecoderError> {
501 let dict = Dictionary::decode_dict(raw_dictionary)?;
502 self.add_dict(dict)
503 }
504
505 #[cfg(target_has_atomic = "ptr")]
513 pub fn add_dict_handle(&mut self, dict: DictionaryHandle) -> Result<(), FrameDecoderError> {
514 Self::validate_registered_dictionary(dict.as_dict())?;
515 let dict_id = dict.id();
516 if self.owned_dicts.contains_key(&dict_id) || self.shared_dicts.contains_key(&dict_id) {
517 return Err(FrameDecoderError::DictAlreadyRegistered { dict_id });
518 }
519 self.shared_dicts.insert(dict_id, dict);
520 Ok(())
521 }
522
523 pub fn force_dict(&mut self, dict_id: u32) -> Result<(), FrameDecoderError> {
524 use FrameDecoderError as err;
525 let state = self.state.as_mut().ok_or(err::NotYetInitialized)?;
526 let owned_dicts = &self.owned_dicts;
527 #[cfg(target_has_atomic = "ptr")]
528 let shared_dicts = &self.shared_dicts;
529
530 let dict = owned_dicts
531 .get(&dict_id)
532 .or_else(|| {
533 #[cfg(target_has_atomic = "ptr")]
534 {
535 shared_dicts.get(&dict_id).map(DictionaryHandle::as_dict)
536 }
537 #[cfg(not(target_has_atomic = "ptr"))]
538 {
539 None
540 }
541 })
542 .ok_or(err::DictNotProvided { dict_id })?;
543 state.decoder_scratch.init_from_dict(dict);
544 state.using_dict = Some(dict_id);
545
546 Ok(())
547 }
548
549 pub fn content_size(&self) -> u64 {
551 match &self.state {
552 None => 0,
553 Some(s) => s.frame_header.frame_content_size(),
554 }
555 }
556
557 pub fn get_checksum_from_data(&self) -> Option<u32> {
559 let state = self.state.as_ref()?;
560
561 state.check_sum
562 }
563
564 #[cfg(feature = "hash")]
567 pub fn get_calculated_checksum(&self) -> Option<u32> {
568 let state = self.state.as_ref()?;
569 let cksum_64bit = state.decoder_scratch.hash_finish();
570 Some(cksum_64bit as u32)
572 }
573
574 pub fn bytes_read_from_source(&self) -> u64 {
576 let state = match &self.state {
577 None => return 0,
578 Some(s) => s,
579 };
580 state.bytes_read_counter
581 }
582
583 pub fn is_finished(&self) -> bool {
587 let state = match &self.state {
588 None => return true,
589 Some(s) => s,
590 };
591 if state.frame_header.descriptor.content_checksum_flag() {
592 state.frame_finished && state.check_sum.is_some()
593 } else {
594 state.frame_finished
595 }
596 }
597
598 pub fn blocks_decoded(&self) -> usize {
600 let state = match &self.state {
601 None => return 0,
602 Some(s) => s,
603 };
604 state.block_counter
605 }
606
607 pub fn decode_blocks(
612 &mut self,
613 mut source: impl Read,
614 strat: BlockDecodingStrategy,
615 ) -> Result<bool, FrameDecoderError> {
616 use FrameDecoderError as err;
617 let state = self.state.as_mut().ok_or(err::NotYetInitialized)?;
618
619 let mut block_dec = decoding::block_decoder::new();
620
621 let buffer_size_before = state.decoder_scratch.buffer_len();
622 let block_counter_before = state.block_counter;
623 loop {
624 vprintln!("################");
625 vprintln!("Next Block: {}", state.block_counter);
626 vprintln!("################");
627 let (block_header, block_header_size) = block_dec
628 .read_block_header(&mut source)
629 .map_err(err::FailedToReadBlockHeader)?;
630 state.bytes_read_counter += u64::from(block_header_size);
631
632 vprintln!();
633 vprintln!(
634 "Found {} block with size: {}, which will be of size: {}",
635 block_header.block_type,
636 block_header.content_size,
637 block_header.decompressed_size
638 );
639
640 let bytes_read_in_block_body = state
641 .decoder_scratch
642 .decode_block_content(&mut block_dec, &block_header, &mut source)
643 .map_err(err::FailedToReadBlockBody)?;
644 state.bytes_read_counter += bytes_read_in_block_body;
645
646 state.block_counter += 1;
647
648 vprintln!("Output: {}", state.decoder_scratch.buffer_len());
649
650 if block_header.last_block {
651 state.frame_finished = true;
652 if state.frame_header.descriptor.content_checksum_flag() {
653 let mut chksum = [0u8; 4];
654 source
655 .read_exact(&mut chksum)
656 .map_err(err::FailedToReadChecksum)?;
657 state.bytes_read_counter += 4;
658 let chksum = u32::from_le_bytes(chksum);
659 state.check_sum = Some(chksum);
660 }
661 break;
662 }
663
664 match strat {
665 BlockDecodingStrategy::All => { }
666 BlockDecodingStrategy::UptoBlocks(n) => {
667 if state.block_counter - block_counter_before >= n {
668 break;
669 }
670 }
671 BlockDecodingStrategy::UptoBytes(n) => {
672 if state.decoder_scratch.buffer_len() - buffer_size_before >= n {
673 break;
674 }
675 }
676 }
677 }
678
679 Ok(state.frame_finished)
680 }
681
682 pub fn collect(&mut self) -> Option<Vec<u8>> {
685 let finished = self.is_finished();
686 let state = self.state.as_mut()?;
687 if finished {
688 Some(state.decoder_scratch.buffer_drain())
689 } else {
690 state.decoder_scratch.buffer_drain_to_window_size()
691 }
692 }
693
694 pub fn collect_to_writer(&mut self, w: impl Write) -> Result<usize, Error> {
697 let finished = self.is_finished();
698 let state = match &mut self.state {
699 None => return Ok(0),
700 Some(s) => s,
701 };
702 if finished {
703 state.decoder_scratch.buffer_drain_to_writer(w)
704 } else {
705 state.decoder_scratch.buffer_drain_to_window_size_writer(w)
706 }
707 }
708
709 pub fn can_collect(&self) -> usize {
713 let finished = self.is_finished();
714 let state = match &self.state {
715 None => return 0,
716 Some(s) => s,
717 };
718 if finished {
719 state.decoder_scratch.buffer_can_drain()
720 } else {
721 state
722 .decoder_scratch
723 .buffer_can_drain_to_window_size()
724 .unwrap_or(0)
725 }
726 }
727
728 pub fn decode_from_to(
742 &mut self,
743 source: &[u8],
744 target: &mut [u8],
745 ) -> Result<(usize, usize), FrameDecoderError> {
746 use FrameDecoderError as err;
747 let bytes_read_at_start = match &self.state {
748 Some(s) => s.bytes_read_counter,
749 None => 0,
750 };
751
752 if !self.is_finished() || self.state.is_none() {
753 let mut mt_source = source;
754
755 if self.state.is_none() {
756 self.init(&mut mt_source)?;
757 }
758
759 {
761 let state = match &mut self.state {
762 Some(s) => s,
763 None => panic!("Bug in library"),
764 };
765 let mut block_dec = decoding::block_decoder::new();
766
767 if state.frame_header.descriptor.content_checksum_flag()
768 && state.frame_finished
769 && state.check_sum.is_none()
770 {
771 if mt_source.len() >= 4 {
773 let chksum = mt_source[..4].try_into().expect("optimized away");
774 state.bytes_read_counter += 4;
775 let chksum = u32::from_le_bytes(chksum);
776 state.check_sum = Some(chksum);
777 }
778 return Ok((4, 0));
779 }
780
781 loop {
782 if mt_source.len() < 3 {
784 break;
785 }
786 let (block_header, block_header_size) = block_dec
787 .read_block_header(&mut mt_source)
788 .map_err(err::FailedToReadBlockHeader)?;
789
790 if mt_source.len() < block_header.content_size as usize {
793 break;
794 }
795 state.bytes_read_counter += u64::from(block_header_size);
796
797 let bytes_read_in_block_body = state
798 .decoder_scratch
799 .decode_block_content(&mut block_dec, &block_header, &mut mt_source)
800 .map_err(err::FailedToReadBlockBody)?;
801 state.bytes_read_counter += bytes_read_in_block_body;
802 state.block_counter += 1;
803
804 if block_header.last_block {
805 state.frame_finished = true;
806 if state.frame_header.descriptor.content_checksum_flag() {
807 if mt_source.len() >= 4 {
809 let chksum = mt_source[..4].try_into().expect("optimized away");
810 state.bytes_read_counter += 4;
811 let chksum = u32::from_le_bytes(chksum);
812 state.check_sum = Some(chksum);
813 }
814 }
815 break;
816 }
817 }
818 }
819 }
820
821 let result_len = self.read(target).map_err(err::FailedToDrainDecodebuffer)?;
822 let bytes_read_at_end = match &mut self.state {
823 Some(s) => s.bytes_read_counter,
824 None => panic!("Bug in library"),
825 };
826 let read_len = bytes_read_at_end - bytes_read_at_start;
827 Ok((read_len as usize, result_len))
828 }
829
830 pub fn decode_all(
842 &mut self,
843 input: &[u8],
844 output: &mut [u8],
845 ) -> Result<usize, FrameDecoderError> {
846 self.decode_all_impl(input, output, |this, src| this.init(src))
847 }
848
849 pub fn decode_all_with_dict_handle(
867 &mut self,
868 input: &[u8],
869 output: &mut [u8],
870 dict: &DictionaryHandle,
871 ) -> Result<usize, FrameDecoderError> {
872 self.decode_all_impl(input, output, |this, src| {
873 this.init_with_dict_handle(src, dict)
874 })
875 }
876
877 fn decode_all_impl(
878 &mut self,
879 mut input: &[u8],
880 mut output: &mut [u8],
881 mut init_frame: impl FnMut(&mut Self, &mut &[u8]) -> Result<(), FrameDecoderError>,
882 ) -> Result<usize, FrameDecoderError> {
883 let mut total_bytes_written = 0;
884 while !input.is_empty() {
885 match init_frame(self, &mut input) {
886 Ok(_) => {}
887 Err(FrameDecoderError::ReadFrameHeaderError(
888 crate::decoding::errors::ReadFrameHeaderError::SkipFrame { length, .. },
889 )) => {
890 input = input
891 .get(length as usize..)
892 .ok_or(FrameDecoderError::FailedToSkipFrame)?;
893 continue;
894 }
895 Err(e) => return Err(e),
896 };
897 loop {
898 self.decode_blocks(&mut input, BlockDecodingStrategy::UptoBytes(1024 * 1024))?;
899 let bytes_written = self
900 .read(output)
901 .map_err(FrameDecoderError::FailedToDrainDecodebuffer)?;
902 output = &mut output[bytes_written..];
903 total_bytes_written += bytes_written;
904 if self.can_collect() != 0 {
905 return Err(FrameDecoderError::TargetTooSmall);
906 }
907 if self.is_finished() {
908 break;
909 }
910 }
911 }
912
913 Ok(total_bytes_written)
914 }
915
916 pub fn decode_all_with_dict_bytes(
925 &mut self,
926 input: &[u8],
927 output: &mut [u8],
928 raw_dictionary: &[u8],
929 ) -> Result<usize, FrameDecoderError> {
930 let dict = DictionaryHandle::decode_dict(raw_dictionary)?;
931 self.decode_all_with_dict_handle(input, output, &dict)
932 }
933
934 pub fn decode_all_to_vec(
947 &mut self,
948 input: &[u8],
949 output: &mut Vec<u8>,
950 ) -> Result<(), FrameDecoderError> {
951 let len = output.len();
952 let cap = output.capacity();
953 output.resize(cap, 0);
954 match self.decode_all(input, &mut output[len..]) {
955 Ok(bytes_written) => {
956 let new_len = core::cmp::min(len + bytes_written, cap); output.resize(new_len, 0);
958 Ok(())
959 }
960 Err(e) => {
961 output.resize(len, 0);
962 Err(e)
963 }
964 }
965 }
966}
967
968impl Read for FrameDecoder {
971 fn read(&mut self, target: &mut [u8]) -> Result<usize, Error> {
972 let state = match &mut self.state {
973 None => return Ok(0),
974 Some(s) => s,
975 };
976 if state.frame_finished {
977 state.decoder_scratch.buffer_read_all(target)
978 } else {
979 state.decoder_scratch.buffer_read(target)
980 }
981 }
982}
983
984#[cfg(test)]
985mod tests {
986 extern crate std;
987
988 use super::{DictionaryHandle, FrameDecoder};
989 use crate::encoding::{CompressionLevel, FrameCompressor};
990 use alloc::vec::Vec;
991
992 #[test]
993 fn reset_with_dict_handle_applies_dict_when_no_dict_id() {
994 let payload = b"reset-without-dict-id";
995 let mut compressor = FrameCompressor::new(CompressionLevel::Default);
996 compressor.set_source(payload.as_slice());
997 let mut compressed = Vec::new();
998 compressor.set_drain(&mut compressed);
999 compressor.compress();
1000
1001 let dict_raw = include_bytes!("../../dict_tests/dictionary");
1002 let handle = DictionaryHandle::decode_dict(dict_raw).expect("dictionary should parse");
1003
1004 let mut decoder = FrameDecoder::new();
1005 decoder
1006 .reset_with_dict_handle(compressed.as_slice(), &handle)
1007 .expect("reset should succeed");
1008 let state = decoder.state.as_ref().expect("state should be initialized");
1009 assert!(state.frame_header.dictionary_id().is_none());
1010 assert_eq!(state.using_dict, Some(handle.id()));
1011 }
1012}