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

vigna / dsi-bitstream-rs / 19989385183

06 Dec 2025 01:47PM UTC coverage: 52.909% (+0.09%) from 52.821%
19989385183

push

github

vigna
Converted code enum variants to tuple types to increase readability

19 of 357 new or added lines in 4 files covered. (5.32%)

9 existing lines in 3 files now uncovered.

1910 of 3610 relevant lines covered (52.91%)

3013506.24 hits per line

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

0.0
/src/dispatch/dynamic.rs
1
/*
2
 * SPDX-FileCopyrightText: 2025 Tommaso Fontana
3
 * SPDX-FileCopyrightText: 2025 Inria
4
 * SPDX-FileCopyrightText: 2025 Sebastiano Vigna
5
 *
6
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
7
 */
8

9
//! Dynamic dispatching for codes based on function pointers.
10
//!
11
//! This kind of dispatch is resolved at runtime, but just once, at construction
12
//! time, against a specific [`CodesRead`]. The code is stored in a function
13
//! pointer, so it cannot be inlined like in the [static
14
//! case](crate::dispatch::static), but the approach is more flexible.
15

16
use super::*;
17
#[cfg(feature = "mem_dbg")]
18
use mem_dbg::{MemDbg, MemSize};
19

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

22
/// A newtype containing a function pointer dispatching the read
23
/// method for a code.
24
///
25
/// This is a more efficient way to pass a [`StaticCodeRead`] to a method, as a
26
/// [`FuncCodeReader`] does not need to do a runtime test to dispatch the
27
/// correct code.
28
///
29
/// Instances can be obtained by calling the [`new`](FuncCodeReader::new) method
30
///  with method with a variant of the [`Codes`] enum, or by calling the
31
/// [`new_with_func`](FuncCodeReader::new_with_func) method with a function
32
/// pointer.
33
///
34
/// Note that since selection of the code happens in the
35
/// [`new`](FuncCodeReader::new) method, it is more efficient to clone a
36
/// [`FuncCodeReader`] than to create a new one.
37
#[derive(Debug, Copy)]
38
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
39
pub struct FuncCodeReader<E: Endianness, CR: CodesRead<E> + ?Sized>(ReadFn<E, CR>);
40

41
/// manually implement Clone to avoid the Clone bound on CR and E
42
impl<E: Endianness, CR: CodesRead<E> + ?Sized> Clone for FuncCodeReader<E, CR> {
43
    #[inline(always)]
44
    fn clone(&self) -> Self {
×
45
        Self(self.0)
×
46
    }
47
}
48

