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

vigna / dsi-bitstream-rs / 10182869467

31 Jul 2024 03:11PM UTC coverage: 58.897% (+0.06%) from 58.835%
10182869467

push

github

vigna
cargo fmt

1890 of 3209 relevant lines covered (58.9%)

3003623.69 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
//! [`CodeStatsWrapper`] is a struct that can wrap any struct implementing
26
//! [`CodeRead`] or [`CodeWrite`], and keep track of the space it would need to
27
//! store the same sequence using different codes. This can be used as a
28
//! transparent wrapper to figure out which code is the best for a given sequence.
29
//!
30

31
use super::*;
32
use core::fmt::Debug;
33
use core::marker::PhantomData;
34
use std::error::Error;
35

36
/// Something that can decode a value form any bitstream.
37
pub trait CodeRead {
38
    type Error<CRE>: Error + Debug + Send + Sync + 'static
39
    where
40
        CRE: Error + Debug + Send + Sync + 'static;
41
    /// Read a value
42
    fn read<E: Endianness, CR: ReadCodes<E> + ?Sized>(
43
        &self,
44
        reader: &mut CR,
45
    ) -> Result<u64, Self::Error<CR::Error>>;
46
}
47

48
/// Like [`CodeRead`] but with a specific endianness and reader.
49
/// This more specialized version allows also to do single static dispatch
50
/// of the read method for a code.
51
pub trait CodeReadDispatch<E, CR>
52
where
53
    E: Endianness,
54
    CR: ReadCodes<E> + ?Sized,
55
{
56
    type Error<CRE>: Error + Debug + Send + Sync + 'static
57
    where
58
        CRE: Error + Debug + Send + Sync + 'static;
59
    fn read_dispatch(&self, reader: &mut CR) -> Result<u64, Self::Error<CR::Error>>;
60
}
61

62
/// Something that can encode a value to any bitstream.
63
pub trait CodeWrite {
64
    type Error<CWE>: Error + Debug + Send + Sync + 'static
65
    where
66
        CWE: Error + Debug + Send + Sync + 'static;
67
    /// Write a value
68
    fn write<E: Endianness, CW: WriteCodes<E> + ?Sized>(
69
        &self,
70
        writer: &mut CW,
71
        value: u64,
72
    ) -> Result<usize, Self::Error<CW::Error>>;
73
}
74

75
/// Like [`CodeWrite`] but with a specific endianness and writer.
76
/// This more specialized version allows also to do single static dispatch
77
/// of the write method for a code.
78
pub trait CodeWriteDispatch<E, CW>
79
where
80
    E: Endianness,
81
    CW: WriteCodes<E> + ?Sized,
82
{
83
    type Error<CWE>: Error + Debug + Send + Sync + 'static
84
    where
85
        CWE: Error + Debug + Send + Sync + 'static;
86
    fn write_dispatch(&self, writer: &mut CW, value: u64) -> Result<usize, Self::Error<CW::Error>>;
87
}
88

89
/// Something that can compute the length of a value encoded with a code.
90
pub trait CodeLen {
91
    /// Compute how many bits it takes to encode a value with this code.
92
    fn len(&self, value: u64) -> usize;
93
}
94

95
#[derive(Debug)]
96
/// Error type for parsing a code from a string.
97
pub enum CodeError {
98
    ParseError(core::num::ParseIntError),
99
    UnknownCode(String),
100
}
101
impl std::error::Error for CodeError {}
102
impl core::fmt::Display for CodeError {
103
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
×
104
        match self {
×
105
            CodeError::ParseError(e) => write!(f, "Parse error: {}", e),
×
106
            CodeError::UnknownCode(s) => write!(f, "Unknown code: {}", s),
×
107
        }
108
    }
109
}
110

111
impl From<core::num::ParseIntError> for CodeError {
112
    fn from(e: core::num::ParseIntError) -> Self {
×
113
        CodeError::ParseError(e)
×
114
    }
115
}
116

117
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
118
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
119
#[non_exhaustive]
120
/// An enum of all the codes supported by this library, with their parameters.
121
/// This can be used to test different codes in a generic way.
122
pub enum Code {
123
    Unary,
124
    Gamma,
125
    Delta,
126
    Omega,
127
    VByte,
128
    Zeta { k: usize },
129
    Pi { k: usize },
130
    PiWeb { k: usize },
131
    Golomb { b: usize },
132
    ExpGolomb { k: usize },
133
    Rice { log2_b: usize },
134
}
135

136
impl CodeRead for Code {
137
    type Error<CRE> = CRE
138
    where
139
        CRE: Error + Debug + Send + Sync + 'static;
140
    #[inline]
141
    fn read<E: Endianness, CR: ReadCodes<E> + ?Sized>(
×
142
        &self,
143
        reader: &mut CR,
144
    ) -> Result<u64, Self::Error<CR::Error>> {
145
        Ok(match self {
×
146
            Code::Unary => reader.read_unary()?,
×
147
            Code::Gamma => reader.read_gamma()?,
×
148
            Code::Delta => reader.read_delta()?,
×
149
            Code::Omega => reader.read_omega()?,
×
150
            Code::VByte => reader.read_vbyte()?,
×
151
            Code::Zeta { k: 3 } => reader.read_zeta3()?,
×
152
            Code::Zeta { k } => reader.read_zeta(*k as u64)?,
×
153
            Code::Pi { k } => reader.read_pi(*k as u64)?,
×
154
            Code::PiWeb { k } => reader.read_pi_web(*k as u64)?,
×
155
            Code::Golomb { b } => reader.read_golomb(*b as u64)?,
×
156
            Code::ExpGolomb { k } => reader.read_exp_golomb(*k)?,
×
157
            Code::Rice { log2_b } => reader.read_rice(*log2_b)?,
×
158
        })
159
    }
160
}
161

162
impl<E, CR> CodeReadDispatch<E, CR> for Code
163
where
164
    E: Endianness,
165
    CR: ReadCodes<E> + ?Sized,
166
{
167
    type Error<CRE> = CRE
168
    where
169
        CRE: Error + Debug + Send + Sync + 'static;
170
    #[inline(always)]
171
    fn read_dispatch(&self, reader: &mut CR) -> Result<u64, Self::Error<CR::Error>> {
×
172
        <Self as CodeRead>::read(self, reader)
×
173
    }
174
}
175

