• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vigna / dsi-bitstream-rs / 10547604359

25 Aug 2024 02:08PM UTC coverage: 58.71%. Remained the same
10547604359

push

github

Tommaso Fontana
fmt

1884 of 3209 relevant lines covered (58.71%)

3082082.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/codes/code.rs
1
/*
2
 * SPDX-FileCopyrightText: 2024 Tommaso Fontana
3
 *
4
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5
 */
6

7
//! A module for selecting the code to use either dynamically or at compile time.
8
//!
9
//! - [`Code`] is an enum with all the supported codes and can be used
10
//!   to test different codes in a generic way.
11
//! - [`ConstCode`] is a zero-sized struct with a const generic parameter that can be used
12
//!   to select the code at compile time.
13
//!
14
//! [`CodeRead`], [`CodeWrite`] and [`CodeLen`] are traits that both
15
//! [`Code`] and [`ConstCode`] implement to allow for generic code selection
16
//! over a generic bitstream.
17
//!
18
//! If you need to read or write a code multiple times on the same type of bitstream,
19
//! you can use [`CodeReadDispatch`] and [`CodeWriteDispatch`] which are
20
//! specialized versions of [`CodeRead`] and [`CodeWrite`] that are implemented
21
//! by [`Code`], [`ConstCode`] and [`CodeReadDispatcher`], [`CodeWriteDispatcher`]
22
//! which are more efficient for multiple reads and writes because they do
23
//! not need to do dynamic dispatch.
24
//!
25
//! While [`Code`] supports all the codes, [`ConstCode`] only supports a subset of
26
//! the most commonly used codes, because we have to manually write the dispatch  
27
//! for every combination of code and parameters. If you need more codes, you can
28
//! avoid this limitation by implementing your own version of it like this:
29
//!
30
//! ```rust
31
//! use dsi_bitstream::prelude::*;
32
//! use std::error::Error;
33
//! use std::fmt::Debug;
34
//!
35
//! #[derive(Clone, Copy, Debug, Default)]
36
//! pub struct Rice<const B: usize>;
37
//!
38
//! impl<const B: usize> CodeRead for Rice<B> {
39
//!     type Error<CRE> = CRE
40
//!     where
41
//!         CRE: Error + Debug + Send + Sync + 'static;
42
//!     fn read<E: Endianness, CR: ReadCodes<E> + ?Sized>(
43
//!         &self,
44
//!         reader: &mut CR,
45
//!     ) -> Result<u64, Self::Error<CR::Error>> {
46
//!         reader.read_rice(B)
47
//!     }
48
//! }
49
//!
50
//! impl<const B: usize> CodeWrite for Rice<B> {
51
//!     type Error<CWE> = CWE
52
//!     where
53
//!         CWE: Error + Debug + Send + Sync + 'static;
54
//!     fn write<E: Endianness, CW: WriteCodes<E> + ?Sized>(
55
//!         &self,
56
//!         writer: &mut CW,
57
//!         value: u64,
58
//!     ) -> Result<usize, Self::Error<CW::Error>> {
59
//!         writer.write_rice(value, B)
60
//!     }
61
//! }
62
//!
63
//! impl<const B: usize> CodeLen for Rice<B> {
64
//!     #[inline]
65
//!     fn len(&self, value: u64) -> usize {
66
//!         len_rice(value, B)
67
//!     }
68
//! }
69
//! ```
70

71
use super::*;
72
use core::fmt::Debug;
73
use core::marker::PhantomData;
74
use std::error::Error;
75

76
/// Something that can decode a value form any bitstream.
77
pub trait CodeRead {
78
    type Error<CRE>: Error + Debug + Send + Sync + 'static
79
    where
80
        CRE: Error + Debug + Send + Sync + 'static;
81
    /// Read a value
82
    fn read<E: Endianness, CR: ReadCodes<E> + ?Sized>(
83
        &self,
84
        reader: &mut CR,
85
    ) -> Result<u64, Self::Error<CR::Error>>;
86
}
87

88
/// Like [`CodeRead`] but with a specific endianness and reader.
89
/// This more specialized version allows also to do single static dispatch
90
/// of the read method for a code.
91
pub trait CodeReadDispatch<E, CR>
92
where
93
    E: Endianness,
94
    CR: ReadCodes<E> + ?Sized,
95
{
96
    type Error<CRE>: Error + Debug + Send + Sync + 'static
97
    where
98
        CRE: Error + Debug + Send + Sync + 'static;
99
    fn read_dispatch(&self, reader: &mut CR) -> Result<u64, Self::Error<CR::Error>>;
100
}
101

102
/// Something that can encode a value to any bitstream.
103
pub trait CodeWrite {
104
    type Error<CWE>: Error + Debug + Send + Sync + 'static
105
    where
106
        CWE: Error + Debug + Send + Sync + 'static;
107
    /// Write a value
108
    fn write<E: Endianness, CW: WriteCodes<E> + ?Sized>(
109
        &self,
110
        writer: &mut CW,
111
        value: u64,
112
    ) -> Result<usize, Self::Error<CW::Error>>;
113
}
114

115
/// Like [`CodeWrite`] but with a specific endianness and writer.
116
/// This more specialized version allows also to do single static dispatch
117
/// of the write method for a code.
118
pub trait CodeWriteDispatch<E, CW>
119
where
120
    E: Endianness,
121
    CW: WriteCodes<E> + ?Sized,
122
{
123
    type Error<CWE>: Error + Debug + Send + Sync + 'static
124
    where
125
        CWE: Error + Debug + Send + Sync + 'static;
126
    fn write_dispatch(&self, writer: &mut CW, value: u64) -> Result<usize, Self::Error<CW::Error>>;
127
}
128

129
/// Something that can compute the length of a value encoded with a code.
130
pub trait CodeLen {
131
    /// Compute how many bits it takes to encode a value with this code.
132
    fn len(&self, value: u64) -> usize;
133
}
134

135
#[derive(Debug)]
136
/// Error type for parsing a code from a string.
137
pub enum CodeError {
138
    ParseError(core::num::ParseIntError),
139
    UnknownCode(String),
140
}
141
impl std::error::Error for CodeError {}
142
impl core::fmt::Display for CodeError {
143
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
×
144
        match self {
×
145
            CodeError::ParseError(e) => write!(f, "Parse error: {}", e),
×
146
            CodeError::UnknownCode(s) => write!(f, "Unknown code: {}", s),
×
147
        }
148
    }
149
}
150

151
impl From<core::num::ParseIntError> for CodeError {
152
    fn from(e: core::num::ParseIntError) -> Self {
×
153
        CodeError::ParseError(e)
×
154
    }
155
}
156