49
impl<E: Endianness, CR: CodesRead<E> + ?Sized> FuncCodeReader<E, CR> {
50
    const UNARY: ReadFn<E, CR> = |reader: &mut CR| reader.read_unary();
×
51
    const GAMMA: ReadFn<E, CR> = |reader: &mut CR| reader.read_gamma();
×
52
    const DELTA: ReadFn<E, CR> = |reader: &mut CR| reader.read_delta();
×
53
    const OMEGA: ReadFn<E, CR> = |reader: &mut CR| reader.read_omega();
×
54
    const VBYTE_BE: ReadFn<E, CR> = |reader: &mut CR| reader.read_vbyte_be();
×
55
    const VBYTE_LE: ReadFn<E, CR> = |reader: &mut CR| reader.read_vbyte_le();
×
56
    const ZETA2: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(2);
×
57
    const ZETA3: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta3();
×
58
    const ZETA4: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(4);
×
59
    const ZETA5: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(5);
×
60
    const ZETA6: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(6);
×
61
    const ZETA7: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(7);
×
62
    const ZETA8: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(8);
×
63
    const ZETA9: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(9);
×
64
    const ZETA10: ReadFn<E, CR> = |reader: &mut CR| reader.read_zeta(10);
×
65
    const RICE1: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(1);
×
66
    const RICE2: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(2);
×
67
    const RICE3: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(3);
×
68
    const RICE4: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(4);
×
69
    const RICE5: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(5);
×
70
    const RICE6: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(6);
×
71
    const RICE7: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(7);
×
72
    const RICE8: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(8);
×
73
    const RICE9: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(9);
×
74
    const RICE10: ReadFn<E, CR> = |reader: &mut CR| reader.read_rice(10);
×
75
    const PI1: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(1);
×
76
    const PI2: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(2);
×
77
    const PI3: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(3);
×
78
    const PI4: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(4);
×
79
    const PI5: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(5);
×
80
    const PI6: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(6);
×
81
    const PI7: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(7);
×
82
    const PI8: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(8);
×
83
    const PI9: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(9);
×
84
    const PI10: ReadFn<E, CR> = |reader: &mut CR| reader.read_pi(10);
×
85
    const GOLOMB3: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(3);
×
86
    const GOLOMB5: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(5);
×
87
    const GOLOMB6: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(6);
×
88
    const GOLOMB7: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(7);
×
89
    const GOLOMB9: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(9);
×
90
    const GOLOMB10: ReadFn<E, CR> = |reader: &mut CR| reader.read_golomb(10);
×
91
    const EXP_GOLOMB1: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(1);
×
92
    const EXP_GOLOMB2: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(2);
×
93
    const EXP_GOLOMB3: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(3);
×
94
    const EXP_GOLOMB4: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(4);
×
95
    const EXP_GOLOMB5: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(5);
×
96
    const EXP_GOLOMB6: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(6);
×
97
    const EXP_GOLOMB7: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(7);
×
98
    const EXP_GOLOMB8: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(8);
×
99
    const EXP_GOLOMB9: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(9);
×
100
    const EXP_GOLOMB10: ReadFn<E, CR> = |reader: &mut CR| reader.read_exp_golomb(10);
×
101
    /// Returns a new [`FuncCodeReader`] for the given code.
102
    ///
103
    /// # Errors
104
    ///
105
    /// The method will return an error if there is no constant
106
    /// for the given code in [`FuncCodeReader`].
107
    pub fn new(code: Codes) -> anyhow::Result<Self> {
×
108
        let read_func = match code {
×
109
            Codes::Unary => Self::UNARY,
×
110
            Codes::Gamma => Self::GAMMA,
×
111
            Codes::Delta => Self::DELTA,
×
112
            Codes::Omega => Self::OMEGA,
×
113
            Codes::VByteBe => Self::VBYTE_BE,
×
114
            Codes::VByteLe => Self::VBYTE_LE,
×
NEW
115
            Codes::Zeta(1) => Self::GAMMA,
×
NEW
116
            Codes::Zeta(2) => Self::ZETA2,
×
NEW
117
            Codes::Zeta(3) => Self::ZETA3,
×
NEW
118
            Codes::Zeta(4) => Self::ZETA4,
×
NEW
119
            Codes::Zeta(5) => Self::ZETA5,
×
NEW
120
            Codes::Zeta(6) => Self::ZETA6,
×
NEW
121
            Codes::Zeta(7) => Self::ZETA7,
×
NEW
122
            Codes::Zeta(8) => Self::ZETA8,
×
NEW
123
            Codes::Zeta(9) => Self::ZETA9,
×
NEW
124
            Codes::Zeta(10) => Self::ZETA10,
×
NEW
125
            Codes::Rice(0) => Self::UNARY,
×
NEW
126
            Codes::Rice(1) => Self::RICE1,
×
NEW
127
            Codes::Rice(2) => Self::RICE2,
×
NEW
128
            Codes::Rice(3) => Self::RICE3,
×
NEW
129
            Codes::Rice(4) => Self::RICE4,
×
NEW
130
            Codes::Rice(5) => Self::RICE5,
×
NEW
131
            Codes::Rice(6) => Self::RICE6,
×
NEW
132
            Codes::Rice(7) => Self::RICE7,
×
NEW
133
            Codes::Rice(8) => Self::RICE8,
×
NEW
134
            Codes::Rice(9) => Self::RICE9,
×
NEW
135
            Codes::Rice(10) => Self::RICE10,
×
NEW
136
            Codes::Pi(0) => Self::GAMMA,
×
NEW
137
            Codes::Pi(1) => Self::PI1,
×
NEW
138
            Codes::Pi(2) => Self::PI2,
×
NEW
139
            Codes::Pi(3) => Self::PI3,
×
NEW
140
            Codes::Pi(4) => Self::PI4,
×
NEW
141
            Codes::Pi(5) => Self::PI5,
×
NEW
142
            Codes::Pi(6) => Self::PI6,
×
NEW
143
            Codes::Pi(7) => Self::PI7,
×
NEW
144
            Codes::Pi(8) => Self::PI8,
×
NEW
145
            Codes::Pi(9) => Self::PI9,
×
NEW
146
            Codes::Pi(10) => Self::PI10,
×
NEW
147
            Codes::Golomb(1) => Self::UNARY,
×
NEW
148
            Codes::Golomb(2) => Self::RICE1,
×
NEW
149
            Codes::Golomb(3) => Self::GOLOMB3,
×
NEW
150
            Codes::Golomb(4) => Self::RICE2,
×
NEW
151
            Codes::Golomb(5) => Self::GOLOMB5,
×
NEW
152
            Codes::Golomb(6) => Self::GOLOMB6,
×
NEW
153
            Codes::Golomb(7) => Self::GOLOMB7,
×
NEW
154
            Codes::Golomb(8) => Self::RICE3,
×
NEW
155
            Codes::Golomb(9) => Self::GOLOMB9,
×
NEW
156
            Codes::Golomb(10) => Self::GOLOMB10,
×
NEW
157
            Codes::ExpGolomb(0) => Self::GAMMA,
×
NEW
158
            Codes::ExpGolomb(1) => Self::EXP_GOLOMB1,
×
NEW
159
            Codes::ExpGolomb(2) => Self::EXP_GOLOMB2,
×
NEW
160
            Codes::ExpGolomb(3) => Self::EXP_GOLOMB3,
×
NEW
161
            Codes::ExpGolomb(4) => Self::EXP_GOLOMB4,
×
NEW
162
            Codes::ExpGolomb(5) => Self::EXP_GOLOMB5,
×
NEW
163
            Codes::ExpGolomb(6) => Self::EXP_GOLOMB6,
×
NEW
164
            Codes::ExpGolomb(7) => Self::EXP_GOLOMB7,
×
NEW
165
            Codes::ExpGolomb(8) => Self::EXP_GOLOMB8,
×
NEW
166
            Codes::ExpGolomb(9) => Self::EXP_GOLOMB9,
×
NEW
167
            Codes::ExpGolomb(10) => Self::EXP_GOLOMB10,
×
UNCOV
168
            _ => anyhow::bail!("Unsupported read dispatch for code {:?}", code),
×
169
        };
170
        Ok(Self(read_func))
×
171
    }
172

173
    /// Returns a new [`FuncCodeReader`] for the given function.
174
    #[inline(always)]
175
    pub fn new_with_func(read_func: ReadFn<E, CR>) -> Self {
×
176
        Self(read_func)
×
177
    }
178

179
    /// Gets the function pointer for the code.
180
    #[inline(always)]
181
    pub fn get_func(&self) -> ReadFn<E, CR> {
×
182
        self.0
×
183
    }
184
}
185