176
impl CodeWrite for Code {
177
    type Error<CWE> = CWE
178
    where
179
        CWE: Error + Debug + Send + Sync + 'static;
180
    #[inline]
181
    fn write<E: Endianness, CW: WriteCodes<E> + ?Sized>(
×
182
        &self,
183
        writer: &mut CW,
184
        value: u64,
185
    ) -> Result<usize, Self::Error<CW::Error>> {
186
        Ok(match self {
×
187
            Code::Unary => writer.write_unary(value)?,
×
188
            Code::Gamma => writer.write_gamma(value)?,
×
189
            Code::Delta => writer.write_delta(value)?,
×
190
            Code::Omega => writer.write_omega(value)?,
×
191
            Code::VByte => writer.write_vbyte(value)?,
×
192
            Code::Zeta { k: 3 } => writer.write_zeta3(value)?,
×
193
            Code::Zeta { k } => writer.write_zeta(value, *k as u64)?,
×
194
            Code::Pi { k } => writer.write_pi(value, *k as u64)?,
×
195
            Code::PiWeb { k } => writer.write_pi_web(value, *k as u64)?,
×
196
            Code::Golomb { b } => writer.write_golomb(value, *b as u64)?,
×
197
            Code::ExpGolomb { k } => writer.write_exp_golomb(value, *k)?,
×
198
            Code::Rice { log2_b } => writer.write_rice(value, *log2_b)?,
×
199
        })
200
    }
201
}
202

203
impl<E, CW> CodeWriteDispatch<E, CW> for Code
204
where
205
    E: Endianness,
206
    CW: WriteCodes<E> + ?Sized,
207
{
208
    type Error<CWE> = CWE
209
    where
210
        CWE: Error + Debug + Send + Sync + 'static;
211
    #[inline(always)]
212
    fn write_dispatch(&self, writer: &mut CW, value: u64) -> Result<usize, Self::Error<CW::Error>> {
×
213
        <Self as CodeWrite>::write(self, writer, value)
×
214
    }
215
}
216

217
impl CodeLen for Code {
218
    #[inline]
219
    fn len(&self, value: u64) -> usize {
×
220
        match self {
×
221
            Code::Unary => value as usize + 1,
×
222
            Code::Gamma => len_gamma(value),
×
223
            Code::Delta => len_delta(value),
×
224
            Code::Omega => len_omega(value),
×
225
            Code::VByte => len_vbyte(value),
×
226
            Code::Zeta { k } => len_zeta(value, *k as u64),
×
227
            Code::Pi { k } => len_pi(value, *k as u64),
×
228
            Code::PiWeb { k } => len_pi_web(value, *k as u64),
×
229
            Code::Golomb { b } => len_golomb(value, *b as u64),
×
230
            Code::ExpGolomb { k } => len_exp_golomb(value, *k),
×
231
            Code::Rice { log2_b } => len_rice(value, *log2_b),
×
232
        }
233
    }
234
}
235

236
impl core::fmt::Display for Code {
237
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
×
238
        match self {
×
239
            Code::Unary => write!(f, "Unary"),
×
240
            Code::Gamma => write!(f, "Gamma"),
×
241
            Code::Delta => write!(f, "Delta"),
×
242
            Code::Omega => write!(f, "Omega"),
×
243
            Code::VByte => write!(f, "VByte"),
×
244
            Code::Zeta { k } => write!(f, "Zeta({})", k),
×
245
            Code::Pi { k } => write!(f, "Pi({})", k),
×
246
            Code::PiWeb { k } => write!(f, "PiWeb({})", k),
×
247
            Code::Golomb { b } => write!(f, "Golomb({})", b),
×
248
            Code::ExpGolomb { k } => write!(f, "ExpGolomb({})", k),
×
249
            Code::Rice { log2_b } => write!(f, "Rice({})", log2_b),
×
250
        }
251
    }
252
}
253

254
impl std::str::FromStr for Code {
255
    type Err = CodeError;
256

257
    fn from_str(s: &str) -> Result<Self, Self::Err> {
×
258
        match s {
×
259
            "Unary" => Ok(Code::Unary),
×
260
            "Gamma" => Ok(Code::Gamma),
×
261
            "Delta" => Ok(Code::Delta),
×
262
            "Omega" => Ok(Code::Omega),
×
263
            "VByte" => Ok(Code::VByte),
×
264
            _ => {
265
                let mut parts = s.split('(');
×
266
                let name = parts
×
267
                    .next()
268
                    .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?;
×
269
                let k = parts
×
270
                    .next()
271
                    .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?
×
272
                    .split(')')
273
                    .next()
274
                    .ok_or_else(|| CodeError::UnknownCode(format!("Could not parse {}", s)))?;
×
275
                match name {
276
                    "Zeta" => Ok(Code::Zeta { k: k.parse()? }),
×
277
                    "Pi" => Ok(Code::Pi { k: k.parse()? }),
×
278
                    "PiWeb" => Ok(Code::PiWeb { k: k.parse()? }),
×
279
                    "Golomb" => Ok(Code::Golomb { b: k.parse()? }),
×
280
                    "ExpGolomb" => Ok(Code::ExpGolomb { k: k.parse()? }),
×
281
                    "Rice" => Ok(Code::Rice { log2_b: k.parse()? }),
×
282
                    _ => Err(CodeError::UnknownCode(format!("Could not parse {}", name))),
×
283
                }
284
            }
285
        }
286
    }
287
}
288

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

291
/// Single static dispatch of the read method for a code.
292
/// This is a more efficient way to read codes that are initialized once dynamically,
293
/// and then used multiple times.
294
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
295
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
296
pub struct CodeReadDispatcher<E, CR>
297
where
298
    E: Endianness,
299
    CR: ReadCodes<E> + ?Sized,
300
{
301
    read: ReadFn<E, CR>,
302
    _marker: PhantomData<E>,
303
}
304

305
impl<E, CR> CodeReadDispatcher<E, CR>
306
where
307
    E: Endianness,
308
    CR: ReadCodes<E> + ?Sized,