157
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
158
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
159
#[non_exhaustive]
160
/// An enum of all the codes supported by this library, with their parameters.
161
/// This can be used to test different codes in a generic way.
162
pub enum Code {
163
    Unary,
164
    Gamma,
165
    Delta,
166
    Omega,
167
    VByte,
168
    Zeta { k: usize },
169
    Pi { k: usize },
170
    PiWeb { k: usize },
171
    Golomb { b: usize },
172
    ExpGolomb { k: usize },
173
    Rice { log2_b: usize },
174
}
175

176
impl CodeRead for Code {
177
    type Error<CRE> = CRE
178
    where
179
        CRE: Error + Debug + Send + Sync + 'static;
180
    #[inline]
181
    fn read<E: Endianness, CR: ReadCodes<E> + ?Sized>(
×
182
        &self,
183
        reader: &mut CR,
184
    ) -> Result<u64, Self::Error<CR::Error>> {
185
        Ok(match self {
×
186
            Code::Unary => reader.read_unary()?,
×
187
            Code::Gamma => reader.read_gamma()?,
×
188
            Code::Delta => reader.read_delta()?,
×
189
            Code::Omega => reader.read_omega()?,
×
190
            Code::VByte => reader.read_vbyte()?,
×
191
            Code::Zeta { k: 3 } => reader.read_zeta3()?,
×
192
            Code::Zeta { k } => reader.read_zeta(*k as u64)?,
×
193
            Code::Pi { k } => reader.read_pi(*k as u64)?,
×
194
            Code::PiWeb { k } => reader.read_pi_web(*k as u64)?,
×
195
            Code::Golomb { b } => reader.read_golomb(*b as u64)?,
×
196
            Code::ExpGolomb { k } => reader.read_exp_golomb(*k)?,
×
197
            Code::Rice { log2_b } => reader.read_rice(*log2_b)?,
×
198
        })
199
    }
200
}
201

202
impl<E, CR> CodeReadDispatch<E, CR> for Code
203
where
204
    E: Endianness,
205
    CR: ReadCodes<E> + ?Sized,
206
{
207
    type Error<CRE> = CRE
208
    where
209
        CRE: Error + Debug + Send + Sync + 'static;
210
    #[inline(always)]
211
    fn read_dispatch(&self, reader: &mut CR) -> Result<u64, Self::Error<CR::Error>> {
×
212
        <Self as CodeRead>::read(self, reader)
×
213
    }
214
}
215

216
impl CodeWrite for Code {
217
    type Error<CWE> = CWE
218
    where
219
        CWE: Error + Debug + Send + Sync + 'static;
220
    #[inline]
221
    fn write<E: Endianness, CW: WriteCodes<E> + ?Sized>(
×
222
        &self,
223
        writer: &mut CW,
224
        value: u64,
225
    ) -> Result<usize, Self::Error<CW::Error>> {
226
        Ok(match self {
×
227
            Code::Unary => writer.write_unary(value)?,
×
228
            Code::Gamma => writer.write_gamma(value)?,
×
229
            Code::Delta => writer.write_delta(value)?,
×
230
            Code::Omega => writer.write_omega(value)?,
×
231
            Code::VByte => writer.write_vbyte(value)?,
×
232
            Code::Zeta { k: 3 } => writer.write_zeta3(value)?,
×
233
            Code::Zeta { k } => writer.write_zeta(value, *k as u64)?,
×
234
            Code::Pi { k } => writer.write_pi(value, *k as u64)?,
×
235
            Code::PiWeb { k } => writer.write_pi_web(value, *k as u64)?,
×
236
            Code::Golomb { b } => writer.write_golomb(value, *b as u64)?,
×
237
            Code::ExpGolomb { k } => writer.write_exp_golomb(value, *k)?,
×
238
            Code::Rice { log2_b } => writer.write_rice(value, *log2_b)?,
×
239
        })
240
    }
241
}
242

243
impl<E, CW> CodeWriteDispatch<E, CW> for Code
244
where
245
    E: Endianness,
246
    CW: WriteCodes<E> + ?Sized,
247
{
248
    type Error<CWE> = CWE
249
    where
250
        CWE: Error + Debug + Send + Sync + 'static;
251
    #[inline(always)]
252
    fn write_dispatch(&self, writer: &mut CW, value: u64) -> Result<usize, Self::Error<CW::Error>> {
×
253
        <Self as CodeWrite>::write(self, writer, value)
×
254
    }
255
}
256

257
impl CodeLen for Code {
258
    #[inline]
259
    fn len(&self, value: u64) -> usize {
×
260
        match self {
×
261
            Code::Unary => value as usize + 1,
×
262
            Code::Gamma => len_gamma(value),
×
263
            Code::Delta => len_delta(value),
×
264
            Code::Omega => len_omega(value),
×
265
            Code::VByte => len_vbyte(value),
×
266
            Code::Zeta { k } => len_zeta(value, *k as u64),
×
267
            Code::Pi { k } => len_pi(value, *k as u64),
×
268
            Code::PiWeb { k } => len_pi_web(value, *k as u64),
×
269
            Code::Golomb { b } => len_golomb(value, *b as u64),
×
270
            Code::ExpGolomb { k } => len_exp_golomb(value, *k),
×
271
            Code::Rice { log2_b } => len_rice(value, *log2_b),
×
272
        }
273
    }
274
}
275

276
impl core::fmt::Display for Code {
277
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
×
278
        match self {
×
279
            Code::Unary => write!(f, "Unary"),
×
280
            Code::Gamma => write!(f, "Gamma"),
×
281
            Code::Delta => write!(f, "Delta"),
×
282
            Code::Omega => write!(f, "Omega"),
×
283
            Code::VByte => write!(f, "VByte"),
×
284
            Code::Zeta { k } => write!(f, "Zeta({})", k),
×
285
            Code::Pi { k } => write!(f, "Pi({})", k),
×
286
            Code::PiWeb { k } => write!(f, "PiWeb({})", k),
×
287
            Code::Golomb { b } => write!(f, "Golomb({})", b),
×
288
            Code::ExpGolomb { k } => write!(f, "ExpGolomb({})", k),
×
289
            Code::Rice { log2_b } => write!(f, "Rice({})", log2_b),
×
290
        }
291
    }
292
}
293