186
impl<E: Endianness, CR: CodesRead<E> + ?Sized> StaticCodeRead<E, CR> for FuncCodeReader<E, CR> {
187
    #[inline(always)]
188
    fn read(&self, reader: &mut CR) -> Result<u64, CR::Error> {
×
189
        (self.0)(reader)
×
190
    }
191
}
192

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

195
/// A newtype containing a function pointer dispatching the write method for a
196
/// code.
197
///
198
/// This is a more efficient way to pass a [`StaticCodeWrite`] to a method, as
199
/// a [`FuncCodeWriter`] does not need to do a runtime test to dispatch the
200
/// correct code.
201
///
202
/// Instances can be obtained by calling the [`new`](FuncCodeWriter::new) method
203
///  with method with a variant of the [`Codes`] enum, or by calling the
204
/// [`new_with_func`](FuncCodeWriter::new_with_func) method with a function
205
/// pointer.
206
///
207
/// Note that since selection of the code happens in the
208
/// [`new`](FuncCodeReader::new) method, it is more efficient to clone a
209
/// [`FuncCodeWriter`] than to create a new one.
210
#[derive(Debug, Copy)]
211
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
212
pub struct FuncCodeWriter<E: Endianness, CW: CodesWrite<E> + ?Sized>(WriteFn<E, CW>);
213