309
{
310
    pub const UNARY: ReadFn<E, CR> = |reader: &mut CR| reader.read_unary();
×
311
    pub const GAMMA: ReadFn<E, CR> = |reader: &mut CR| reader.read_gamma();
×
312
    pub const DELTA: ReadFn<E, CR> = |reader: &mut CR| reader.read_delta();
×
313
    pub const OMEGA: ReadFn<E, CR> = |reader: &mut CR| reader.read_omega();
×
314
    pub const VBYTE: ReadFn<E, CR> = |reader: &mut CR| reader.read_vbyte();
×
315
    pub const ZETA2: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(2);
×
316
    pub const ZETA3: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta3();
×
317
    pub const ZETA4: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(4);
×
318
    pub const ZETA5: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(5);
×
319
    pub const ZETA6: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(6);
×
320
    pub const ZETA7: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(7);
×
321
    pub const ZETA8: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(8);
×
322
    pub const ZETA9: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(9);
×
323
    pub const ZETA10: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(10);
×
324
    pub const PI2: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(2);
×
325
    pub const PI3: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(3);
×
326
    pub const PI4: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(4);
×
327
    pub const PI5: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(5);
×
328
    pub const PI6: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(6);
×
329
    pub const PI7: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(7);
×
330
    pub const PI8: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(8);
×
331
    pub const PI9: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(9);
×
332
    pub const PI10: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(10);
×
333
    pub const PI_WEB2: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(2);
×
334
    pub const PI_WEB3: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(3);
×
335
    pub const PI_WEB4: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(4);
×
336
    pub const PI_WEB5: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(5);
×
337
    pub const PI_WEB6: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(6);
×
338
    pub const PI_WEB7: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(7);
×
339
    pub const PI_WEB8: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(8);
×
340
    pub const PI_WEB9: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(9);
×
341
    pub const PI_WEB10: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi_web(10);
×
342
    pub const GOLOMB2: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(2);
×
343
    pub const GOLOMB3: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(3);
×
344
    pub const GOLOMB4: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(4);
×
345
    pub const GOLOMB5: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(5);
×
346
    pub const GOLOMB6: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(6);
×
347
    pub const GOLOMB7: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(7);
×
348
    pub const GOLOMB8: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(8);
×
349
    pub const GOLOMB9: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(9);
×
350
    pub const GOLOMB10: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(10);
×
351
    pub const EXP_GOLOMB2: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(2);
×
352
    pub const EXP_GOLOMB3: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(3);
×
353
    pub const EXP_GOLOMB4: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(4);
×
354
    pub const EXP_GOLOMB5: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(5);
×
355
    pub const EXP_GOLOMB6: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(6);
×
356
    pub const EXP_GOLOMB7: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(7);
×
357
    pub const EXP_GOLOMB8: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(8);
×
358
    pub const EXP_GOLOMB9: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(9);
×
359
    pub const EXP_GOLOMB10: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(10);
×
360
    pub const RICE2: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(2);
×
361
    pub const RICE3: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(3);
×
362
    pub const RICE4: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(4);
×
363
    pub const RICE5: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(5);
×
364
    pub const RICE6: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(6);
×
365
    pub const RICE7: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(7);
×
366
    pub const RICE8: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(8);
×
367
    pub const RICE9: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(9);
×
368
    pub const RICE10: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(10);
×
369

370
    /// Create a new dispatch for the given code.
371
    pub fn new(code: Code) -> Result<Self> {
×
372
        let read = match code {
×
373
            Code::Unary => Self::UNARY,
×
374
            Code::Gamma => Self::GAMMA,
×
375
            Code::Delta => Self::DELTA,
×
376
            Code::Omega => Self::OMEGA,
×
377
            Code::VByte => Self::VBYTE,
×
378
            Code::Zeta { k: 2 } => Self::ZETA2,
×
379
            Code::Zeta { k: 3 } => Self::ZETA3,
×
380
            Code::Zeta { k: 4 } => Self::ZETA4,
×
381
            Code::Zeta { k: 5 } => Self::ZETA5,
×
382
            Code::Zeta { k: 6 } => Self::ZETA6,
×
383
            Code::Zeta { k: 7 } => Self::ZETA7,
×
384
            Code::Zeta { k: 8 } => Self::ZETA8,
×
385
            Code::Zeta { k: 9 } => Self::ZETA9,
×
386
            Code::Zeta { k: 10 } => Self::ZETA10,
×
387
            Code::Pi { k: 2 } => Self::PI2,
×
388
            Code::Pi { k: 3 } => Self::PI3,
×
389
            Code::Pi { k: 4 } => Self::PI4,
×
390
            Code::Pi { k: 5 } => Self::PI5,
×
391
            Code::Pi { k: 6 } => Self::PI6,
×
392
            Code::Pi { k: 7 } => Self::PI7,
×
393
            Code::Pi { k: 8 } => Self::PI8,
×
394
            Code::Pi { k: 9 } => Self::PI9,
×
395
            Code::Pi { k: 10 } => Self::PI10,
×
396
            Code::PiWeb { k: 2 } => Self::PI_WEB2,
×
397
            Code::PiWeb { k: 3 } => Self::PI_WEB3,
×
398
            Code::PiWeb { k: 4 } => Self::PI_WEB4,
×
399
            Code::PiWeb { k: 5 } => Self::PI_WEB5,
×
400
            Code::PiWeb { k: 6 } => Self::PI_WEB6,
×
401
            Code::PiWeb { k: 7 } => Self::PI_WEB7,
×
402
            Code::PiWeb { k: 8 } => Self::PI_WEB8,
×
403
            Code::PiWeb { k: 9 } => Self::PI_WEB9,
×
404
            Code::PiWeb { k: 10 } => Self::PI_WEB10,
×
405
            Code::Golomb { b: 2 } => Self::GOLOMB2,
×
406
            Code::Golomb { b: 3 } => Self::GOLOMB3,
×
407
            Code::Golomb { b: 4 } => Self::GOLOMB4,
×
408
            Code::Golomb { b: 5 } => Self::GOLOMB5,
×
409
            Code::Golomb { b: 6 } => Self::GOLOMB6,
×
410
            Code::Golomb { b: 7 } => Self::GOLOMB7,
×
411
            Code::Golomb { b: 8 } => Self::GOLOMB8,
×
412
            Code::Golomb { b: 9 } => Self::GOLOMB9,
×
413
            Code::Golomb { b: 10 } => Self::GOLOMB10,
×
414
            Code::ExpGolomb { k: 2 } => Self::EXP_GOLOMB2,
×
415
            Code::ExpGolomb { k: 3 } => Self::EXP_GOLOMB3,
×
416
            Code::ExpGolomb { k: 4 } => Self::EXP_GOLOMB4,
×
417
            Code::ExpGolomb { k: 5 } => Self::EXP_GOLOMB5,
×
418
            Code::ExpGolomb { k: 6 } => Self::EXP_GOLOMB6,
×
419
            Code::ExpGolomb { k: 7 } => Self::EXP_GOLOMB7,
×
420
            Code::ExpGolomb { k: 8 } => Self::EXP_GOLOMB8,
×
421
            Code::ExpGolomb { k: 9 } => Self::EXP_GOLOMB9,
×
422
            Code::ExpGolomb { k: 10 } => Self::EXP_GOLOMB10,
×
423
            Code::Rice { log2_b: 2 } => Self::RICE2,
×
424
            Code::Rice { log2_b: 3 } => Self::RICE3,
×
425
            Code::Rice { log2_b: 4 } => Self::RICE4,
×
426
            Code::Rice { log2_b: 5 } => Self::RICE5,
×
427
            Code::Rice { log2_b: 6 } => Self::RICE6,
×
428
            Code::Rice { log2_b: 7 } => Self::RICE7,
×
429
            Code::Rice { log2_b: 8 } => Self::RICE8,
×
430
            Code::Rice { log2_b: 9 } => Self::RICE9,
×
431
            Code::Rice { log2_b: 10 } => Self::RICE10,
×
432
            _ => anyhow::bail!("Unsupported read dispatch for code {:?}", code),
×
433
        };
434
        Ok(Self {
×
435
            read,
×
436
            _marker: PhantomData,
×
437
        })
438
    }
439
}
440