294
impl std::str::FromStr for Code {
295
    type Err = CodeError;
296

297
    fn from_str(s: &str) -> Result<Self, Self::Err> {
×
298
        match s {
×
299
            "Unary" => Ok(Code::Unary),
×
300
            "Gamma" => Ok(Code::Gamma),
×
301
            "Delta" => Ok(Code::Delta),
×
302
            "Omega" => Ok(Code::Omega),
×
303
            "VByte" => Ok(Code::VByte),
×
304
            _ => {
305
                let mut parts = s.split('(');
×
306
                let name = parts
×
307
                    .next()
308
                    .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?;
×
309
                let k = parts
×
310
                    .next()
311
                    .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?
×
312
                    .split(')')
313
                    .next()
314
                    .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?;
×
315
                match name {
316
                    "Zeta" => Ok(Code::Zeta { k: k.parse()? }),
×
317
                    "Pi" => Ok(Code::Pi { k: k.parse()? }),
×
318
                    "PiWeb" => Ok(Code::PiWeb { k: k.parse()? }),
×
319
                    "Golomb" => Ok(Code::Golomb { b: k.parse()? }),
×
320
                    "ExpGolomb" => Ok(Code::ExpGolomb { k: k.parse()? }),
×
321
                    "Rice" => Ok(Code::Rice { log2_b: k.parse()? }),
×
322
                    _ => Err(CodeError::UnknownCode(format!("Could not parse {}", name))),
×
323
                }
324
            }
325
        }
326
    }
327
}
328

329
type ReadFn<E, CR> = fn(&mut CR) -> Result<u64, <CR as BitRead<E>>::Error>;
330

331
/// Single static dispatch of the read method for a code.
332
/// This is a more efficient way to read codes that are initialized once dynamically,
333
/// and then used multiple times.
334
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
335
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
336
pub struct CodeReadDispatcher<E, CR>
337
where
338
    E: Endianness,
339
    CR: ReadCodes<E> + ?Sized,
340
{
341
    read: ReadFn<E, CR>,
342
    _marker: PhantomData<E>,
343
}
344

345
impl<E, CR> CodeReadDispatcher<E, CR>
346
where
347
    E: Endianness,
348
    CR: ReadCodes<E> + ?Sized,
349
{
350
    pub const UNARY: ReadFn<E, CR> = |reader: &mut CR| reader.read_unary();
×
351
    pub const GAMMA: ReadFn<E, CR> = |reader: &mut CR| reader.read_gamma();
×
352
    pub const DELTA: ReadFn<E, CR> = |reader: &mut CR| reader.read_delta();
×
353
    pub const OMEGA: ReadFn<E, CR> = |reader: &mut CR| reader.read_omega();
×
354
    pub const VBYTE: ReadFn<E, CR> = |reader: &mut CR| reader.read_vbyte();
×
355
    pub const ZETA2: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(2);
×
356
    pub const ZETA3: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta3();
×
357
    pub const ZETA4: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(4);
×
358
    pub const ZETA5: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(5);
×
359
    pub const ZETA6: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(6);
×
360
    pub const ZETA7: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(7);
×
361
    pub const ZETA8: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(8);
×
362
    pub const ZETA9: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(9);
×
363
    pub const ZETA10: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(10);
×
364
    pub const PI2: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(2);
×
365
    pub const PI3: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(3);
×
366
    pub const PI4: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(4);
×
367
    pub const PI5: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(5);
×
368
    pub const PI6: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(6);
×
369
    pub const PI7: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(7);
×
370
    pub const PI8: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(8);
×
371
    pub const PI9: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(9);
×
372
    pub const PI10: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(10);
×
373
    pub const PI_WEB2: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(2);
×
374
    pub const PI_WEB3: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(3);
×
375
    pub const PI_WEB4: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(4);
×
376
    pub const PI_WEB5: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(5);
×
377
    pub const PI_WEB6: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(6);
×
378
    pub const PI_WEB7: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(7);
×
379
    pub const PI_WEB8: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(8);
×
380
    pub const PI_WEB9: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(9);
×
381
    pub const PI_WEB10: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(10);
×
382
    pub const GOLOMB2: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(2);
×
383
    pub const GOLOMB3: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(3);
×
384
    pub const GOLOMB4: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(4);
×
385
    pub const GOLOMB5: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(5);
×
386
    pub const GOLOMB6: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(6);
×
387
    pub const GOLOMB7: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(7);
×
388
    pub const GOLOMB8: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(8);
×
389
    pub const GOLOMB9: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(9);
×
390
    pub const GOLOMB10: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(10);
×
391
    pub const EXP_GOLOMB2: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(2);
×
392
    pub const EXP_GOLOMB3: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(3);
×
393
    pub const EXP_GOLOMB4: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(4);
×
394
    pub const EXP_GOLOMB5: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(5);
×
395
    pub const EXP_GOLOMB6: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(6);
×
396
    pub const EXP_GOLOMB7: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(7);
×
397
    pub const EXP_GOLOMB8: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(8);
×
398
    pub const EXP_GOLOMB9: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(9);
×
399
    pub const EXP_GOLOMB10: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(10);
×
400
    pub const RICE2: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(2);
×
401
    pub const RICE3: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(3);
×
402
    pub const RICE4: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(4);
×
403
    pub const RICE5: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(5);
×
404
    pub const RICE6: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(6);
×
405
    pub const RICE7: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(7);
×
406
    pub const RICE8: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(8);
×
407
    pub const RICE9: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(9);
×
408
    pub const RICE10: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(10);
×
409

410
    /// Create a new dispatch for the given code.
411
    pub fn new(code: Code) -> Result<Self> {
×
412
        let read = match code {
×
413
            Code::Unary => Self::UNARY,
×
414
            Code::Gamma => Self::GAMMA,
×
415
            Code::Delta => Self::DELTA,
×
416
            Code::Omega => Self::OMEGA,
×
417
            Code::VByte => Self::VBYTE,
×
418
            Code::Zeta { k: 2 } => Self::ZETA2,
×
419
            Code::Zeta { k: 3 } => Self::ZETA3,
×
420
            Code::Zeta { k: 4 } => Self::ZETA4,
×
421
            Code::Zeta { k: 5 } => Self::ZETA5,
×
422
            Code::Zeta { k: 6 } => Self::ZETA6,
×
423
            Code::Zeta { k: 7 } => Self::ZETA7,
×
424
            Code::Zeta { k: 8 } => Self::ZETA8,
×
425
            Code::Zeta { k: 9 } => Self::ZETA9,
×
426
            Code::Zeta { k: 10 } => Self::ZETA10,
×
427
            Code::Pi { k: 2 } => Self::PI2,
×
428
            Code::Pi { k: 3 } => Self::PI3,
×
429
            Code::Pi { k: 4 } => Self::PI4,
×
430
            Code::Pi { k: 5 } => Self::PI5,
×
431
            Code::Pi { k: 6 } => Self::PI6,
×
432
            Code::Pi { k: 7 } => Self::PI7,
×
433
            Code::Pi { k: 8 } => Self::PI8,
×
434
            Code::Pi { k: 9 } => Self::PI9,
×
435
            Code::Pi { k: 10 } => Self::PI10,
×
436
            Code::PiWeb { k: 2 } => Self::PI_WEB2,
×
437
            Code::PiWeb { k: 3 } => Self::PI_WEB3,
×
438
            Code::PiWeb { k: 4 } => Self::PI_WEB4,
×
439
            Code::PiWeb { k: 5 } => Self::PI_WEB5,
×
440
            Code::PiWeb { k: 6 } => Self::PI_WEB6,
×
441
            Code::PiWeb { k: 7 } => Self::PI_WEB7,
×
442
            Code::PiWeb { k: 8 } => Self::PI_WEB8,
×
443
            Code::PiWeb { k: 9 } => Self::PI_WEB9,
×
444
            Code::PiWeb { k: 10 } => Self::PI_WEB10,
×
445
            Code::Golomb { b: 2 } => Self::GOLOMB2,
×
446
            Code::Golomb { b: 3 } => Self::GOLOMB3,
×
447
            Code::Golomb { b: 4 } => Self::GOLOMB4,
×
448
            Code::Golomb { b: 5 } => Self::GOLOMB5,
×
449
            Code::Golomb { b: 6 } => Self::GOLOMB6,
×
450
            Code::Golomb { b: 7 } => Self::GOLOMB7,
×
451
            Code::Golomb { b: 8 } => Self::GOLOMB8,
×
452
            Code::Golomb { b: 9 } => Self::GOLOMB9,
×
453
            Code::Golomb { b: 10 } => Self::GOLOMB10,
×
454
            Code::ExpGolomb { k: 2 } => Self::EXP_GOLOMB2,
×
455
            Code::ExpGolomb { k: 3 } => Self::EXP_GOLOMB3,
×
456
            Code::ExpGolomb { k: 4 } => Self::EXP_GOLOMB4,
×
457
            Code::ExpGolomb { k: 5 } => Self::EXP_GOLOMB5,
×
458
            Code::ExpGolomb { k: 6 } => Self::EXP_GOLOMB6,
×
459
            Code::ExpGolomb { k: 7 } => Self::EXP_GOLOMB7,
×
460
            Code::ExpGolomb { k: 8 } => Self::EXP_GOLOMB8,
×
461
            Code::ExpGolomb { k: 9 } => Self::EXP_GOLOMB9,
×
462
            Code::ExpGolomb { k: 10 } => Self::EXP_GOLOMB10,
×
463
            Code::Rice { log2_b: 2 } => Self::RICE2,
×
464
            Code::Rice { log2_b: 3 } => Self::RICE3,
×
465
            Code::Rice { log2_b: 4 } => Self::RICE4,
×
466
            Code::Rice { log2_b: 5 } => Self::RICE5,
×
467
            Code::Rice { log2_b: 6 } => Self::RICE6,
×
468
            Code::Rice { log2_b: 7 } => Self::RICE7,
×
469
            Code::Rice { log2_b: 8 } => Self::RICE8,
×
470
            Code::Rice { log2_b: 9 } => Self::RICE9,
×
471
            Code::Rice { log2_b: 10 } => Self::RICE10,
×
472
            _ => anyhow::bail!("Unsupported read dispatch for code {:?}", code),
×
473
        };
474
        Ok(Self {
×
475
            read,
×
476
            _marker: PhantomData,
×
477
        })
478
    }
479
}
480