214
/// manually implement Clone to avoid the Clone bound on CR and E
215
impl<E: Endianness, CR: CodesWrite<E> + ?Sized> Clone for FuncCodeWriter<E, CR> {
216
    #[inline(always)]
217
    fn clone(&self) -> Self {
×
218
        Self(self.0)
×
219
    }
220
}
221

222
impl<E: Endianness, CW: CodesWrite<E> + ?Sized> FuncCodeWriter<E, CW> {
223
    const UNARY: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_unary(value);
×
224
    const GAMMA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_gamma(value);
×
225
    const DELTA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_delta(value);
×
226
    const OMEGA: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_omega(value);
×
227
    const VBYTE_BE: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_vbyte_be(value);
×
228
    const VBYTE_LE: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_vbyte_le(value);
×
229
    const ZETA2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 2);
×
230
    const ZETA3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta3(value);
×
231
    const ZETA4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 4);
×
232
    const ZETA5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 5);
×
233
    const ZETA6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 6);
×
234
    const ZETA7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 7);
×
235
    const ZETA8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 8);
×
236
    const ZETA9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 9);
×
237
    const ZETA10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_zeta(value, 10);
×
238
    const RICE1: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 1);
×
239
    const RICE2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 2);
×
240
    const RICE3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 3);
×
241
    const RICE4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 4);
×
242
    const RICE5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 5);
×
243
    const RICE6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 6);
×
244
    const RICE7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 7);
×
245
    const RICE8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 8);
×
246
    const RICE9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 9);
×
247
    const RICE10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_rice(value, 10);
×
248
    const PI1: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 1);
×
249
    const PI2: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 2);
×
250
    const PI3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 3);
×
251
    const PI4: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 4);
×
252
    const PI5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 5);
×
253
    const PI6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 6);
×
254
    const PI7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 7);
×
255
    const PI8: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 8);
×
256
    const PI9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 9);
×
257
    const PI10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_pi(value, 10);
×
258
    const GOLOMB3: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 3);
×
259
    const GOLOMB5: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 5);
×
260
    const GOLOMB6: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 6);
×
261
    const GOLOMB7: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 7);
×
262
    const GOLOMB9: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 9);
×
263
    const GOLOMB10: WriteFn<E, CW> = |writer: &mut CW, value: u64| writer.write_golomb(value, 10);
×
264
    const EXP_GOLOMB1: WriteFn<E, CW> =
265
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 1);
×
266
    const EXP_GOLOMB2: WriteFn<E, CW> =
267
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 2);
×
268
    const EXP_GOLOMB3: WriteFn<E, CW> =
269
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 3);
×
270
    const EXP_GOLOMB4: WriteFn<E, CW> =
271
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 4);
×
272
    const EXP_GOLOMB5: WriteFn<E, CW> =
273
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 5);
×
274
    const EXP_GOLOMB6: WriteFn<E, CW> =
275
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 6);
×
276
    const EXP_GOLOMB7: WriteFn<E, CW> =
277
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 7);
×
278
    const EXP_GOLOMB8: WriteFn<E, CW> =
279
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 8);
×
280
    const EXP_GOLOMB9: WriteFn<E, CW> =
281
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 9);
×
282
    const EXP_GOLOMB10: WriteFn<E, CW> =
283
        |writer: &mut CW, value: u64| writer.write_exp_golomb(value, 10);
×
284

285
    /// Returns a new [`FuncCodeWriter`] for the given code.
286
    ///
287
    /// # Errors
288
    ///
289
    /// The method will return an error if there is no constant
290
    /// for the given code in [`FuncCodeWriter`].
