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