1use super::*;
16#[cfg(feature = "mem_dbg")]
17use mem_dbg::{MemDbg, MemSize};
18
19#[derive(Debug, Clone, Copy, Eq)]
20#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
21#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
22#[non_exhaustive]
23pub enum Codes {
32 Unary,
33 Gamma,
34 Delta,
35 Omega,
36 VByteLe,
37 VByteBe,
38 Zeta { k: usize },
39 Pi { k: usize },
40 Golomb { b: usize },
41 ExpGolomb { k: usize },
42 Rice { log2_b: usize },
43}
44
45impl PartialEq for Codes {
48 fn eq(&self, other: &Self) -> bool {
49 match (self, other) {
50 (
52 Self::Unary | Self::Rice { log2_b: 0 } | Self::Golomb { b: 1 },
53 Self::Unary | Self::Rice { log2_b: 0 } | Self::Golomb { b: 1 },
54 ) => true,
55 (
56 Self::Gamma | Self::Zeta { k: 1 } | Self::ExpGolomb { k: 0 },
57 Self::Gamma | Self::Zeta { k: 1 } | Self::ExpGolomb { k: 0 },
58 ) => true,
59 (
60 Self::Golomb { b: 2 } | Self::Rice { log2_b: 1 },
61 Self::Golomb { b: 2 } | Self::Rice { log2_b: 1 },
62 ) => true,
63 (
64 Self::Golomb { b: 4 } | Self::Rice { log2_b: 2 },
65 Self::Golomb { b: 4 } | Self::Rice { log2_b: 2 },
66 ) => true,
67 (
68 Self::Golomb { b: 8 } | Self::Rice { log2_b: 3 },
69 Self::Golomb { b: 8 } | Self::Rice { log2_b: 3 },
70 ) => true,
71 (Self::Delta, Self::Delta) => true,
74 (Self::Omega, Self::Omega) => true,
75 (Self::VByteLe, Self::VByteLe) => true,
76 (Self::VByteBe, Self::VByteBe) => true,
77 (Self::Zeta { k }, Self::Zeta { k: k2 }) => k == k2,
78 (Self::Pi { k }, Self::Pi { k: k2 }) => k == k2,
79 (Self::Golomb { b }, Self::Golomb { b: b2 }) => b == b2,
80 (Self::ExpGolomb { k }, Self::ExpGolomb { k: k2 }) => k == k2,
81 (Self::Rice { log2_b }, Self::Rice { log2_b: log2_b2 }) => log2_b == log2_b2,
82 _ => false,
83 }
84 }
85}
86
87impl Codes {
88 #[inline(always)]
93 pub fn read<E: Endianness, CR: CodesRead<E> + ?Sized>(
94 &self,
95 reader: &mut CR,
96 ) -> Result<u64, CR::Error> {
97 DynamicCodeRead::read(self, reader)
98 }
99
100 #[inline(always)]
105 pub fn write<E: Endianness, CW: CodesWrite<E> + ?Sized>(
106 &self,
107 writer: &mut CW,
108 value: u64,
109 ) -> Result<usize, CW::Error> {
110 DynamicCodeWrite::write(self, writer, value)
111 }
112
113 pub fn to_code_const(&self) -> Result<usize> {
117 Ok(match self {
118 Self::Unary => code_consts::UNARY,
119 Self::Gamma => code_consts::GAMMA,
120 Self::Delta => code_consts::DELTA,
121 Self::Omega => code_consts::OMEGA,
122 Self::VByteLe => code_consts::VBYTE_LE,
123 Self::VByteBe => code_consts::VBYTE_BE,
124 Self::Zeta { k: 1 } => code_consts::ZETA1,
125 Self::Zeta { k: 2 } => code_consts::ZETA2,
126 Self::Zeta { k: 3 } => code_consts::ZETA3,
127 Self::Zeta { k: 4 } => code_consts::ZETA4,
128 Self::Zeta { k: 5 } => code_consts::ZETA5,
129 Self::Zeta { k: 6 } => code_consts::ZETA6,
130 Self::Zeta { k: 7 } => code_consts::ZETA7,
131 Self::Zeta { k: 8 } => code_consts::ZETA8,
132 Self::Zeta { k: 9 } => code_consts::ZETA9,
133 Self::Zeta { k: 10 } => code_consts::ZETA10,
134 Self::Rice { log2_b: 0 } => code_consts::RICE0,
135 Self::Rice { log2_b: 1 } => code_consts::RICE1,
136 Self::Rice { log2_b: 2 } => code_consts::RICE2,
137 Self::Rice { log2_b: 3 } => code_consts::RICE3,
138 Self::Rice { log2_b: 4 } => code_consts::RICE4,
139 Self::Rice { log2_b: 5 } => code_consts::RICE5,
140 Self::Rice { log2_b: 6 } => code_consts::RICE6,
141 Self::Rice { log2_b: 7 } => code_consts::RICE7,
142 Self::Rice { log2_b: 8 } => code_consts::RICE8,
143 Self::Rice { log2_b: 9 } => code_consts::RICE9,
144 Self::Rice { log2_b: 10 } => code_consts::RICE10,
145 Self::Pi { k: 0 } => code_consts::PI0,
146 Self::Pi { k: 1 } => code_consts::PI1,
147 Self::Pi { k: 2 } => code_consts::PI2,
148 Self::Pi { k: 3 } => code_consts::PI3,
149 Self::Pi { k: 4 } => code_consts::PI4,
150 Self::Pi { k: 5 } => code_consts::PI5,
151 Self::Pi { k: 6 } => code_consts::PI6,
152 Self::Pi { k: 7 } => code_consts::PI7,
153 Self::Pi { k: 8 } => code_consts::PI8,
154 Self::Pi { k: 9 } => code_consts::PI9,
155 Self::Pi { k: 10 } => code_consts::PI10,
156 Self::Golomb { b: 1 } => code_consts::GOLOMB1,
157 Self::Golomb { b: 2 } => code_consts::GOLOMB2,
158 Self::Golomb { b: 3 } => code_consts::GOLOMB3,
159 Self::Golomb { b: 4 } => code_consts::GOLOMB4,
160 Self::Golomb { b: 5 } => code_consts::GOLOMB5,
161 Self::Golomb { b: 6 } => code_consts::GOLOMB6,
162 Self::Golomb { b: 7 } => code_consts::GOLOMB7,
163 Self::Golomb { b: 8 } => code_consts::GOLOMB8,
164 Self::Golomb { b: 9 } => code_consts::GOLOMB9,
165 Self::Golomb { b: 10 } => code_consts::GOLOMB10,
166 Self::ExpGolomb { k: 0 } => code_consts::EXP_GOLOMB0,
167 Self::ExpGolomb { k: 1 } => code_consts::EXP_GOLOMB1,
168 Self::ExpGolomb { k: 2 } => code_consts::EXP_GOLOMB2,
169 Self::ExpGolomb { k: 3 } => code_consts::EXP_GOLOMB3,
170 Self::ExpGolomb { k: 4 } => code_consts::EXP_GOLOMB4,
171 Self::ExpGolomb { k: 5 } => code_consts::EXP_GOLOMB5,
172 Self::ExpGolomb { k: 6 } => code_consts::EXP_GOLOMB6,
173 Self::ExpGolomb { k: 7 } => code_consts::EXP_GOLOMB7,
174 Self::ExpGolomb { k: 8 } => code_consts::EXP_GOLOMB8,
175 Self::ExpGolomb { k: 9 } => code_consts::EXP_GOLOMB9,
176 Self::ExpGolomb { k: 10 } => code_consts::EXP_GOLOMB10,
177 _ => {
178 return Err(anyhow::anyhow!(
179 "Code {:?} not supported as const code",
180 self
181 ))
182 }
183 })
184 }
185
186 pub fn from_code_const(const_code: usize) -> Result<Self> {
188 Ok(match const_code {
189 code_consts::UNARY => Self::Unary,
190 code_consts::GAMMA => Self::Gamma,
191 code_consts::DELTA => Self::Delta,
192 code_consts::OMEGA => Self::Omega,
193 code_consts::VBYTE_LE => Self::VByteLe,
194 code_consts::VBYTE_BE => Self::VByteBe,
195 code_consts::ZETA2 => Self::Zeta { k: 2 },
196 code_consts::ZETA3 => Self::Zeta { k: 3 },
197 code_consts::ZETA4 => Self::Zeta { k: 4 },
198 code_consts::ZETA5 => Self::Zeta { k: 5 },
199 code_consts::ZETA6 => Self::Zeta { k: 6 },
200 code_consts::ZETA7 => Self::Zeta { k: 7 },
201 code_consts::ZETA8 => Self::Zeta { k: 8 },
202 code_consts::ZETA9 => Self::Zeta { k: 9 },
203 code_consts::ZETA10 => Self::Zeta { k: 10 },
204 code_consts::RICE1 => Self::Rice { log2_b: 1 },
205 code_consts::RICE2 => Self::Rice { log2_b: 2 },
206 code_consts::RICE3 => Self::Rice { log2_b: 3 },
207 code_consts::RICE4 => Self::Rice { log2_b: 4 },
208 code_consts::RICE5 => Self::Rice { log2_b: 5 },
209 code_consts::RICE6 => Self::Rice { log2_b: 6 },
210 code_consts::RICE7 => Self::Rice { log2_b: 7 },
211 code_consts::RICE8 => Self::Rice { log2_b: 8 },
212 code_consts::RICE9 => Self::Rice { log2_b: 9 },
213 code_consts::RICE10 => Self::Rice { log2_b: 10 },
214 code_consts::PI1 => Self::Pi { k: 1 },
215 code_consts::PI2 => Self::Pi { k: 2 },
216 code_consts::PI3 => Self::Pi { k: 3 },
217 code_consts::PI4 => Self::Pi { k: 4 },
218 code_consts::PI5 => Self::Pi { k: 5 },
219 code_consts::PI6 => Self::Pi { k: 6 },
220 code_consts::PI7 => Self::Pi { k: 7 },
221 code_consts::PI8 => Self::Pi { k: 8 },
222 code_consts::PI9 => Self::Pi { k: 9 },
223 code_consts::PI10 => Self::Pi { k: 10 },
224 code_consts::GOLOMB3 => Self::Golomb { b: 3 },
225 code_consts::GOLOMB5 => Self::Golomb { b: 5 },
226 code_consts::GOLOMB6 => Self::Golomb { b: 6 },
227 code_consts::GOLOMB7 => Self::Golomb { b: 7 },
228 code_consts::GOLOMB9 => Self::Golomb { b: 9 },
229 code_consts::GOLOMB10 => Self::Golomb { b: 10 },
230 code_consts::EXP_GOLOMB1 => Self::ExpGolomb { k: 1 },
231 code_consts::EXP_GOLOMB2 => Self::ExpGolomb { k: 2 },
232 code_consts::EXP_GOLOMB3 => Self::ExpGolomb { k: 3 },
233 code_consts::EXP_GOLOMB4 => Self::ExpGolomb { k: 4 },
234 code_consts::EXP_GOLOMB5 => Self::ExpGolomb { k: 5 },
235 code_consts::EXP_GOLOMB6 => Self::ExpGolomb { k: 6 },
236 code_consts::EXP_GOLOMB7 => Self::ExpGolomb { k: 7 },
237 code_consts::EXP_GOLOMB8 => Self::ExpGolomb { k: 8 },
238 code_consts::EXP_GOLOMB9 => Self::ExpGolomb { k: 9 },
239 code_consts::EXP_GOLOMB10 => Self::ExpGolomb { k: 10 },
240 _ => return Err(anyhow::anyhow!("Code {} not supported", const_code)),
241 })
242 }
243}
244
245impl DynamicCodeRead for Codes {
246 #[inline]
247 fn read<E: Endianness, CR: CodesRead<E> + ?Sized>(
248 &self,
249 reader: &mut CR,
250 ) -> Result<u64, CR::Error> {
251 Ok(match self {
252 Codes::Unary => reader.read_unary()?,
253 Codes::Gamma => reader.read_gamma()?,
254 Codes::Delta => reader.read_delta()?,
255 Codes::Omega => reader.read_omega()?,
256 Codes::VByteBe => reader.read_vbyte_be()?,
257 Codes::VByteLe => reader.read_vbyte_le()?,
258 Codes::Zeta { k: 3 } => reader.read_zeta3()?,
259 Codes::Zeta { k } => reader.read_zeta(*k)?,
260 Codes::Pi { k } => reader.read_pi(*k)?,
261 Codes::Golomb { b } => reader.read_golomb(*b as u64)?,
262 Codes::ExpGolomb { k } => reader.read_exp_golomb(*k)?,
263 Codes::Rice { log2_b } => reader.read_rice(*log2_b)?,
264 })
265 }
266}
267
268impl DynamicCodeWrite for Codes {
269 #[inline]
270 fn write<E: Endianness, CW: CodesWrite<E> + ?Sized>(
271 &self,
272 writer: &mut CW,
273 value: u64,
274 ) -> Result<usize, CW::Error> {
275 Ok(match self {
276 Codes::Unary => writer.write_unary(value)?,
277 Codes::Gamma => writer.write_gamma(value)?,
278 Codes::Delta => writer.write_delta(value)?,
279 Codes::Omega => writer.write_omega(value)?,
280 Codes::VByteBe => writer.write_vbyte_be(value)?,
281 Codes::VByteLe => writer.write_vbyte_le(value)?,
282 Codes::Zeta { k: 1 } => writer.write_gamma(value)?,
283 Codes::Zeta { k: 3 } => writer.write_zeta3(value)?,
284 Codes::Zeta { k } => writer.write_zeta(value, *k)?,
285 Codes::Pi { k } => writer.write_pi(value, *k)?,
286 Codes::Golomb { b } => writer.write_golomb(value, *b as u64)?,
287 Codes::ExpGolomb { k } => writer.write_exp_golomb(value, *k)?,
288 Codes::Rice { log2_b } => writer.write_rice(value, *log2_b)?,
289 })
290 }
291}
292
293impl<E: Endianness, CR: CodesRead<E> + ?Sized> StaticCodeRead<E, CR> for Codes {
294 #[inline(always)]
295 fn read(&self, reader: &mut CR) -> Result<u64, CR::Error> {
296 <Self as DynamicCodeRead>::read(self, reader)
297 }
298}
299
300impl<E: Endianness, CW: CodesWrite<E> + ?Sized> StaticCodeWrite<E, CW> for Codes {
301 #[inline(always)]
302 fn write(&self, writer: &mut CW, value: u64) -> Result<usize, CW::Error> {
303 <Self as DynamicCodeWrite>::write(self, writer, value)
304 }
305}
306
307impl CodeLen for Codes {
308 #[inline]
309 fn len(&self, value: u64) -> usize {
310 match self {
311 Codes::Unary => value as usize + 1,
312 Codes::Gamma => len_gamma(value),
313 Codes::Delta => len_delta(value),
314 Codes::Omega => len_omega(value),
315 Codes::VByteLe | Codes::VByteBe => bit_len_vbyte(value),
316 Codes::Zeta { k: 1 } => len_gamma(value),
317 Codes::Zeta { k } => len_zeta(value, *k),
318 Codes::Pi { k } => len_pi(value, *k),
319 Codes::Golomb { b } => len_golomb(value, *b as u64),
320 Codes::ExpGolomb { k } => len_exp_golomb(value, *k),
321 Codes::Rice { log2_b } => len_rice(value, *log2_b),
322 }
323 }
324}
325
326#[derive(Debug)]
327pub enum CodeError {
329 ParseError(core::num::ParseIntError),
330 UnknownCode(String),
331}
332impl std::error::Error for CodeError {}
333impl core::fmt::Display for CodeError {
334 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
335 match self {
336 CodeError::ParseError(e) => write!(f, "Parse error: {}", e),
337 CodeError::UnknownCode(s) => write!(f, "Unknown code: {}", s),
338 }
339 }
340}
341
342impl From<core::num::ParseIntError> for CodeError {
343 fn from(e: core::num::ParseIntError) -> Self {
344 CodeError::ParseError(e)
345 }
346}
347
348impl core::fmt::Display for Codes {
349 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
350 match self {
351 Codes::Unary => write!(f, "Unary"),
352 Codes::Gamma => write!(f, "Gamma"),
353 Codes::Delta => write!(f, "Delta"),
354 Codes::Omega => write!(f, "Omega"),
355 Codes::VByteBe => write!(f, "VByteBe"),
356 Codes::VByteLe => write!(f, "VByteLe"),
357 Codes::Zeta { k } => write!(f, "Zeta({})", k),
358 Codes::Pi { k } => write!(f, "Pi({})", k),
359 Codes::Golomb { b } => write!(f, "Golomb({})", b),
360 Codes::ExpGolomb { k } => write!(f, "ExpGolomb({})", k),
361 Codes::Rice { log2_b } => write!(f, "Rice({})", log2_b),
362 }
363 }
364}
365
366impl std::str::FromStr for Codes {
367 type Err = CodeError;
368
369 fn from_str(s: &str) -> Result<Self, Self::Err> {
370 match s {
371 "Unary" => Ok(Codes::Unary),
372 "Gamma" => Ok(Codes::Gamma),
373 "Delta" => Ok(Codes::Delta),
374 "Omega" => Ok(Codes::Omega),
375 "VByteBe" => Ok(Codes::VByteBe),
376
377 _ => {
378 let mut parts = s.split('(');
379 let name = parts
380 .next()
381 .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?;
382 let k = parts
383 .next()
384 .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?
385 .split(')')
386 .next()
387 .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?;
388 match name {
389 "Zeta" => Ok(Codes::Zeta { k: k.parse()? }),
390 "Pi" => Ok(Codes::Pi { k: k.parse()? }),
391 "Golomb" => Ok(Codes::Golomb { b: k.parse()? }),
392 "ExpGolomb" => Ok(Codes::ExpGolomb { k: k.parse()? }),
393 "Rice" => Ok(Codes::Rice { log2_b: k.parse()? }),
394 _ => Err(CodeError::UnknownCode(format!("Could not parse {}", name))),
395 }
396 }
397 }
398 }
399}