291
    pub fn new(code: Codes) -> anyhow::Result<Self> {
×
292
        let write_func = match code {
×
293
            Codes::Unary => Self::UNARY,
×
294
            Codes::Gamma => Self::GAMMA,
×
295
            Codes::Delta => Self::DELTA,
×
296
            Codes::Omega => Self::OMEGA,
×
297
            Codes::VByteBe => Self::VBYTE_BE,
×
298
            Codes::VByteLe => Self::VBYTE_LE,
×
NEW
299
            Codes::Zeta(1) => Self::GAMMA,
×
NEW
300
            Codes::Zeta(2) => Self::ZETA2,
×
NEW
301
            Codes::Zeta(3) => Self::ZETA3,
×
NEW
302
            Codes::Zeta(4) => Self::ZETA4,
×
NEW
303
            Codes::Zeta(5) => Self::ZETA5,
×
NEW
304
            Codes::Zeta(6) => Self::ZETA6,
×
NEW
305
            Codes::Zeta(7) => Self::ZETA7,
×
NEW
306
            Codes::Zeta(8) => Self::ZETA8,
×
NEW
307
            Codes::Zeta(9) => Self::ZETA9,
×
NEW
308
            Codes::Zeta(10) => Self::ZETA10,
×
NEW
309
            Codes::Rice(0) => Self::UNARY,
×
NEW
310
            Codes::Rice(1) => Self::RICE1,
×
NEW
311
            Codes::Rice(2) => Self::RICE2,
×
NEW
312
            Codes::Rice(3) => Self::RICE3,
×
NEW
313
            Codes::Rice(4) => Self::RICE4,
×
NEW
314
            Codes::Rice(5) => Self::RICE5,
×
NEW
315
            Codes::Rice(6) => Self::RICE6,
×
NEW
316
            Codes::Rice(7) => Self::RICE7,
×
NEW
317
            Codes::Rice(8) => Self::RICE8,
×
NEW
318
            Codes::Rice(9) => Self::RICE9,
×
NEW
319
            Codes::Rice(10) => Self::RICE10,
×
NEW
320
            Codes::Pi(0) => Self::GAMMA,
×
NEW
321
            Codes::Pi(1) => Self::PI1,
×
NEW
322
            Codes::Pi(2) => Self::PI2,
×
NEW
323
            Codes::Pi(3) => Self::PI3,
×
NEW
324
            Codes::Pi(4) => Self::PI4,
×
NEW
325
            Codes::Pi(5) => Self::PI5,
×
NEW
326
            Codes::Pi(6) => Self::PI6,
×
NEW
327
            Codes::Pi(7) => Self::PI7,
×
NEW
328
            Codes::Pi(8) => Self::PI8,
×
NEW
329
            Codes::Pi(9) => Self::PI9,
×
NEW
330
            Codes::Pi(10) => Self::PI10,
×
NEW
331
            Codes::Golomb(1) => Self::UNARY,
×
NEW
332
            Codes::Golomb(2) => Self::RICE1,
×
NEW
333
            Codes::Golomb(3) => Self::GOLOMB3,
×
NEW
334
            Codes::Golomb(4) => Self::RICE2,
×
NEW
335
            Codes::Golomb(5) => Self::GOLOMB5,
×
NEW
336
            Codes::Golomb(6) => Self::GOLOMB6,
×
NEW
337
            Codes::Golomb(7) => Self::GOLOMB7,
×
NEW
338
            Codes::Golomb(8) => Self::RICE3,
×
NEW
339
            Codes::Golomb(9) => Self::GOLOMB9,
×
NEW
340
            Codes::Golomb(10) => Self::GOLOMB10,
×
NEW
341
            Codes::ExpGolomb(0) => Self::GAMMA,
×
NEW
342
            Codes::ExpGolomb(1) => Self::EXP_GOLOMB1,
×
NEW
343
            Codes::ExpGolomb(2) => Self::EXP_GOLOMB2,
×
NEW
344
            Codes::ExpGolomb(3) => Self::EXP_GOLOMB3,
×
NEW
345
            Codes::ExpGolomb(4) => Self::EXP_GOLOMB4,
×
NEW
346
            Codes::ExpGolomb(5) => Self::EXP_GOLOMB5,
×
NEW
347
            Codes::ExpGolomb(6) => Self::EXP_GOLOMB6,
×
NEW
348
            Codes::ExpGolomb(7) => Self::EXP_GOLOMB7,
×
NEW
349
            Codes::ExpGolomb(8) => Self::EXP_GOLOMB8,
×
NEW
350
            Codes::ExpGolomb(9) => Self::EXP_GOLOMB9,
×
NEW
351
            Codes::ExpGolomb(10) => Self::EXP_GOLOMB10,
×
UNCOV
352
            _ => anyhow::bail!("Unsupported write dispatch for code {:?}", code),
×
353
        };
354
        Ok(Self(write_func))
×
355
    }