481
impl<E, CR> CodeReadDispatch<E, CR> for CodeReadDispatcher<E, CR>
482
where
483
    E: Endianness,
484
    CR: ReadCodes<E> + ?Sized,
485
{
486
    type Error<CRE> = CRE
487
    where
488
        CRE: Error + Debug + Send + Sync + 'static;
489

490
    #[inline(always)]
491
    fn read_dispatch(&self, reader: &mut CR) -> Result<u64, Self::Error<CR::Error>> {
×
492
        (self.read)(reader).map_err(Into::into)
×
493
    }
494
}
495

496
type WriteFn<E, CW> = fn(&mut CW, u64) -> Result<usize, <CW as BitWrite<E>>::Error>;
497

498
/// Single static dispatch of the write method for a code.
499
/// This is a more efficient way to write codes that are initialized once dynamically,
500
/// and then used multiple times.
501
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
502
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
503
pub struct CodeWriteDispatcher<E, CW>
504
where
505
    E: Endianness,
506
    CW: WriteCodes<E> + ?Sized,
507
{
508
    write: WriteFn<E, CW>,
509
    _marker: PhantomData<E>,
510
}
511

512
impl<E, CW> CodeWriteDispatcher<E, CW>
513
where
514
    E: Endianness,
515
    CW: WriteCodes<E> + ?Sized,
516
{
517
    pub const UNARY: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_unary(value);
×
518
    pub const GAMMA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_gamma(value);
×
519
    pub const DELTA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_delta(value);
×
520
    pub const OMEGA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_omega(value);
×
521
    pub const VBYTE: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_vbyte(value);
×
522
    pub const ZETA2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 2);
×
523
    pub const ZETA3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta3(value);
×
524
    pub const ZETA4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 4);
×
525
    pub const ZETA5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 5);
×
526
    pub const ZETA6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 6);
×
527
    pub const ZETA7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 7);
×
528
    pub const ZETA8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 8);
×
529
    pub const ZETA9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 9);
×
530
    pub const ZETA10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 10);
×
531
    pub const PI2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 2);
×
532
    pub const PI3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 3);
×
533
    pub const PI4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 4);
×
534
    pub const PI5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 5);
×
535
    pub const PI6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 6);
×
536
    pub const PI7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 7);
×
537
    pub const PI8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 8);
×
538
    pub const PI9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 9);
×
539
    pub const PI10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 10);
×
540
    pub const PI_WEB2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 2);
×
541
    pub const PI_WEB3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 3);
×
542
    pub const PI_WEB4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 4);
×
543
    pub const PI_WEB5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 5);
×
544
    pub const PI_WEB6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 6);
×
545
    pub const PI_WEB7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 7);
×
546
    pub const PI_WEB8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 8);
×
547
    pub const PI_WEB9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 9);
×
548
    pub const PI_WEB10: WriteFn<E, CW> =
549
        |writer: &mut CW, value: u64| writer.write_pi_web(value, 10);
×
550
    pub const GOLOMB2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 2);
×
551
    pub const GOLOMB3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 3);