441
impl<E, CR> CodeReadDispatch<E, CR> for CodeReadDispatcher<E, CR>
442
where
443
    E: Endianness,
444
    CR: ReadCodes<E> + ?Sized,
445
{
446
    type Error<CRE> = CRE
447
    where
448
        CRE: Error + Debug + Send + Sync + 'static;
449

450
    #[inline(always)]
451
    fn read_dispatch(&self, reader: &mut CR) -> Result<u64, Self::Error<CR::Error>> {
×
452
        (self.read)(reader).map_err(Into::into)
×
453
    }
454
}
455

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

458
/// Single static dispatch of the write method for a code.
459
/// This is a more efficient way to write codes that are initialized once dynamically,
460
/// and then used multiple times.
461
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
462
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
463
pub struct CodeWriteDispatcher<E, CW>
464
where
465
    E: Endianness,
466
    CW: WriteCodes<E> + ?Sized,
467
{
468
    write: WriteFn<E, CW>,
469
    _marker: PhantomData<E>,
470
}
471

472
impl<E, CW> CodeWriteDispatcher<E, CW>
473
where
474
    E: Endianness,
475
    CW: WriteCodes<E> + ?Sized,
476
{
477
    pub const UNARY: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_unary(value);
×
478
    pub const GAMMA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_gamma(value);
×
479
    pub const DELTA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_delta(value);
×
480
    pub const OMEGA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_omega(value);
×
481
    pub const VBYTE: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_vbyte(value);
×
482
    pub const ZETA2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 2);
×
483
    pub const ZETA3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta3(value);
×
484
    pub const ZETA4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 4);
×
485
    pub const ZETA5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 5);
×
486
    pub const ZETA6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 6);
×
487
    pub const ZETA7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 7);
×
488
    pub const ZETA8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 8);
×
489
    pub const ZETA9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 9);
×
490
    pub const ZETA10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 10);
×
491
    pub const PI2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 2);
×
492
    pub const PI3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 3);
×
493
    pub const PI4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 4);
×
494
    pub const PI5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 5);
×
495
    pub const PI6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 6);
×
496
    pub const PI7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 7);
×
497
    pub const PI8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 8);
×
498
    pub const PI9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 9);
×
499
    pub const PI10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 10);
×
500
    pub const PI_WEB2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 2);
×
501
    pub const PI_WEB3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 3);
×
502
    pub const PI_WEB4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 4);
×
503
    pub const PI_WEB5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 5);
×
504
    pub const PI_WEB6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 6);
×
505
    pub const PI_WEB7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 7);
×
506
    pub const PI_WEB8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 8);
×
507
    pub const PI_WEB9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi_web(value, 9);
×
508
    pub const PI_WEB10: WriteFn<E, CW> =
509
        |writer: &mut CW, value: u64| writer.write_pi_web(value, 10);
×
510
    pub const GOLOMB2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 2);
×
511
    pub const GOLOMB3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 3);
×
512
    pub const GOLOMB4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 4);
×
513
    pub const GOLOMB5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 5);
×
514
    pub const GOLOMB6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 6);
×
515
    pub const GOLOMB7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 7);
×
516
    pub const GOLOMB8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 8);
×
517
    pub const GOLOMB9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 9);
×
518
    pub const GOLOMB10: WriteFn<E, CW> =
519
        |writer: &mut CW, value: u64| writer.write_golomb(value, 10);
×
520
    pub const EXP_GOLOMB2: WriteFn<E, CW> =
521
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 2);
×
522
    pub const EXP_GOLOMB3: WriteFn<E, CW> =
523
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 3);
×
524
    pub const EXP_GOLOMB4: WriteFn<E, CW> =
525
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 4);
×
526
    pub const EXP_GOLOMB5: WriteFn<E, CW> =
527
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 5);
×
528
    pub const EXP_GOLOMB6: WriteFn<E, CW> =
529
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 6);
×
530
    pub const EXP_GOLOMB7: WriteFn<E, CW> =
531
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 7);
×
532
    pub const EXP_GOLOMB8: WriteFn<E, CW> =
533
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 8);
×
534
    pub const EXP_GOLOMB9: WriteFn<E, CW> =
535
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 9);
×
536
    pub const EXP_GOLOMB10: WriteFn<E, CW> =