356

357
    /// Returns a new [`FuncCodeWriter`] for the given function.
358
    #[inline(always)]
359
    pub fn new_with_func(write_func: WriteFn<E, CW>) -> Self {
×
360
        Self(write_func)
×
361
    }
362

363
    /// Gets the function pointer for the code.
364
    #[inline(always)]
365
    pub fn get_func(&self) -> WriteFn<E, CW> {
×
366
        self.0
×
367
    }
368
}
369

370
impl<E: Endianness, CW: CodesWrite<E> + ?Sized> StaticCodeWrite<E, CW> for FuncCodeWriter<E, CW> {
371
    #[inline(always)]
372
    fn write(&self, writer: &mut CW, value: u64) -> Result<usize, CW::Error> {
×
373
        (self.0)(writer, value)
×
374
    }
375
}
376

377
type LenFn = fn(u64) -> usize;
378

379
/// A newtype containing a function pointer dispatching the read method for a
380
/// code.
381
///
382
/// This is a more efficient way to pass a [`StaticCodeRead`] to a method, as
383
/// a [`FuncCodeReader`] does not need to do a runtime test to dispatch the correct
384
/// code.
385
///
386
/// Instances can be obtained by calling the [`new`](FuncCodeReader::new) method with
387
///  method with a variant of the [`Codes`] enum, or by calling the
388
/// [`new_with_func`](FuncCodeReader::new_with_func) method with a function pointer.
389
///
390
/// Note that since selection of the code happens in the [`new`](FuncCodeReader::new)
391
/// method, it is more efficient to clone a [`FuncCodeReader`] than to create a new one.
392
#[derive(Debug, Clone, Copy)]
393
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
394
pub struct FuncCodeLen(LenFn);
395

