ruzstd/decoding/
sequence_execution.rs1use super::scratch::DecoderScratch;
2use crate::decoding::errors::ExecuteSequencesError;
3
4pub fn execute_sequences(scratch: &mut DecoderScratch) -> Result<(), ExecuteSequencesError> {
6 let mut literals_copy_counter = 0;
7 let old_buffer_size = scratch.buffer.len();
8 let mut seq_sum = 0;
9
10 for idx in 0..scratch.sequences.len() {
11 let seq = scratch.sequences[idx];
12
13 if seq.ll > 0 {
14 let high = literals_copy_counter + seq.ll as usize;
15 if high > scratch.literals_buffer.len() {
16 return Err(ExecuteSequencesError::NotEnoughBytesForSequence {
17 wanted: high,
18 have: scratch.literals_buffer.len(),
19 });
20 }
21 let literals = &scratch.literals_buffer[literals_copy_counter..high];
22 literals_copy_counter += seq.ll as usize;
23
24 scratch.buffer.push(literals);
25 }
26
27 let actual_offset = do_offset_history(seq.of, seq.ll, &mut scratch.offset_hist);
28 if actual_offset == 0 {
29 return Err(ExecuteSequencesError::ZeroOffset);
30 }
31 if seq.ml > 0 {
32 scratch
33 .buffer
34 .repeat(actual_offset as usize, seq.ml as usize)?;
35 }
36
37 seq_sum += seq.ml;
38 seq_sum += seq.ll;
39 }
40 if literals_copy_counter < scratch.literals_buffer.len() {
41 let rest_literals = &scratch.literals_buffer[literals_copy_counter..];
42 scratch.buffer.push(rest_literals);
43 seq_sum += rest_literals.len() as u32;
44 }
45
46 let diff = scratch.buffer.len() - old_buffer_size;
47 assert!(
48 seq_sum as usize == diff,
49 "Seq_sum: {} is different from the difference in buffersize: {}",
50 seq_sum,
51 diff
52 );
53 Ok(())
54}
55
56fn do_offset_history(offset_value: u32, lit_len: u32, scratch: &mut [u32; 3]) -> u32 {
60 let actual_offset = if lit_len > 0 {
61 match offset_value {
62 1..=3 => scratch[offset_value as usize - 1],
63 _ => {
64 offset_value - 3
66 }
67 }
68 } else {
69 match offset_value {
70 1..=2 => scratch[offset_value as usize],
71 3 => scratch[0] - 1,
72 _ => {
73 offset_value - 3
75 }
76 }
77 };
78
79 if lit_len > 0 {
81 match offset_value {
82 1 => {
83 }
85 2 => {
86 scratch[1] = scratch[0];
87 scratch[0] = actual_offset;
88 }
89 _ => {
90 scratch[2] = scratch[1];
91 scratch[1] = scratch[0];
92 scratch[0] = actual_offset;
93 }
94 }
95 } else {
96 match offset_value {
97 1 => {
98 scratch[1] = scratch[0];
99 scratch[0] = actual_offset;
100 }
101 2 => {
102 scratch[2] = scratch[1];
103 scratch[1] = scratch[0];
104 scratch[0] = actual_offset;
105 }
106 _ => {
107 scratch[2] = scratch[1];
108 scratch[1] = scratch[0];
109 scratch[0] = actual_offset;
110 }
111 }
112 }
113
114 actual_offset
115}