537
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 10);
×
538
    pub const RICE2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 2);
×
539
    pub const RICE3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 3);
×
540
    pub const RICE4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 4);
×
541
    pub const RICE5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 5);
×
542
    pub const RICE6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 6);
×
543
    pub const RICE7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 7);
×
544
    pub const RICE8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 8);
×
545
    pub const RICE9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 9);
×
546
    pub const RICE10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 10);
×
547

548
    pub fn new(code: Code) -> Result<Self> {
×
549
        let write = match code {
×
550
            Code::Unary => Self::UNARY,
×
551
            Code::Gamma => Self::GAMMA,
×
552
            Code::Delta => Self::DELTA,
×
553
            Code::Omega => Self::OMEGA,
×
554
            Code::VByte => Self::VBYTE,
×
555
            Code::Zeta { k: 2 } => Self::ZETA2,
×
556
            Code::Zeta { k: 3 } => Self::ZETA3,
×
557
            Code::Zeta { k: 4 } => Self::ZETA4,
×
558
            Code::Zeta { k: 5 } => Self::ZETA5,
×
559
            Code::Zeta { k: 6 } => Self::ZETA6,
×
560
            Code::Zeta { k: 7 } => Self::ZETA7,
×
561
            Code::Zeta { k: 8 } => Self::ZETA8,
×
562
            Code::Zeta { k: 9 } => Self::ZETA9,
×
563
            Code::Zeta { k: 10 } => Self::ZETA10,
×
564
            Code::Pi { k: 2 } => Self::PI2,
×
565
            Code::Pi { k: 3 } => Self::PI3,
×
566
            Code::Pi { k: 4 } => Self::PI4,
×
567
            Code::Pi { k: 5 } => Self::PI5,
×
568
            Code::Pi { k: 6 } => Self::PI6,
×
569
            Code::Pi { k: 7 } => Self::PI7,
×
570
            Code::Pi { k: 8 } => Self::PI8,
×
571
            Code::Pi { k: 9 } => Self::PI9,
×
572
            Code::Pi { k: 10 } => Self::PI10,
×
573
            Code::PiWeb { k: 2 } => Self::PI_WEB2,
×
574
            Code::PiWeb { k: 3 } => Self::PI_WEB3,
×
575
            Code::PiWeb { k: 4 } => Self::PI_WEB4,
×
576
            Code::PiWeb { k: 5 } => Self::PI_WEB5,
×
577
            Code::PiWeb { k: 6 } => Self::PI_WEB6,
×
578
            Code::PiWeb { k: 7 } => Self::PI_WEB7,
×
579
            Code::PiWeb { k: 8 } => Self::PI_WEB8,
×
580
            Code::PiWeb { k: 9 } => Self::PI_WEB9,
×
581
            Code::PiWeb { k: 10 } => Self::PI_WEB10,
×
582
            Code::Golomb { b: 2 } => Self::GOLOMB2,
×
583
            Code::Golomb { b: 3 } => Self::GOLOMB3,
×
584
            Code::Golomb { b: 4 } => Self::GOLOMB4,
×
585
            Code::Golomb { b: 5 } => Self::GOLOMB5,
×
586
            Code::Golomb { b: 6 } => Self::GOLOMB6,
×
587
            Code::Golomb { b: 7 } => Self::GOLOMB7,
×
588
            Code::Golomb { b: 8 } => Self::GOLOMB8,
×
589
            Code::Golomb { b: 9 } => Self::GOLOMB9,
×
590
            Code::Golomb { b: 10 } => Self::GOLOMB10,
×
591
            Code::ExpGolomb { k: 2 } => Self::EXP_GOLOMB2,
×
592
            Code::ExpGolomb { k: 3 } => Self::EXP_GOLOMB3,
×
593
            Code::ExpGolomb { k: 4 } => Self::EXP_GOLOMB4,
×
594
            Code::ExpGolomb { k: 5 } => Self::EXP_GOLOMB5,
×
595
            Code::ExpGolomb { k: 6 } => Self::EXP_GOLOMB6,
×
596
            Code::ExpGolomb { k: 7 } => Self::EXP_GOLOMB7,
×
597
            Code::ExpGolomb { k: 8 } => Self::EXP_GOLOMB8,
×
598
            Code::ExpGolomb { k: 9 } => Self::EXP_GOLOMB9,
×
599
            Code::ExpGolomb { k: 10 } => Self::EXP_GOLOMB10,
×
600
            Code::Rice { log2_b: 2 } => Self::RICE2,
×
601
            Code::Rice { log2_b: 3 } => Self::RICE3,
×
602
            Code::Rice { log2_b: 4 } => Self::RICE4,
×
603
            Code::Rice { log2_b: 5 } => Self::RICE5,
×
604
            Code::Rice { log2_b: 6 } => Self::RICE6,
×
605
            Code::Rice { log2_b: 7 } => Self::RICE7,
×
606
            Code::Rice { log2_b: 8 } => Self::RICE8,
×
607
            Code::Rice { log2_b: 9 } => Self::RICE9,
×
608
            Code::Rice { log2_b: 10 } => Self::RICE10,
×
609
            _ => anyhow::bail!("Unsupported write dispatch for code {:?}", code),
×
610
        };
611
        Ok(Self {
×
612
            write,
×
613
            _marker: PhantomData,
×
614
        })
615
    }
616
}
617

618
impl<E, CW> CodeWriteDispatch<E, CW> for CodeWriteDispatcher<E, CW>
619
where
620
    E: Endianness,
621
    CW: WriteCodes<E> + ?Sized,
622
{
623
    type Error<CWE> = CWE
624
    where
625
        CWE: Error + Debug + Send + Sync + 'static;
626
    #[inline(always)]
627
    fn write_dispatch(&self, writer: &mut CW, value: u64) -> Result<usize, Self::Error<CW::Error>> {
×
628
        (self.write)(writer, value).map_err(Into::into)
×
629
    }
630
}
631

632
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
633
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
634
/// A zero-sized struct with a const generic parameter that can be used to
635
/// select the code at compile time.
636
pub struct ConstCode<const CODE: usize>;
637

