1 | use super::super::decoding::bit_reader::{BitReader, GetBitsError}; |
2 | |
3 | pub struct LiteralsSection { |
4 | pub regenerated_size: u32, |
5 | pub compressed_size: Option<u32>, |
6 | pub num_streams: Option<u8>, |
7 | pub ls_type: LiteralsSectionType, |
8 | } |
9 | |
10 | pub enum LiteralsSectionType { |
11 | Raw, |
12 | RLE, |
13 | Compressed, |
14 | Treeless, |
15 | } |
16 | |
17 | #[derive (Debug, derive_more::Display, derive_more::From)] |
18 | #[cfg_attr (feature = "std" , derive(derive_more::Error))] |
19 | #[non_exhaustive ] |
20 | pub enum LiteralsSectionParseError { |
21 | #[display(fmt = "Illegal literalssectiontype. Is: {got}, must be in: 0, 1, 2, 3" )] |
22 | IllegalLiteralSectionType { got: u8 }, |
23 | #[display(fmt = "{_0:?}" )] |
24 | #[from] |
25 | GetBitsError(GetBitsError), |
26 | #[display( |
27 | fmt = "Not enough byte to parse the literals section header. Have: {have}, Need: {need}" |
28 | )] |
29 | NotEnoughBytes { have: usize, need: u8 }, |
30 | } |
31 | |
32 | impl core::fmt::Display for LiteralsSectionType { |
33 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { |
34 | match self { |
35 | LiteralsSectionType::Compressed => write!(f, "Compressed" ), |
36 | LiteralsSectionType::Raw => write!(f, "Raw" ), |
37 | LiteralsSectionType::RLE => write!(f, "RLE" ), |
38 | LiteralsSectionType::Treeless => write!(f, "Treeless" ), |
39 | } |
40 | } |
41 | } |
42 | |
43 | impl Default for LiteralsSection { |
44 | fn default() -> Self { |
45 | Self::new() |
46 | } |
47 | } |
48 | |
49 | impl LiteralsSection { |
50 | pub fn new() -> LiteralsSection { |
51 | LiteralsSection { |
52 | regenerated_size: 0, |
53 | compressed_size: None, |
54 | num_streams: None, |
55 | ls_type: LiteralsSectionType::Raw, |
56 | } |
57 | } |
58 | |
59 | pub fn header_bytes_needed(&self, first_byte: u8) -> Result<u8, LiteralsSectionParseError> { |
60 | let ls_type = Self::section_type(first_byte)?; |
61 | let size_format = (first_byte >> 2) & 0x3; |
62 | match ls_type { |
63 | LiteralsSectionType::RLE | LiteralsSectionType::Raw => { |
64 | match size_format { |
65 | 0 | 2 => { |
66 | //size_format actually only uses one bit |
67 | //regenerated_size uses 5 bits |
68 | Ok(1) |
69 | } |
70 | 1 => { |
71 | //size_format uses 2 bit |
72 | //regenerated_size uses 12 bits |
73 | Ok(2) |
74 | } |
75 | 3 => { |
76 | //size_format uses 2 bit |
77 | //regenerated_size uses 20 bits |
78 | Ok(3) |
79 | } |
80 | _ => panic!( |
81 | "This is a bug in the program. There should only be values between 0..3" |
82 | ), |
83 | } |
84 | } |
85 | LiteralsSectionType::Compressed | LiteralsSectionType::Treeless => { |
86 | match size_format { |
87 | 0 | 1 => { |
88 | //Only differ in num_streams |
89 | //both regenerated and compressed sizes use 10 bit |
90 | Ok(3) |
91 | } |
92 | 2 => { |
93 | //both regenerated and compressed sizes use 14 bit |
94 | Ok(4) |
95 | } |
96 | 3 => { |
97 | //both regenerated and compressed sizes use 18 bit |
98 | Ok(5) |
99 | } |
100 | |
101 | _ => panic!( |
102 | "This is a bug in the program. There should only be values between 0..3" |
103 | ), |
104 | } |
105 | } |
106 | } |
107 | } |
108 | |
109 | pub fn parse_from_header(&mut self, raw: &[u8]) -> Result<u8, LiteralsSectionParseError> { |
110 | let mut br = BitReader::new(raw); |
111 | let t = br.get_bits(2)? as u8; |
112 | self.ls_type = Self::section_type(t)?; |
113 | let size_format = br.get_bits(2)? as u8; |
114 | |
115 | let byte_needed = self.header_bytes_needed(raw[0])?; |
116 | if raw.len() < byte_needed as usize { |
117 | return Err(LiteralsSectionParseError::NotEnoughBytes { |
118 | have: raw.len(), |
119 | need: byte_needed, |
120 | }); |
121 | } |
122 | |
123 | match self.ls_type { |
124 | LiteralsSectionType::RLE | LiteralsSectionType::Raw => { |
125 | self.compressed_size = None; |
126 | match size_format { |
127 | 0 | 2 => { |
128 | //size_format actually only uses one bit |
129 | //regenerated_size uses 5 bits |
130 | self.regenerated_size = u32::from(raw[0]) >> 3; |
131 | Ok(1) |
132 | } |
133 | 1 => { |
134 | //size_format uses 2 bit |
135 | //regenerated_size uses 12 bits |
136 | self.regenerated_size = (u32::from(raw[0]) >> 4) + (u32::from(raw[1]) << 4); |
137 | Ok(2) |
138 | } |
139 | 3 => { |
140 | //size_format uses 2 bit |
141 | //regenerated_size uses 20 bits |
142 | self.regenerated_size = (u32::from(raw[0]) >> 4) |
143 | + (u32::from(raw[1]) << 4) |
144 | + (u32::from(raw[2]) << 12); |
145 | Ok(3) |
146 | } |
147 | _ => panic!( |
148 | "This is a bug in the program. There should only be values between 0..3" |
149 | ), |
150 | } |
151 | } |
152 | LiteralsSectionType::Compressed | LiteralsSectionType::Treeless => { |
153 | match size_format { |
154 | 0 => { |
155 | self.num_streams = Some(1); |
156 | } |
157 | 1..=3 => { |
158 | self.num_streams = Some(4); |
159 | } |
160 | _ => panic!( |
161 | "This is a bug in the program. There should only be values between 0..3" |
162 | ), |
163 | }; |
164 | |
165 | match size_format { |
166 | 0 | 1 => { |
167 | //Differ in num_streams see above |
168 | //both regenerated and compressed sizes use 10 bit |
169 | |
170 | //4 from the first, six from the second byte |
171 | self.regenerated_size = |
172 | (u32::from(raw[0]) >> 4) + ((u32::from(raw[1]) & 0x3f) << 4); |
173 | |
174 | // 2 from the second, full last byte |
175 | self.compressed_size = |
176 | Some(u32::from(raw[1] >> 6) + (u32::from(raw[2]) << 2)); |
177 | Ok(3) |
178 | } |
179 | 2 => { |
180 | //both regenerated and compressed sizes use 14 bit |
181 | |
182 | //4 from first, full second, 2 from the third byte |
183 | self.regenerated_size = (u32::from(raw[0]) >> 4) |
184 | + (u32::from(raw[1]) << 4) |
185 | + ((u32::from(raw[2]) & 0x3) << 12); |
186 | |
187 | //6 from the third, full last byte |
188 | self.compressed_size = |
189 | Some((u32::from(raw[2]) >> 2) + (u32::from(raw[3]) << 6)); |
190 | Ok(4) |
191 | } |
192 | 3 => { |
193 | //both regenerated and compressed sizes use 18 bit |
194 | |
195 | //4 from first, full second, six from third byte |
196 | self.regenerated_size = (u32::from(raw[0]) >> 4) |
197 | + (u32::from(raw[1]) << 4) |
198 | + ((u32::from(raw[2]) & 0x3F) << 12); |
199 | |
200 | //2 from third, full fourth, full fifth byte |
201 | self.compressed_size = Some( |
202 | (u32::from(raw[2]) >> 6) |
203 | + (u32::from(raw[3]) << 2) |
204 | + (u32::from(raw[4]) << 10), |
205 | ); |
206 | Ok(5) |
207 | } |
208 | |
209 | _ => panic!( |
210 | "This is a bug in the program. There should only be values between 0..3" |
211 | ), |
212 | } |
213 | } |
214 | } |
215 | } |
216 | |
217 | fn section_type(raw: u8) -> Result<LiteralsSectionType, LiteralsSectionParseError> { |
218 | let t = raw & 0x3; |
219 | match t { |
220 | 0 => Ok(LiteralsSectionType::Raw), |
221 | 1 => Ok(LiteralsSectionType::RLE), |
222 | 2 => Ok(LiteralsSectionType::Compressed), |
223 | 3 => Ok(LiteralsSectionType::Treeless), |
224 | other => Err(LiteralsSectionParseError::IllegalLiteralSectionType { got: other }), |
225 | } |
226 | } |
227 | } |
228 | |