1use super::*;
16#[cfg(feature = "serde")]
17use alloc::string::{String, ToString};
18#[cfg(feature = "mem_dbg")]
19use mem_dbg::{MemDbg, MemSize};
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
31#[cfg_attr(feature = "mem_dbg", mem_size_flat)]
32#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
33#[non_exhaustive]
34pub enum Codes {
35 Unary,
36 Gamma,
37 Delta,
38 Omega,
39 VByteLe,
40 VByteBe,
41 Zeta(usize),
42 Pi(usize),
43 Golomb(u64),
44 ExpGolomb(usize),
45 Rice(usize),
46}
47
48impl Codes {
49 #[must_use]
69 pub const fn canonicalize(self) -> Self {
70 match self {
71 Self::Zeta(1) | Self::ExpGolomb(0) | Self::Pi(0) => Self::Gamma,
72 Self::Rice(0) | Self::Golomb(1) => Self::Unary,
73 Self::Golomb(b) if b.is_power_of_two() => Self::Rice(b.trailing_zeros() as usize),
74 other => other,
75 }
76 }
77
78 #[inline(always)]
83 pub fn read<E: Endianness, CR: CodesRead<E> + ?Sized>(
84 &self,
85 reader: &mut CR,
86 ) -> Result<u64, CR::Error> {
87 DynamicCodeRead::read(self, reader)
88 }
89
90 #[inline(always)]
95 pub fn write<E: Endianness, CW: CodesWrite<E> + ?Sized>(
96 &self,
97 writer: &mut CW,
98 n: u64,
99 ) -> Result<usize, CW::Error> {
100 DynamicCodeWrite::write(self, writer, n)
101 }
102
103 pub const fn to_code_const(&self) -> Result<usize, DispatchError> {
116 Ok(match self.canonicalize() {
117 Self::Unary => code_consts::UNARY,
118 Self::Gamma => code_consts::GAMMA,
119 Self::Delta => code_consts::DELTA,
120 Self::Omega => code_consts::OMEGA,
121 Self::VByteLe => code_consts::VBYTE_LE,
122 Self::VByteBe => code_consts::VBYTE_BE,
123 Self::Zeta(2) => code_consts::ZETA2,
124 Self::Zeta(3) => code_consts::ZETA3,
125 Self::Zeta(4) => code_consts::ZETA4,
126 Self::Zeta(5) => code_consts::ZETA5,
127 Self::Zeta(6) => code_consts::ZETA6,
128 Self::Zeta(7) => code_consts::ZETA7,
129 Self::Zeta(8) => code_consts::ZETA8,
130 Self::Zeta(9) => code_consts::ZETA9,
131 Self::Zeta(10) => code_consts::ZETA10,
132 Self::Rice(1) => code_consts::RICE1,
133 Self::Rice(2) => code_consts::RICE2,
134 Self::Rice(3) => code_consts::RICE3,
135 Self::Rice(4) => code_consts::RICE4,
136 Self::Rice(5) => code_consts::RICE5,
137 Self::Rice(6) => code_consts::RICE6,
138 Self::Rice(7) => code_consts::RICE7,
139 Self::Rice(8) => code_consts::RICE8,
140 Self::Rice(9) => code_consts::RICE9,
141 Self::Rice(10) => code_consts::RICE10,
142 Self::Pi(1) => code_consts::PI1,
143 Self::Pi(2) => code_consts::PI2,
144 Self::Pi(3) => code_consts::PI3,
145 Self::Pi(4) => code_consts::PI4,
146 Self::Pi(5) => code_consts::PI5,
147 Self::Pi(6) => code_consts::PI6,
148 Self::Pi(7) => code_consts::PI7,
149 Self::Pi(8) => code_consts::PI8,
150 Self::Pi(9) => code_consts::PI9,
151 Self::Pi(10) => code_consts::PI10,
152 Self::Golomb(3) => code_consts::GOLOMB3,
153 Self::Golomb(5) => code_consts::GOLOMB5,
154 Self::Golomb(6) => code_consts::GOLOMB6,
155 Self::Golomb(7) => code_consts::GOLOMB7,
156 Self::Golomb(9) => code_consts::GOLOMB9,
157 Self::Golomb(10) => code_consts::GOLOMB10,
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(DispatchError::UnsupportedCode(*self));
170 }
171 })
172 }
173
174 pub const fn from_code_const(const_code: usize) -> Result<Self, DispatchError> {
181 Ok(match const_code {
182 code_consts::UNARY => Self::Unary,
183 code_consts::GAMMA => Self::Gamma,
184 code_consts::DELTA => Self::Delta,
185 code_consts::OMEGA => Self::Omega,
186 code_consts::VBYTE_LE => Self::VByteLe,
187 code_consts::VBYTE_BE => Self::VByteBe,
188 code_consts::ZETA2 => Self::Zeta(2),
189 code_consts::ZETA3 => Self::Zeta(3),
190 code_consts::ZETA4 => Self::Zeta(4),
191 code_consts::ZETA5 => Self::Zeta(5),
192 code_consts::ZETA6 => Self::Zeta(6),
193 code_consts::ZETA7 => Self::Zeta(7),
194 code_consts::ZETA8 => Self::Zeta(8),
195 code_consts::ZETA9 => Self::Zeta(9),
196 code_consts::ZETA10 => Self::Zeta(10),
197 code_consts::RICE1 => Self::Rice(1),
198 code_consts::RICE2 => Self::Rice(2),
199 code_consts::RICE3 => Self::Rice(3),
200 code_consts::RICE4 => Self::Rice(4),
201 code_consts::RICE5 => Self::Rice(5),
202 code_consts::RICE6 => Self::Rice(6),
203 code_consts::RICE7 => Self::Rice(7),
204 code_consts::RICE8 => Self::Rice(8),
205 code_consts::RICE9 => Self::Rice(9),
206 code_consts::RICE10 => Self::Rice(10),
207 code_consts::PI1 => Self::Pi(1),
208 code_consts::PI2 => Self::Pi(2),
209 code_consts::PI3 => Self::Pi(3),
210 code_consts::PI4 => Self::Pi(4),
211 code_consts::PI5 => Self::Pi(5),
212 code_consts::PI6 => Self::Pi(6),
213 code_consts::PI7 => Self::Pi(7),
214 code_consts::PI8 => Self::Pi(8),
215 code_consts::PI9 => Self::Pi(9),
216 code_consts::PI10 => Self::Pi(10),
217 code_consts::GOLOMB3 => Self::Golomb(3),
218 code_consts::GOLOMB5 => Self::Golomb(5),
219 code_consts::GOLOMB6 => Self::Golomb(6),
220 code_consts::GOLOMB7 => Self::Golomb(7),
221 code_consts::GOLOMB9 => Self::Golomb(9),
222 code_consts::GOLOMB10 => Self::Golomb(10),
223 code_consts::EXP_GOLOMB1 => Self::ExpGolomb(1),
224 code_consts::EXP_GOLOMB2 => Self::ExpGolomb(2),
225 code_consts::EXP_GOLOMB3 => Self::ExpGolomb(3),
226 code_consts::EXP_GOLOMB4 => Self::ExpGolomb(4),
227 code_consts::EXP_GOLOMB5 => Self::ExpGolomb(5),
228 code_consts::EXP_GOLOMB6 => Self::ExpGolomb(6),
229 code_consts::EXP_GOLOMB7 => Self::ExpGolomb(7),
230 code_consts::EXP_GOLOMB8 => Self::ExpGolomb(8),
231 code_consts::EXP_GOLOMB9 => Self::ExpGolomb(9),
232 code_consts::EXP_GOLOMB10 => Self::ExpGolomb(10),
233 _ => return Err(DispatchError::UnsupportedCodeConst(const_code)),
234 })
235 }
236}
237
238impl DynamicCodeRead for Codes {
239 #[inline]
240 fn read<E: Endianness, CR: CodesRead<E> + ?Sized>(
241 &self,
242 reader: &mut CR,
243 ) -> Result<u64, CR::Error> {
244 Ok(match self.canonicalize() {
245 Codes::Unary => reader.read_unary()?,
246 Codes::Gamma => reader.read_gamma()?,
247 Codes::Delta => reader.read_delta()?,
248 Codes::Omega => reader.read_omega()?,
249 Codes::VByteBe => reader.read_vbyte_be()?,
250 Codes::VByteLe => reader.read_vbyte_le()?,
251 Codes::Zeta(3) => reader.read_zeta3()?,
252 Codes::Zeta(k) => reader.read_zeta(k)?,
253 Codes::Pi(2) => reader.read_pi2()?,
254 Codes::Pi(k) => reader.read_pi(k)?,
255 Codes::Golomb(b) => reader.read_golomb(b)?,
256 Codes::ExpGolomb(k) => reader.read_exp_golomb(k)?,
257 Codes::Rice(log2_b) => reader.read_rice(log2_b)?,
258 })
259 }
260}
261
262impl DynamicCodeWrite for Codes {
263 #[inline]
264 fn write<E: Endianness, CW: CodesWrite<E> + ?Sized>(
265 &self,
266 writer: &mut CW,
267 n: u64,
268 ) -> Result<usize, CW::Error> {
269 Ok(match self.canonicalize() {
270 Codes::Unary => writer.write_unary(n)?,
271 Codes::Gamma => writer.write_gamma(n)?,
272 Codes::Delta => writer.write_delta(n)?,
273 Codes::Omega => writer.write_omega(n)?,
274 Codes::VByteBe => writer.write_vbyte_be(n)?,
275 Codes::VByteLe => writer.write_vbyte_le(n)?,
276 Codes::Zeta(3) => writer.write_zeta3(n)?,
277 Codes::Zeta(k) => writer.write_zeta(n, k)?,
278 Codes::Pi(2) => writer.write_pi2(n)?,
279 Codes::Pi(k) => writer.write_pi(n, k)?,
280 Codes::Golomb(b) => writer.write_golomb(n, b)?,
281 Codes::ExpGolomb(k) => writer.write_exp_golomb(n, k)?,
282 Codes::Rice(log2_b) => writer.write_rice(n, log2_b)?,
283 })
284 }
285}
286
287impl<E: Endianness, CR: CodesRead<E> + ?Sized> StaticCodeRead<E, CR> for Codes {
288 #[inline(always)]
289 fn read(&self, reader: &mut CR) -> Result<u64, CR::Error> {
290 <Self as DynamicCodeRead>::read(self, reader)
291 }
292}
293
294impl<E: Endianness, CW: CodesWrite<E> + ?Sized> StaticCodeWrite<E, CW> for Codes {
295 #[inline(always)]
296 fn write(&self, writer: &mut CW, n: u64) -> Result<usize, CW::Error> {
297 <Self as DynamicCodeWrite>::write(self, writer, n)
298 }
299}
300
301impl CodeLen for Codes {
302 #[inline]
303 fn len(&self, n: u64) -> usize {
304 match self.canonicalize() {
305 Codes::Unary => n as usize + 1,
306 Codes::Gamma => len_gamma(n),
307 Codes::Delta => len_delta(n),
308 Codes::Omega => len_omega(n),
309 Codes::VByteLe | Codes::VByteBe => bit_len_vbyte(n),
310 Codes::Zeta(k) => len_zeta(n, k),
311 Codes::Pi(k) => len_pi(n, k),
312 Codes::Golomb(b) => len_golomb(n, b),
313 Codes::ExpGolomb(k) => len_exp_golomb(n, k),
314 Codes::Rice(log2_b) => len_rice(n, log2_b),
315 }
316 }
317}
318
319#[derive(Debug, Clone)]
321pub enum CodeError {
322 ParseError(core::num::ParseIntError),
324 UnknownCode([u8; 32]),
326}
327impl core::error::Error for CodeError {}
328impl core::fmt::Display for CodeError {
329 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
330 match self {
331 CodeError::ParseError(e) => write!(f, "parse error: {}", e),
332 CodeError::UnknownCode(s) => {
333 write!(f, "unknown code: ")?;
334 for c in s {
335 if *c == 0 {
336 break;
337 }
338 write!(f, "{}", *c as char)?;
339 }
340 Ok(())
341 }
342 }
343 }
344}
345
346impl From<core::num::ParseIntError> for CodeError {
347 fn from(e: core::num::ParseIntError) -> Self {
348 CodeError::ParseError(e)
349 }
350}
351
352impl core::fmt::Display for Codes {
353 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
354 match self {
355 Codes::Unary => write!(f, "Unary"),
356 Codes::Gamma => write!(f, "Gamma"),
357 Codes::Delta => write!(f, "Delta"),
358 Codes::Omega => write!(f, "Omega"),
359 Codes::VByteBe => write!(f, "VByteBe"),
360 Codes::VByteLe => write!(f, "VByteLe"),
361 Codes::Zeta(k) => write!(f, "Zeta({})", k),
362 Codes::Pi(k) => write!(f, "Pi({})", k),
363 Codes::Golomb(b) => write!(f, "Golomb({})", b),
364 Codes::ExpGolomb(k) => write!(f, "ExpGolomb({})", k),
365 Codes::Rice(log2_b) => write!(f, "Rice({})", log2_b),
366 }
367 }
368}
369
370fn array_format_error(s: &str) -> [u8; 32] {
371 let mut error_buffer = [0u8; 32];
372 let len = s.len().min(32);
373 error_buffer[..len].copy_from_slice(&s.as_bytes()[..len]);
374 error_buffer
375}
376
377impl core::str::FromStr for Codes {
378 type Err = CodeError;
379
380 fn from_str(s: &str) -> Result<Self, Self::Err> {
381 match s {
382 "Unary" => Ok(Codes::Unary),
383 "Gamma" => Ok(Codes::Gamma),
384 "Delta" => Ok(Codes::Delta),
385 "Omega" => Ok(Codes::Omega),
386 "VByteBe" => Ok(Codes::VByteBe),
387 "VByteLe" => Ok(Codes::VByteLe),
388
389 _ => {
390 let mut parts = s.split('(');
391 let name = parts
392 .next()
393 .ok_or_else(|| CodeError::UnknownCode(array_format_error(s)))?;
394 let k = parts
395 .next()
396 .ok_or_else(|| CodeError::UnknownCode(array_format_error(s)))?
397 .split(')')
398 .next()
399 .ok_or_else(|| CodeError::UnknownCode(array_format_error(s)))?;
400 match name {
401 "Zeta" => Ok(Codes::Zeta(k.parse()?)),
402 "Pi" => Ok(Codes::Pi(k.parse()?)),
403 "Golomb" => Ok(Codes::Golomb(k.parse()?)),
404 "ExpGolomb" => Ok(Codes::ExpGolomb(k.parse()?)),
405 "Rice" => Ok(Codes::Rice(k.parse()?)),
406 _ => Err(CodeError::UnknownCode(array_format_error(name))),
407 }
408 }
409 }
410 }
411}
412
413#[cfg(feature = "serde")]
414impl serde::Serialize for Codes {
415 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
416 where
417 S: serde::Serializer,
418 {
419 serializer.serialize_str(&self.to_string())
420 }
421}
422
423#[cfg(feature = "serde")]
424impl<'de> serde::Deserialize<'de> for Codes {
425 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
426 where
427 D: serde::Deserializer<'de>,
428 {
429 let s = String::deserialize(deserializer)?;
430 s.parse().map_err(serde::de::Error::custom)
431 }
432}
433
434#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
444pub struct MinimalBinary(
445 pub u64,
447);
448
449impl DynamicCodeRead for MinimalBinary {
450 fn read<E: Endianness, R: CodesRead<E> + ?Sized>(
451 &self,
452 reader: &mut R,
453 ) -> Result<u64, R::Error> {
454 reader.read_minimal_binary(self.0)
455 }
456}
457
458impl DynamicCodeWrite for MinimalBinary {
459 fn write<E: Endianness, W: CodesWrite<E> + ?Sized>(
460 &self,
461 writer: &mut W,
462 n: u64,
463 ) -> Result<usize, W::Error> {
464 writer.write_minimal_binary(n, self.0)
465 }
466}
467
468impl<E: Endianness, CR: CodesRead<E> + ?Sized> StaticCodeRead<E, CR> for MinimalBinary {
469 fn read(&self, reader: &mut CR) -> Result<u64, CR::Error> {
470 <Self as DynamicCodeRead>::read(self, reader)
471 }
472}
473
474impl<E: Endianness, CW: CodesWrite<E> + ?Sized> StaticCodeWrite<E, CW> for MinimalBinary {
475 fn write(&self, writer: &mut CW, n: u64) -> Result<usize, CW::Error> {
476 <Self as DynamicCodeWrite>::write(self, writer, n)
477 }
478}
479
480impl CodeLen for MinimalBinary {
481 fn len(&self, n: u64) -> usize {
482 len_minimal_binary(n, self.0)
483 }
484}