638
/// The constants ot use as generic parameter of the [`ConstCode`] struct.
639
pub mod const_codes {
640
    /// This macro just define a bunch of constants with progressive values.
641
    /// It is used to assign a unique integer to each code.
642
    macro_rules! impl_codes {
643
        ($code:ident, $($tail:ident),*) => {
644
            pub const $code: usize = 0 $( + 1 + (0 * $tail))*;
645
            impl_codes!($($tail),*);
646
        };
647
        ($code:ident) => {
648
            pub const $code: usize = 0;
649
        };
650
    }
651

652
    impl_codes!(
653
        ZETA1,
654
        ZETA2,
655
        ZETA3,
656
        ZETA4,
657
        ZETA5,
658
        ZETA6,
659
        ZETA7,
660
        ZETA8,
661
        ZETA9,
662
        ZETA10,
663
        PI2,
664
        PI3,
665
        PI4,
666
        PI5,
667
        PI6,
668
        PI7,
669
        PI8,
670
        PI9,
671
        PI10,
672
        PI_WEB2,
673
        PI_WEB3,
674
        PI_WEB4,
675
        PI_WEB5,
676
        PI_WEB6,
677
        PI_WEB7,
678
        PI_WEB8,
679
        PI_WEB9,
680
        PI_WEB10,
681
        GOLOMB2,
682
        GOLOMB3,
683
        GOLOMB4,
684
        GOLOMB5,
685
        GOLOMB6,
686
        GOLOMB7,
687
        GOLOMB8,
688
        GOLOMB9,
689
        GOLOMB10,
690
        EXP_GOLOMB2,
691
        EXP_GOLOMB3,
692
        EXP_GOLOMB4,
693
        EXP_GOLOMB5,
694
        EXP_GOLOMB6,
695
        EXP_GOLOMB7,
696
        EXP_GOLOMB8,
697
        EXP_GOLOMB9,
698
        EXP_GOLOMB10,
699
        RICE2,
700
        RICE3,
701
        RICE4,
702
        RICE5,
703
        RICE6,
704
        RICE7,
705
        RICE8,
706
        RICE9,
707
        RICE10,
708
        VBYTE,
709
        OMEGA,
710
        DELTA,
711
        GAMMA,
712
        UNARY
713
    );
714
}
715

716
impl<const CODE: usize> CodeRead for ConstCode<CODE> {
717
    type Error<CRE> = CRE
718
    where
719
        CRE: Error + Debug + Send + Sync + 'static;
720
    fn read<E: Endianness, CR: ReadCodes<E> + ?Sized>(
×
721
        &self,
722
        reader: &mut CR,
723
    ) -> Result<u64, Self::Error<CR::Error>> {
724
        match CODE {
×
725
            const_codes::UNARY => reader.read_unary(),
×
726
            const_codes::GAMMA => reader.read_gamma(),
×
727
            const_codes::DELTA => reader.read_delta(),
×
728
            const_codes::OMEGA => reader.read_omega(),
×
729
            const_codes::VBYTE => reader.read_vbyte(),
×
730
            const_codes::ZETA1 => reader.read_zeta(1),
×
731
            const_codes::ZETA2 => reader.read_zeta(2),
×
732
            const_codes::ZETA3 => reader.read_zeta3(),
×
733
            const_codes::ZETA4 => reader.read_zeta(4),
×
734
            const_codes::ZETA5 => reader.read_zeta(5),
×
735
            const_codes::ZETA6 => reader.read_zeta(6),
×
736
            const_codes::ZETA7 => reader.read_zeta(7),
×
737
            const_codes::ZETA8 => reader.read_zeta(8),
×
738
            const_codes::ZETA9 => reader.read_zeta(9),
×
739
            const_codes::ZETA10 => reader.read_zeta(10),
×
740
            const_codes::PI2 => reader.read_pi(2),
×
741
            const_codes::PI3 => reader.read_pi(3),
×
742
            const_codes::PI4 => reader.read_pi(4),
×
743
            const_codes::PI5 => reader.read_pi(5),
×
744
            const_codes::PI6 => reader.read_pi(6),
×
745
            const_codes::PI7 => reader.read_pi(7),
×
746
            const_codes::PI8 => reader.read_pi(8),
×
747
            const_codes::PI9 => reader.read_pi(9),
×
748
            const_codes::PI10 => reader.read_pi(10),
×
749
            const_codes::PI_WEB2 => reader.read_pi_web(2),
×
750
            const_codes::PI_WEB3 => reader.read_pi_web(3),
×
751
            const_codes::PI_WEB4 => reader.read_pi_web(4),
×
752
            const_codes::PI_WEB5 => reader.read_pi_web(5),
×
753
            const_codes::PI_WEB6 => reader.read_pi_web(6),
×
754
            const_codes::PI_WEB7 => reader.read_pi_web(7),
×
755
            const_codes::PI_WEB8 => reader.read_pi_web(8),
×
756
            const_codes::PI_WEB9 => reader.read_pi_web(9),
×
757
            const_codes::PI_WEB10 => reader.read_pi_web(10),
×
758
            const_codes::GOLOMB2 => reader.read_golomb(2),
×
759
            const_codes::GOLOMB3 => reader.read_golomb(3),
×
760
            const_codes::GOLOMB4 => reader.read_golomb(4),
×
761
            const_codes::GOLOMB5 => reader.read_golomb(5),
×
762
            const_codes::GOLOMB6 => reader.read_golomb(6),
×
763
            const_codes::GOLOMB7 => reader.read_golomb(7),
×
764
            const_codes::GOLOMB8 => reader.read_golomb(8),
×
765
            const_codes::GOLOMB9 => reader.read_golomb(9),
×
766
            const_codes::GOLOMB10 => reader.read_golomb(10),
×
767
            const_codes::EXP_GOLOMB2 => reader.read_exp_golomb(2),
×
768
            const_codes::EXP_GOLOMB3 => reader.read_exp_golomb(3),
×
769
            const_codes::EXP_GOLOMB4 => reader.read_exp_golomb(4),
×
770
            const_codes::EXP_GOLOMB5 => reader.read_exp_golomb(5),
×
771
            const_codes::EXP_GOLOMB6 => reader.read_exp_golomb(6),
×
772
            const_codes::EXP_GOLOMB7 => reader.read_exp_golomb(7),
×
773
            const_codes::EXP_GOLOMB8 => reader.read_exp_golomb(8),
×
774
            const_codes::EXP_GOLOMB9 => reader.read_exp_golomb(9),
×
775
            const_codes::EXP_GOLOMB10 => reader.read_exp_golomb(10),
×
776
            const_codes::RICE2 => reader.read_rice(2),
×
777
            const_codes::RICE3 => reader.read_rice(3),
×
778
            const_codes::RICE4 => reader.read_rice(4),
×
779
            const_codes::RICE5 => reader.read_rice(5),
×
780
            const_codes::RICE6 => reader.read_rice(6),
×
781
            const_codes::RICE7 => reader.read_rice(7),
×
782
            const_codes::RICE8 => reader.read_rice(8),
×
783
            const_codes::RICE9 => reader.read_rice(9),
×
784
            const_codes::RICE10 => reader.read_rice(10),
×
785
            _ => panic!("Unknown code: {}", CODE),
×
786
        }
787
    }
788
}
789