×
552
    pub const GOLOMB4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 4);
×
553
    pub const GOLOMB5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 5);
×
554
    pub const GOLOMB6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 6);
×
555
    pub const GOLOMB7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 7);
×
556
    pub const GOLOMB8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 8);
×
557
    pub const GOLOMB9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 9);
×
558
    pub const GOLOMB10: WriteFn<E, CW> =
559
        |writer: &mut CW, value: u64| writer.write_golomb(value, 10);
×
560
    pub const EXP_GOLOMB2: WriteFn<E, CW> =
561
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 2);
×
562
    pub const EXP_GOLOMB3: WriteFn<E, CW> =
563
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 3);
×
564
    pub const EXP_GOLOMB4: WriteFn<E, CW> =
565
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 4);
×
566
    pub const EXP_GOLOMB5: WriteFn<E, CW> =
567
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 5);
×
568
    pub const EXP_GOLOMB6: WriteFn<E, CW> =
569
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 6);
×
570
    pub const EXP_GOLOMB7: WriteFn<E, CW> =
571
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 7);
×
572
    pub const EXP_GOLOMB8: WriteFn<E, CW> =
573
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 8);
×
574
    pub const EXP_GOLOMB9: WriteFn<E, CW> =
575
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 9);
×
576
    pub const EXP_GOLOMB10: WriteFn<E, CW> =
577
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 10);
×
578
    pub const RICE2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 2);
×
579
    pub const RICE3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 3);
×
580
    pub const RICE4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 4);
×
581
    pub const RICE5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 5);
×
582
    pub const RICE6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 6);
×
583
    pub const RICE7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 7);
×
584
    pub const RICE8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 8);
×
585
    pub const RICE9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 9);
×
586
    pub const RICE10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 10);
×
587

588
    pub fn new(code: Code) -> Result<Self> {
×
589
        let write = match code {
×
590
            Code::Unary => Self::UNARY,
×
591
            Code::Gamma => Self::GAMMA,
×
592
            Code::Delta => Self::DELTA,
×
593
            Code::Omega => Self::OMEGA,
×
594
            Code::VByte => Self::VBYTE,
×
595
            Code::Zeta { k: 2 } => Self::ZETA2,
×
596
            Code::Zeta { k: 3 } => Self::ZETA3,
×
597
            Code::Zeta { k: 4 } => Self::ZETA4,
×
598
            Code::Zeta { k: 5 } => Self::ZETA5,
×
599
            Code::Zeta { k: 6 } => Self::ZETA6,
×
600
            Code::Zeta { k: 7 } => Self::ZETA7,
×
601
            Code::Zeta { k: 8 } => Self::ZETA8,
×
602
            Code::Zeta { k: 9 } => Self::ZETA9,
×
603
            Code::Zeta { k: 10 } => Self::ZETA10,
×
604
            Code::Pi { k: 2 } => Self::PI2,
×
605
            Code::Pi { k: 3 } => Self::PI3,
×
606
            Code::Pi { k: 4 } => Self::PI4,
×
607
            Code::Pi { k: 5 } => Self::PI5,
×
608
            Code::Pi { k: 6 } => Self::PI6,
×
609
            Code::Pi { k: 7 } => Self::PI7,
×
610
            Code::Pi { k: 8 } => Self::PI8,
×
611
            Code::Pi { k: 9 } => Self::PI9,
×
612
            Code::Pi { k: 10 } => Self::PI10,
×
613
            Code::PiWeb { k: 2 } => Self::PI_WEB2,
×
614
            Code::PiWeb { k: 3 } => Self::PI_WEB3,
×
615
            Code::PiWeb { k: 4 } => Self::PI_WEB4,
×
616
            Code::PiWeb { k: 5 } => Self::PI_WEB5,
×
617
            Code::PiWeb { k: 6 } => Self::PI_WEB6,
×
618
            Code::PiWeb { k: 7 } => Self::PI_WEB7,
×
619
            Code::PiWeb { k: 8 } => Self::PI_WEB8,
×
620
            Code::PiWeb { k: 9 } => Self::PI_WEB9,
×
621
            Code::PiWeb { k: 10 } => Self::PI_WEB10,
×
622
            Code::Golomb { b: 2 } => Self::GOLOMB2,
×
623
            Code::Golomb { b: 3 } => Self::GOLOMB3,
×
624
            Code::Golomb { b: 4 } => Self::GOLOMB4,
×
625
            Code::Golomb { b: 5 } => Self::GOLOMB5,
×
626
            Code::Golomb { b: 6 } => Self::GOLOMB6,
×
627
            Code::Golomb { b: 7 } => Self::GOLOMB7,
×
628
            Code::Golomb { b: 8 } => Self::GOLOMB8,
×
629
            Code::Golomb { b: 9 } => Self::GOLOMB9,
×
630
            Code::Golomb { b: 10 } => Self::GOLOMB10,
×
631
            Code::ExpGolomb { k: 2 } => Self::EXP_GOLOMB2,
×
632
            Code::ExpGolomb { k: 3 } => Self::EXP_GOLOMB3,
×
633
            Code::ExpGolomb { k: 4 } => Self::EXP_GOLOMB4,
×
634
            Code::ExpGolomb { k: 5 } => Self::EXP_GOLOMB5,
×
635
            Code::ExpGolomb { k: 6 } => Self::EXP_GOLOMB6,
×
636
            Code::ExpGolomb { k: 7 } => Self::EXP_GOLOMB7,
×
637
            Code::ExpGolomb { k: 8 } => Self::EXP_GOLOMB8,
×
638
            Code::ExpGolomb { k: 9 } => Self::EXP_GOLOMB9,
×
639
            Code::ExpGolomb { k: 10 } => Self::EXP_GOLOMB10,
×
640
            Code::Rice { log2_b: 2 } => Self::RICE2,
×
641
            Code::Rice { log2_b: 3 } => Self::RICE3,
×
642
            Code::Rice { log2_b: 4 } => Self::RICE4,
×
643
            Code::Rice { log2_b: 5 } => Self::RICE5,
×
644
            Code::Rice { log2_b: 6 } => Self::RICE6,
×
645
            Code::Rice { log2_b: 7 } => Self::RICE7,
×
646
            Code::Rice { log2_b: 8 } => Self::RICE8,
×
647
            Code::Rice { log2_b: 9 } => Self::RICE9,
×
648
            Code::Rice { log2_b: 10 } => Self::RICE10,
×
649
            _ => anyhow::bail!("Unsupported write dispatch for code {:?}", code),
×
650
        };
651
        Ok(Self {
×
652
            write,
×
653
            _marker: PhantomData,
×
654
        })
655
    }