396
impl FuncCodeLen {
397
    const UNARY: LenFn = |value| value as usize + 1;
×
398
    const GAMMA: LenFn = |value| len_gamma(value);
×
399
    const DELTA: LenFn = |value| len_delta(value);
×
400
    const OMEGA: LenFn = |value| len_omega(value);
×
401
    const VBYTE_BE: LenFn = |value| bit_len_vbyte(value);
×
402
    const VBYTE_LE: LenFn = |value| bit_len_vbyte(value);
×
403
    const ZETA2: LenFn = |value| len_zeta(value, 2);
×
404
    const ZETA3: LenFn = |value| len_zeta(value, 3);
×
405
    const ZETA4: LenFn = |value| len_zeta(value, 4);
×
406
    const ZETA5: LenFn = |value| len_zeta(value, 5);
×
407
    const ZETA6: LenFn = |value| len_zeta(value, 6);
×
408
    const ZETA7: LenFn = |value| len_zeta(value, 7);
×
409
    const ZETA8: LenFn = |value| len_zeta(value, 8);
×
410
    const ZETA9: LenFn = |value| len_zeta(value, 9);
×
411
    const ZETA10: LenFn = |value| len_zeta(value, 10);
×
412
    const RICE1: LenFn = |value| len_rice(value, 1);
×
413
    const RICE2: LenFn = |value| len_rice(value, 2);
×
414
    const RICE3: LenFn = |value| len_rice(value, 3);
×
415
    const RICE4: LenFn = |value| len_rice(value, 4);
×
416
    const RICE5: LenFn = |value| len_rice(value, 5);
×
417
    const RICE6: LenFn = |value| len_rice(value, 6);
×
418
    const RICE7: LenFn = |value| len_rice(value, 7);
×
419
    const RICE8: LenFn = |value| len_rice(value, 8);
×
420
    const RICE9: LenFn = |value| len_rice(value, 9);
×
421
    const RICE10: LenFn = |value| len_rice(value, 10);
×
422
    const PI1: LenFn = |value| len_pi(value, 1);
×
423
    const PI2: LenFn = |value| len_pi(value, 2);
×
424
    const PI3: LenFn = |value| len_pi(value, 3);
×
425
    const PI4: LenFn = |value| len_pi(value, 4);
×
426
    const PI5: LenFn = |value| len_pi(value, 5);
×
427
    const PI6: LenFn = |value| len_pi(value, 6);
×
428
    const PI7: LenFn = |value| len_pi(value, 7);
×
429
    const PI8: LenFn = |value| len_pi(value, 8);
×
430
    const PI9: LenFn = |value| len_pi(value, 9);
×
431
    const PI10: LenFn = |value| len_pi(value, 10);
×
432
    const GOLOMB3: LenFn = |value| len_golomb(value, 3);
×
433
    const GOLOMB5: LenFn = |value| len_golomb(value, 5);
×
434
    const GOLOMB6: LenFn = |value| len_golomb(value, 6);
×
435
    const GOLOMB7: LenFn = |value| len_golomb(value, 7);
×
436
    const GOLOMB9: LenFn = |value| len_golomb(value, 9);
×
437
    const GOLOMB10: LenFn = |value| len_golomb(value, 10);
×
438
    const EXP_GOLOMB1: LenFn = |value| len_exp_golomb(value, 1);
×
439
    const EXP_GOLOMB2: LenFn = |value| len_exp_golomb(value, 2);
×
440
    const EXP_GOLOMB3: LenFn = |value| len_exp_golomb(value, 3);
×
441
    const EXP_GOLOMB4: LenFn = |value| len_exp_golomb(value, 4);
×
442
    const EXP_GOLOMB5: LenFn = |value| len_exp_golomb(value, 5);
×
443
    const EXP_GOLOMB6: LenFn = |value| len_exp_golomb(value, 6);
×
444
    const EXP_GOLOMB7: LenFn = |value| len_exp_golomb(value, 7);
×
445
    const EXP_GOLOMB8: LenFn = |value| len_exp_golomb(value, 8);
×
446
    const EXP_GOLOMB9: LenFn = |value| len_exp_golomb(value, 9);
×
447
    const EXP_GOLOMB10: LenFn = |value| len_exp_golomb(value, 10);
×
448
    /// Returns a new [`FuncCodeLen`] for the given code.
449
    ///
450
    /// # Errors
451
    ///
452
    /// The method will return an error if there is no constant
453
    /// for the given code in [`FuncCodeLen`].
454
    pub fn new(code: Codes) -> anyhow::Result<Self> {
×
455
        let len_func = match code {
×
456
            Codes::Unary => Self::UNARY,
×
457
            Codes::Gamma => Self::GAMMA,
×
458
            Codes::Delta => Self::DELTA,
×
459
            Codes::Omega => Self::OMEGA,
×
460
            Codes::VByteBe => Self::VBYTE_BE,
×
461
            Codes::VByteLe => Self::VBYTE_LE,
×
NEW
462
            Codes::Zeta(1) => Self::GAMMA,
×
NEW
463
            Codes::Zeta(2) => Self::ZETA2,
×
NEW
464
            Codes::Zeta(3) => Self::ZETA3,
×
NEW
465
            Codes::Zeta(4) => Self::ZETA4,
×
NEW
466
            Codes::Zeta(5) => Self::ZETA5,
×
NEW
467
            Codes::Zeta(6) => Self::ZETA6,
×
NEW
468
            Codes::Zeta(7) => Self::ZETA7,
×
NEW
469
            Codes::Zeta(8) => Self::ZETA8,
×
NEW
470
            Codes::Zeta(9) => Self::ZETA9,
×
NEW
471
            Codes::Zeta(10) => Self::ZETA10,
×
NEW
472
            Codes::Rice(0) => Self::UNARY,
×
NEW
473
            Codes::Rice(1) => Self::RICE1,
×
NEW
474
            Codes::Rice(2) => Self::RICE2,
×
NEW
475
            Codes::Rice(3) => Self::RICE3,
×
NEW
476
            Codes::Rice(4) => Self::RICE4,
×
NEW
477
            Codes::Rice(5) => Self::RICE5,
×
NEW
478
            Codes::Rice(6) => Self::RICE6,
×
NEW
479
            Codes::Rice(7) => Self::RICE7,
×
NEW
480
            Codes::Rice(8) => Self::RICE8,
×
NEW
481
            Codes::Rice(9) => Self::RICE9,
×
NEW
482
            Codes::Rice(10) => Self::RICE10,
×
NEW
483
            Codes::Pi(0) => Self::GAMMA,
×
NEW
484
            Codes::Pi(1) => Self::PI1,
×
NEW
485
            Codes::Pi(2) => Self::PI2,
×
NEW
486
            Codes::Pi(3) => Self::PI3,
×
NEW
487
            Codes::Pi(4) => Self::PI4,
×
NEW
488
            Codes::Pi(5) => Self::PI5,
×
NEW
489
            Codes::Pi(6) => Self::PI6,
×
NEW
490
            Codes::Pi(7) => Self::PI7,
×
NEW
491
            Codes::Pi(8) => Self::PI8,
×
NEW
492
            Codes::Pi(9) => Self::PI9,
×
NEW
493
            Codes::Pi(10) => Self::PI10,
×
NEW
494
            Codes::Golomb(1) => Self::UNARY,
×
NEW
495
            Codes::Golomb(2) => Self::RICE1,
×
NEW
496
            Codes::Golomb(3) => Self::GOLOMB3,
×
NEW
497
            Codes::Golomb(4) => Self::RICE2,
×
NEW
498
            Codes::Golomb(5) => Self::GOLOMB5,
×
NEW
499
            Codes::Golomb(6) => Self::GOLOMB6,
×
NEW
500
            Codes::Golomb(7) => Self::GOLOMB7,
×
NEW
501
            Codes::Golomb(8) => Self::RICE3,
×
NEW
502
            Codes::Golomb(9) => Self::GOLOMB9,
×
NEW
503
            Codes::Golomb(10) => Self::GOLOMB10,
×
NEW
504
            Codes::ExpGolomb(0) => Self::GAMMA,
×
NEW
505
            Codes::ExpGolomb(1) => Self::EXP_GOLOMB1,
×
NEW
506
            Codes::ExpGolomb(2) => Self::EXP_GOLOMB2,
×
NEW
507
            Codes::ExpGolomb(3) => Self::EXP_GOLOMB3,
×
NEW
508
            Codes::ExpGolomb(4) => Self::EXP_GOLOMB4,
×
NEW
509
            Codes::ExpGolomb(5) => Self::EXP_GOLOMB5,
×
NEW
510
            Codes::ExpGolomb(6) => Self::EXP_GOLOMB6,
×
NEW
511
            Codes::ExpGolomb(7) => Self::EXP_GOLOMB7,
×
NEW
512
            Codes::ExpGolomb(8) => Self::EXP_GOLOMB8,
×
NEW
513
            Codes::ExpGolomb(9) => Self::EXP_GOLOMB9,
×
NEW
514
            Codes::ExpGolomb(10) => Self::EXP_GOLOMB10,
×
UNCOV
515
            _ => anyhow::bail!("Unsupported read dispatch for code {:?}", code),
×
516
        };
517
        Ok(Self(len_func))
×
518
    }
519

520
    /// Returns a new [`FuncCodeReader`] for the given function.
521
    #[inline(always)]
522
    pub fn new_with_func(len_func: LenFn) -> Self {
×
523
        Self(len_func)
×
524
    }
525
    /// Gets the function pointer for the code.
526
    #[inline(always)]
527
    pub fn get_func(&self) -> LenFn {
×
528
        self.0
×
529
    }
530
}
531

532
/// Here we do not depend on the bitstream, so there is no need for a "static"
533
/// version of the trait.
534
impl CodeLen for FuncCodeLen {
535
    #[inline(always)]
536
    fn len(&self, value: u64) -> usize {
×
537
        (self.0)(value)
×
538
    }
539
}
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