790
impl<E, CR, const CODE: usize> CodeReadDispatch<E, CR> for ConstCode<CODE>
791
where
792
    E: Endianness,
793
    CR: ReadCodes<E> + ?Sized,
794
{
795
    type Error<CRE> = CRE
796
    where
797
        CRE: Error + Debug + Send + Sync + 'static;
798
    #[inline(always)]
799
    fn read_dispatch(&self, reader: &mut CR) -> Result<u64, Self::Error<CR::Error>> {
×
800
        <Self as CodeRead>::read(self, reader)
×
801
    }
802
}
803

804
impl<const CODE: usize> CodeWrite for ConstCode<CODE> {
805
    type Error<CWE> = CWE
806
    where
807
        CWE: Error + Debug + Send + Sync + 'static;
808
    fn write<E: Endianness, CW: WriteCodes<E> + ?Sized>(
×
809
        &self,
810
        writer: &mut CW,
811
        value: u64,
812
    ) -> Result<usize, Self::Error<CW::Error>> {
813
        match CODE {
×
814
            const_codes::UNARY => writer.write_unary(value),
×
815
            const_codes::GAMMA => writer.write_gamma(value),
×
816
            const_codes::DELTA => writer.write_delta(value),
×
817
            const_codes::OMEGA => writer.write_omega(value),
×
818
            const_codes::VBYTE => writer.write_vbyte(value),
×
819
            const_codes::ZETA1 => writer.write_zeta(value, 1),
×
820
            const_codes::ZETA2 => writer.write_zeta(value, 2),
×
821
            const_codes::ZETA3 => writer.write_zeta3(value),
×
822
            const_codes::ZETA4 => writer.write_zeta(value, 4),
×
823
            const_codes::ZETA5 => writer.write_zeta(value, 5),
×
824
            const_codes::ZETA6 => writer.write_zeta(value, 6),
×
825
            const_codes::ZETA7 => writer.write_zeta(value, 7),
×
826
            const_codes::ZETA8 => writer.write_zeta(value, 8),
×
827
            const_codes::ZETA9 => writer.write_zeta(value, 9),
×
828
            const_codes::ZETA10 => writer.write_zeta(value, 10),
×
829
            const_codes::PI2 => writer.write_pi(value, 2),
×
830
            const_codes::PI3 => writer.write_pi(value, 3),
×
831
            const_codes::PI4 => writer.write_pi(value, 4),
×
832
            const_codes::PI5 => writer.write_pi(value, 5),
×
833
            const_codes::PI6 => writer.write_pi(value, 6),
×
834
            const_codes::PI7 => writer.write_pi(value, 7),
×
835
            const_codes::PI8 => writer.write_pi(value, 8),
×
836
            const_codes::PI9 => writer.write_pi(value, 9),
×
837
            const_codes::PI10 => writer.write_pi(value, 10),
×
838
            const_codes::PI_WEB2 => writer.write_pi_web(value, 2),
×
839
            const_codes::PI_WEB3 => writer.write_pi_web(value, 3),
×
840
            const_codes::PI_WEB4 => writer.write_pi_web(value, 4),
×
841
            const_codes::PI_WEB5 => writer.write_pi_web(value, 5),
×
842
            const_codes::PI_WEB6 => writer.write_pi_web(value, 6),
×
843
            const_codes::PI_WEB7 => writer.write_pi_web(value, 7),
×
844
            const_codes::PI_WEB8 => writer.write_pi_web(value, 8),
×
845
            const_codes::PI_WEB9 => writer.write_pi_web(value, 9),
×
846
            const_codes::PI_WEB10 => writer.write_pi_web(value, 10),
×
847
            const_codes::GOLOMB2 => writer.write_golomb(value, 2),
×
848
            const_codes::GOLOMB3 => writer.write_golomb(value, 3),
×
849
            const_codes::GOLOMB4 => writer.write_golomb(value, 4),
×
850
            const_codes::GOLOMB5 => writer.write_golomb(value, 5),
×
851
            const_codes::GOLOMB6 => writer.write_golomb(value, 6),
×
852
            const_codes::GOLOMB7 => writer.write_golomb(value, 7),
×
853
            const_codes::GOLOMB8 => writer.write_golomb(value, 8),
×
854
            const_codes::GOLOMB9 => writer.write_golomb(value, 9),
×
855
            const_codes::GOLOMB10 => writer.write_golomb(value, 10),
×
856
            const_codes::EXP_GOLOMB2 => writer.write_exp_golomb(value, 2),
×
857
            const_codes::EXP_GOLOMB3 => writer.write_exp_golomb(value, 3),
×
858
            const_codes::EXP_GOLOMB4 => writer.write_exp_golomb(value, 4),
×
859
            const_codes::EXP_GOLOMB5 => writer.write_exp_golomb(value, 5),
×
860
            const_codes::EXP_GOLOMB6 => writer.write_exp_golomb(value, 6),
×
861
            const_codes::EXP_GOLOMB7 => writer.write_exp_golomb(value, 7),
×
862
            const_codes::EXP_GOLOMB8 => writer.write_exp_golomb(value, 8),
×
863
            const_codes::EXP_GOLOMB9 => writer.write_exp_golomb(value, 9),
×
864
            const_codes::EXP_GOLOMB10 => writer.write_exp_golomb(value, 10),
×
865
            const_codes::RICE2 => writer.write_rice(value, 2),
×
866
            const_codes::RICE3 => writer.write_rice(value, 3),
×
867
            const_codes::RICE4 => writer.write_rice(value, 4),
×
868
            const_codes::RICE5 => writer.write_rice(value, 5),
×
869
            const_codes::RICE6 => writer.write_rice(value, 6),
×
870
            const_codes::RICE7 => writer.write_rice(value, 7),
×
871
            const_codes::RICE8 => writer.write_rice(value, 8),
×
872
            const_codes::RICE9 => writer.write_rice(value, 9),
×
873
            const_codes::RICE10 => writer.write_rice(value, 10),
×
874
            _ => panic!("Unknown code: {}", CODE),
×
875
        }
876
    }
877
}
878