656
}
657

658
impl<E, CW> CodeWriteDispatch<E, CW> for CodeWriteDispatcher<E, CW>
659
where
660
    E: Endianness,
661
    CW: WriteCodes<E> + ?Sized,
662
{
663
    type Error<CWE> = CWE
664
    where
665
        CWE: Error + Debug + Send + Sync + 'static;
666
    #[inline(always)]
667
    fn write_dispatch(&self, writer: &mut CW, value: u64) -> Result<usize, Self::Error<CW::Error>> {
×
668
        (self.write)(writer, value).map_err(Into::into)
×
669
    }
670
}
671

672
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
673
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
674
/// A zero-sized struct with a const generic parameter that can be used to
675
/// select the code at compile time.
676
///
677
/// This only implements a subset of the most commonly used codes.
678
/// If you need to use a code that is not implemented here, you can
679
/// implement [`CodeRead`], [`CodeWrite`], and [`CodeLen`] for your own struct
680
/// like in the example of the [`code`] module.
681
pub struct ConstCode<const CODE: usize>;
682

683
/// The constants ot use as generic parameter of the [`ConstCode`] struct.
684
pub mod const_codes {
685
    /// This macro just define a bunch of constants with progressive values.
686
    /// It is used to assign a unique integer to each code.
687
    macro_rules! impl_codes {
688
        ($code:ident, $($tail:ident),*) => {
689
            pub const $code: usize = 0 $( + 1 + (0 * $tail))*;
690
            impl_codes!($($tail),*);
691
        };
692
        ($code:ident) => {
693
            pub const $code: usize = 0;
694
        };
695
    }
696

697
    impl_codes!(
698
        ZETA1,
699
        ZETA2,
700
        ZETA3,
701
        ZETA4,
702
        ZETA5,
703
        ZETA6,
704
        ZETA7,
705
        ZETA8,
706
        ZETA9,
707
        ZETA10,
708
        PI2,
709
        PI3,
710
        PI4,
711
        PI5,
712
        PI6,
713
        PI7,
714
        PI8,
715
        PI9,
716
        PI10,
717
        PI_WEB2,
718
        PI_WEB3,
719
        PI_WEB4,
720
        PI_WEB5,
721
        PI_WEB6,
722
        PI_WEB7,
723
        PI_WEB8,
724
        PI_WEB9,
725
        PI_WEB10,
726
        GOLOMB2,
727
        GOLOMB3,
728
        GOLOMB4,
729
        GOLOMB5,
730
        GOLOMB6,
731
        GOLOMB7,
732
        GOLOMB8,
733
        GOLOMB9,
734
        GOLOMB10,
735
        EXP_GOLOMB2,
736
        EXP_GOLOMB3,
737
        EXP_GOLOMB4,
738
        EXP_GOLOMB5,
739
        EXP_GOLOMB6,
740
        EXP_GOLOMB7,
741
        EXP_GOLOMB8,
742
        EXP_GOLOMB9,
743
        EXP_GOLOMB10,
744
        RICE2,
745
        RICE3,
746
        RICE4,
747
        RICE5,
748
        RICE6,
749
        RICE7,
750
        RICE8,
751
        RICE9,
752
        RICE10,
753
        VBYTE,
754
        OMEGA,
755
        DELTA,
756
        GAMMA,
757
        UNARY
758
    );
759
}
760

761
impl<const CODE: usize> CodeRead for ConstCode<CODE> {
762
    type Error<CRE> = CRE
763
    where
764
        CRE: Error + Debug + Send + Sync + 'static;
765
    fn read<E: Endianness, CR: ReadCodes<E> + ?Sized>(
×
766
        &self,
767
        reader: &mut CR,
768
    ) -> Result<u64, Self::Error<CR::Error>> {
769
        match CODE {
×
770
            const_codes::UNARY => reader.read_unary(),
×
771
            const_codes::GAMMA => reader.read_gamma(),
×
772
            const_codes::DELTA => reader.read_delta(),
×
773
            const_codes::OMEGA => reader.read_omega(),
×
774
            const_codes::VBYTE => reader.read_vbyte(),
×
775
            const_codes::ZETA1 => reader.read_zeta(1),
×
776
            const_codes::ZETA2 => reader.read_zeta(2),
×
777
            const_codes::ZETA3 => reader.read_zeta3(),
×
778
            const_codes::ZETA4 => reader.read_zeta(4),
×
779
            const_codes::ZETA5 => reader.read_zeta(5),
×
780
            const_codes::ZETA6 => reader.read_zeta(6),
×
781
            const_codes::ZETA7 => reader.read_zeta(7),
×
782
            const_codes::ZETA8 => reader.read_zeta(8),
×
783
            const_codes::ZETA9 => reader.read_zeta(9),
×
784
            const_codes::ZETA10 => reader.read_zeta(10),
×
785
            const_codes::PI2 => reader.read_pi(2),
×
786
            const_codes::PI3 => reader.read_pi(3),
×
787
            const_codes::PI4 => reader.read_pi(4),
×
788
            const_codes::PI5 => reader.read_pi(5),
×
789
            const_codes::PI6 => reader.read_pi(6),
×
790
            const_codes::PI7 => reader.read_pi(7),
×
791
            const_codes::PI8 => reader.read_pi(8),
×
792
            const_codes::PI9 => reader.read_pi(9),
×
793
            const_codes::PI10 => reader.read_pi(10),
×
794
            const_codes::PI_WEB2 => reader.read_pi_web(2),
×
795
            const_codes::PI_WEB3 => reader.read_pi_web(3),
×
796
            const_codes::PI_WEB4 => reader.read_pi_web(4),
×
797
            const_codes::PI_WEB5 => reader.read_pi_web(5),
×
798
            const_codes::PI_WEB6 => reader.read_pi_web(6),
×
799
            const_codes::PI_WEB7 => reader.read_pi_web(7),
×
800
            const_codes::PI_WEB8 => reader.read_pi_web(8),
×
801
            const_codes::PI_WEB9 => reader.read_pi_web(9),
×
802
            const_codes::PI_WEB10 => reader.read_pi_web(10),
×
803
            const_codes::GOLOMB2 => reader.read_golomb(2),
×
804
            const_codes::GOLOMB3 => reader.read_golomb(3),
×
805
            const_codes::GOLOMB4 => reader.read_golomb(4),
×
806
            const_codes::GOLOMB5 => reader.read_golomb(5),
×
807
            const_codes::GOLOMB6 => reader.read_golomb(6),
×
808
            const_codes::GOLOMB7 => reader.read_golomb(7),
×
809
            const_codes::GOLOMB8 => reader.read_golomb(8),
×
810
            const_codes::GOLOMB9 => reader.read_golomb(9),
×
811
            const_codes::GOLOMB10 => reader.read_golomb(10),
×
812
            const_codes::EXP_GOLOMB2 => reader.read_exp_golomb(2),
×
813
            const_codes::EXP_GOLOMB3 => reader.read_exp_golomb(3),
×
814
            const_codes::EXP_GOLOMB4 => reader.read_exp_golomb(4),
×
815
            const_codes::EXP_GOLOMB5 => reader.read_exp_golomb(5),
×
816
            const_codes::EXP_GOLOMB6 => reader.read_exp_golomb(6),
×
817
            const_codes::EXP_GOLOMB7 => reader.read_exp_golomb(7),
×
818
            const_codes::EXP_GOLOMB8 => reader.read_exp_golomb(8),
×
819
            const_codes::EXP_GOLOMB9 => reader.read_exp_golomb(9),
×
820
            const_codes::EXP_GOLOMB10 => reader.read_exp_golomb(10),
×
821
            const_codes::RICE2 => reader.read_rice(2),
×
822
            const_codes::RICE3 => reader.read_rice(3),
×
823
            const_codes::RICE4 => reader.read_rice(4),
×
824
            const_codes::RICE5 => reader.read_rice(5),
×
825
            const_codes::RICE6 => reader.read_rice(6),
×
826
            const_codes::RICE7 => reader.read_rice(7),
×
827
            const_codes::RICE8 => reader.read_rice(8),
×
828
            const_codes::RICE9 => reader.read_rice(9),
×
829
            const_codes::RICE10 => reader.read_rice(10),
×
830
            _ => panic!("Unknown code: {}", CODE),
×
831
        }
832
    }
833
}
834

835
impl<E, CR, const CODE: usize> CodeReadDispatch<E, CR> for ConstCode<CODE>
836
where
837
    E: Endianness,
838
    CR: ReadCodes<E> + ?Sized,
839
{
840
    type Error<CRE> = CRE
841
    where
842
        CRE: Error + Debug + Send + Sync + 'static;
843
    #[inline(always)]
844
    fn read_dispatch(&self, reader: &mut CR) -> Result<u64, Self::Error<CR::Error>> {
×
845
        <Self as CodeRead>::read(self, reader)
×
846
    }
847
}
848

849
impl<const CODE: usize> CodeWrite for ConstCode<CODE> {
850
    type Error<CWE> = CWE
851
    where
852
        CWE: Error + Debug + Send + Sync + 'static;
853
    fn write<E: Endianness, CW: WriteCodes<E> + ?Sized>(
×
854
        &self,
855
        writer: &mut CW,
856
        value: u64,
857
    ) -> Result<usize, Self::Error<CW::Error>> {
858
        match CODE {
×
859
            const_codes::UNARY => writer.write_unary(value),
×
860
            const_codes::GAMMA => writer.write_gamma(value),
×
861
            const_codes::DELTA => writer.write_delta(value),
×
862
            const_codes::OMEGA => writer.write_omega(value),
×
863
            const_codes::VBYTE => writer.write_vbyte(value),
×
864
            const_codes::ZETA1 => writer.write_zeta(value, 1),
×
865
            const_codes::ZETA2 => writer.write_zeta(value, 2),
×
866
            const_codes::ZETA3 => writer.write_zeta3(value),
×
867
            const_codes::ZETA4 => writer.write_zeta(value, 4),
×
868
            const_codes::ZETA5 => writer.write_zeta(value, 5),
×
869
            const_codes::ZETA6 => writer.write_zeta(value, 6),
×
870
            const_codes::ZETA7 => writer.write_zeta(value, 7),
×
871
            const_codes::ZETA8 => writer.write_zeta(value, 8),
×
872
            const_codes::ZETA9 => writer.write_zeta(value, 9),
×
873
            const_codes::ZETA10 => writer.write_zeta(value, 10),
×
874
            const_codes::PI2 => writer.write_pi(value, 2),
×
875
            const_codes::PI3 => writer.write_pi(value, 3),
×
876
            const_codes::PI4 => writer.write_pi(value, 4),
×
877
            const_codes::PI5 => writer.write_pi(value, 5),
×
878
            const_codes::PI6 => writer.write_pi(value, 6),
×
879
            const_codes::PI7 => writer.write_pi(value, 7),
×
880
            const_codes::PI8 => writer.write_pi(value, 8),
×
881
            const_codes::PI9 => writer.write_pi(value, 9),
×
882
            const_codes::PI10 => writer.write_pi(value, 10),
×
883
            const_codes::PI_WEB2 => writer.write_pi_web(value, 2),
×
884
            const_codes::PI_WEB3 => writer.write_pi_web(value, 3),
×
885
            const_codes::PI_WEB4 => writer.write_pi_web(value, 4),
×
886
            const_codes::PI_WEB5 => writer.write_pi_web(value, 5),
×
887
            const_codes::PI_WEB6 => writer.write_pi_web(value, 6),
×
888
            const_codes::PI_WEB7 => writer.write_pi_web(value, 7),
×
889
            const_codes::PI_WEB8 => writer.write_pi_web(value, 8),
×
890
            const_codes::PI_WEB9 => writer.write_pi_web(value, 9),
×
891
            const_codes::PI_WEB10 => writer.write_pi_web(value, 10),
×
892
            const_codes::GOLOMB2 => writer.write_golomb(value, 2),
×
893
            const_codes::GOLOMB3 => writer.write_golomb(value, 3),
×
894
            const_codes::GOLOMB4 => writer.write_golomb(value, 4),
×
895
            const_codes::GOLOMB5 => writer.write_golomb(value, 5),
×
896
            const_codes::GOLOMB6 => writer.write_golomb(value, 6),
×
897
            const_codes::GOLOMB7 => writer.write_golomb(value, 7),
×
898
            const_codes::GOLOMB8 => writer.write_golomb(value, 8),
×
899
            const_codes::GOLOMB9 => writer.write_golomb(value, 9),
×
900
            const_codes::GOLOMB10 => writer.write_golomb(value, 10),
×
901
            const_codes::EXP_GOLOMB2 => writer.write_exp_golomb(value, 2),
×
902
            const_codes::EXP_GOLOMB3 => writer.write_exp_golomb(value, 3),
×
903
            const_codes::EXP_GOLOMB4 => writer.write_exp_golomb(value, 4),
×
904
            const_codes::EXP_GOLOMB5 => writer.write_exp_golomb(value, 5),
×
905
            const_codes::EXP_GOLOMB6 => writer.write_exp_golomb(value, 6),
×
906
            const_codes::EXP_GOLOMB7 => writer.write_exp_golomb(value, 7),
×
907
            const_codes::EXP_GOLOMB8 => writer.write_exp_golomb(value, 8),
×
908
            const_codes::EXP_GOLOMB9 => writer.write_exp_golomb(value, 9),
×
909
            const_codes::EXP_GOLOMB10 => writer.write_exp_golomb(value, 10),
×
910
            const_codes::RICE2 => writer.write_rice(value, 2),
×
911
            const_codes::RICE3 => writer.write_rice(value, 3),
×
912
            const_codes::RICE4 => writer.write_rice(value, 4),
×
913
            const_codes::RICE5 => writer.write_rice(value, 5),
×
914
            const_codes::RICE6 => writer.write_rice(value, 6),
×
915
            const_codes::RICE7 => writer.write_rice(value, 7),
×
916
            const_codes::RICE8 => writer.write_rice(value, 8),
×
917
            const_codes::RICE9 => writer.write_rice(value, 9),
×
918
            const_codes::RICE10 => writer.write_rice(value, 10),
×
919
            _ => panic!("Unknown code: {}", CODE),
×
920
        }
921
    }
922
}
923