879
impl<E, CW, const CODE: usize> CodeWriteDispatch<E, CW> for ConstCode<CODE>
880
where
881
    E: Endianness,
882
    CW: WriteCodes<E> + ?Sized,
883
{
884
    type Error<CWE> = CWE
885
    where
886
        CWE: Error + Debug + Send + Sync + 'static;
887
    #[inline(always)]
888
    fn write_dispatch(&self, writer: &mut CW, value: u64) -> Result<usize, Self::Error<CW::Error>> {
×
889
        <Self as CodeWrite>::write(self, writer, value)
×
890
    }
891
}
892

893
impl<const CODE: usize> CodeLen for ConstCode<CODE> {
894
    #[inline]
895
    fn len(&self, value: u64) -> usize {
×
896
        match CODE {
×
897
            const_codes::UNARY => value as usize + 1,
×
898
            const_codes::GAMMA => len_gamma(value),
×
899
            const_codes::DELTA => len_delta(value),
×
900
            const_codes::OMEGA => len_omega(value),
×
901
            const_codes::VBYTE => len_vbyte(value),
×
902
            const_codes::ZETA1 => len_zeta(value, 1),
×
903
            const_codes::ZETA2 => len_zeta(value, 2),
×
904
            const_codes::ZETA3 => len_zeta(value, 3),
×
905
            const_codes::ZETA4 => len_zeta(value, 4),
×
906
            const_codes::ZETA5 => len_zeta(value, 5),
×
907
            const_codes::ZETA6 => len_zeta(value, 6),
×
908
            const_codes::ZETA7 => len_zeta(value, 7),
×
909
            const_codes::ZETA8 => len_zeta(value, 8),
×
910
            const_codes::ZETA9 => len_zeta(value, 9),
×
911
            const_codes::ZETA10 => len_zeta(value, 10),
×
912
            const_codes::PI2 => len_pi(value, 2),
×
913
            const_codes::PI3 => len_pi(value, 3),
×
914
            const_codes::PI4 => len_pi(value, 4),
×
915
            const_codes::PI5 => len_pi(value, 5),
×
916
            const_codes::PI6 => len_pi(value, 6),
×
917
            const_codes::PI7 => len_pi(value, 7),
×
918
            const_codes::PI8 => len_pi(value, 8),
×
919
            const_codes::PI9 => len_pi(value, 9),
×
920
            const_codes::PI10 => len_pi(value, 10),
×
921
            const_codes::PI_WEB2 => len_pi_web(value, 2),
×
922
            const_codes::PI_WEB3 => len_pi_web(value, 3),
×
923
            const_codes::PI_WEB4 => len_pi_web(value, 4),
×
924
            const_codes::PI_WEB5 => len_pi_web(value, 5),
×
925
            const_codes::PI_WEB6 => len_pi_web(value, 6),
×
926
            const_codes::PI_WEB7 => len_pi_web(value, 7),
×
927
            const_codes::PI_WEB8 => len_pi_web(value, 8),
×
928
            const_codes::PI_WEB9 => len_pi_web(value, 9),
×
929
            const_codes::PI_WEB10 => len_pi_web(value, 10),
×
930
            const_codes::GOLOMB2 => len_golomb(value, 2),
×
931
            const_codes::GOLOMB3 => len_golomb(value, 3),
×
932
            const_codes::GOLOMB4 => len_golomb(value, 4),
×
933
            const_codes::GOLOMB5 => len_golomb(value, 5),
×
934
            const_codes::GOLOMB6 => len_golomb(value, 6),
×
935
            const_codes::GOLOMB7 => len_golomb(value, 7),
×
936
            const_codes::GOLOMB8 => len_golomb(value, 8),
×
937
            const_codes::GOLOMB9 => len_golomb(value, 9),
×
938
            const_codes::GOLOMB10 => len_golomb(value, 10),
×
939
            const_codes::EXP_GOLOMB2 => len_exp_golomb(value, 2),
×
940
            const_codes::EXP_GOLOMB3 => len_exp_golomb(value, 3),
×
941
            const_codes::EXP_GOLOMB4 => len_exp_golomb(value, 4),
×
942
            const_codes::EXP_GOLOMB5 => len_exp_golomb(value, 5),
×
943
            const_codes::EXP_GOLOMB6 => len_exp_golomb(value, 6),
×
944
            const_codes::EXP_GOLOMB7 => len_exp_golomb(value, 7),
×
945
            const_codes::EXP_GOLOMB8 => len_exp_golomb(value, 8),
×
946
            const_codes::EXP_GOLOMB9 => len_exp_golomb(value, 9),
×
947
            const_codes::EXP_GOLOMB10 => len_exp_golomb(value, 10),
×
948
            const_codes::RICE2 => len_rice(value, 2),
×
949
            const_codes::RICE3 => len_rice(value, 3),
×
950
            const_codes::RICE4 => len_rice(value, 4),
×
951
            const_codes::RICE5 => len_rice(value, 5),
×
952
            const_codes::RICE6 => len_rice(value, 6),
×
953
            const_codes::RICE7 => len_rice(value, 7),
×
954
            const_codes::RICE8 => len_rice(value, 8),
×
955
            const_codes::RICE9 => len_rice(value, 9),
×
956
            const_codes::RICE10 => len_rice(value, 10),
×
957
            _ => panic!("Unknown code: {}", CODE),
×
958
        }
959
    }
960
}
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