924
impl<E, CW, const CODE: usize> CodeWriteDispatch<E, CW> for ConstCode<CODE>
925
where
926
    E: Endianness,
927
    CW: WriteCodes<E> + ?Sized,
928
{
929
    type Error<CWE> = CWE
930
    where
931
        CWE: Error + Debug + Send + Sync + 'static;
932
    #[inline(always)]
933
    fn write_dispatch(&self, writer: &mut CW, value: u64) -> Result<usize, Self::Error<CW::Error>> {
×
934
        <Self as CodeWrite>::write(self, writer, value)
×
935
    }
936
}
937

938
impl<const CODE: usize> CodeLen for ConstCode<CODE> {
939
    #[inline]
940
    fn len(&self, value: u64) -> usize {
×
941
        match CODE {
×
942
            const_codes::UNARY => value as usize + 1,
×
943
            const_codes::GAMMA => len_gamma(value),
×
944
            const_codes::DELTA => len_delta(value),
×
945
            const_codes::OMEGA => len_omega(value),
×
946
            const_codes::VBYTE => len_vbyte(value),
×
947
            const_codes::ZETA1 => len_zeta(value, 1),
×
948
            const_codes::ZETA2 => len_zeta(value, 2),
×
949
            const_codes::ZETA3 => len_zeta(value, 3),
×
950
            const_codes::ZETA4 => len_zeta(value, 4),
×
951
            const_codes::ZETA5 => len_zeta(value, 5),
×
952
            const_codes::ZETA6 => len_zeta(value, 6),
×
953
            const_codes::ZETA7 => len_zeta(value, 7),
×
954
            const_codes::ZETA8 => len_zeta(value, 8),
×
955
            const_codes::ZETA9 => len_zeta(value, 9),
×
956
            const_codes::ZETA10 => len_zeta(value, 10),
×
957
            const_codes::PI2 => len_pi(value, 2),
×
958
            const_codes::PI3 => len_pi(value, 3),
×
959
            const_codes::PI4 => len_pi(value, 4),
×
960
            const_codes::PI5 => len_pi(value, 5),
×
961
            const_codes::PI6 => len_pi(value, 6),
×
962
            const_codes::PI7 => len_pi(value, 7),
×
963
            const_codes::PI8 => len_pi(value, 8),
×
964
            const_codes::PI9 => len_pi(value, 9),
×
965
            const_codes::PI10 => len_pi(value, 10),
×
966
            const_codes::PI_WEB2 => len_pi_web(value, 2),
×
967
            const_codes::PI_WEB3 => len_pi_web(value, 3),
×
968
            const_codes::PI_WEB4 => len_pi_web(value, 4),
×
969
            const_codes::PI_WEB5 => len_pi_web(value, 5),
×
970
            const_codes::PI_WEB6 => len_pi_web(value, 6),
×
971
            const_codes::PI_WEB7 => len_pi_web(value, 7),
×
972
            const_codes::PI_WEB8 => len_pi_web(value, 8),
×
973
            const_codes::PI_WEB9 => len_pi_web(value, 9),
×
974
            const_codes::PI_WEB10 => len_pi_web(value, 10),
×
975
            const_codes::GOLOMB2 => len_golomb(value, 2),
×
976
            const_codes::GOLOMB3 => len_golomb(value, 3),
×
977
            const_codes::GOLOMB4 => len_golomb(value, 4),
×
978
            const_codes::GOLOMB5 => len_golomb(value, 5),
×
979
            const_codes::GOLOMB6 => len_golomb(value, 6),
×
980
            const_codes::GOLOMB7 => len_golomb(value, 7),
×
981
            const_codes::GOLOMB8 => len_golomb(value, 8),
×
982
            const_codes::GOLOMB9 => len_golomb(value, 9),
×
983
            const_codes::GOLOMB10 => len_golomb(value, 10),
×
984
            const_codes::EXP_GOLOMB2 => len_exp_golomb(value, 2),
×
985
            const_codes::EXP_GOLOMB3 => len_exp_golomb(value, 3),
×
986
            const_codes::EXP_GOLOMB4 => len_exp_golomb(value, 4),
×
987
            const_codes::EXP_GOLOMB5 => len_exp_golomb(value, 5),
×
988
            const_codes::EXP_GOLOMB6 => len_exp_golomb(value, 6),
×
989
            const_codes::EXP_GOLOMB7 => len_exp_golomb(value, 7),
×
990
            const_codes::EXP_GOLOMB8 => len_exp_golomb(value, 8),
×
991
            const_codes::EXP_GOLOMB9 => len_exp_golomb(value, 9),
×
992
            const_codes::EXP_GOLOMB10 => len_exp_golomb(value, 10),
×
993
            const_codes::RICE2 => len_rice(value, 2),
×
994
            const_codes::RICE3 => len_rice(value, 3),
×
995
            const_codes::RICE4 => len_rice(value, 4),
×
996
            const_codes::RICE5 => len_rice(value, 5),
×
997
            const_codes::RICE6 => len_rice(value, 6),
×
998
            const_codes::RICE7 => len_rice(value, 7),
×
999
            const_codes::RICE8 => len_rice(value, 8),
×
1000
            const_codes::RICE9 => len_rice(value, 9),
×
1001
            const_codes::RICE10 => len_rice(value, 10),
×
1002
            _ => panic!("Unknown code: {}", CODE),
×
1003
        }
1004
    }
1005
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc