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

vigna / dsi-bitstream-rs / 22257013902

21 Feb 2026 12:42PM UTC coverage: 54.618% (+0.7%) from 53.899%
22257013902

push

github

vigna
Explicit Codes::canonicalize method; many const to code-conversion functions

32 of 48 new or added lines in 5 files covered. (66.67%)

2111 of 3865 relevant lines covered (54.62%)

2728423.2 hits per line

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

0.0
/src/dispatch/static.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
//! Static dispatch for codes.
10
//!
11
//! This kind of dispatch is resolved at compile time against a specific
12
//! [`CodesRead`]. Thus, the code can be inlined and optimized, contrarily to
13
//! the [dynamic case](crate::dispatch::dynamic), but you have less flexibility
14
//! as codes have to be chosen at compile time.
15

16
use super::*;
17

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

21
/// A zero-sized struct with a const generic parameter representing a code using
22
/// the values exported by the [`code_consts`] module.
23
///
24
/// Methods for all traits are implemented for this struct using a match on the
25
/// value of the const type parameter. Since the parameter is a constant, the
26
/// match is resolved at compile time, so there will be no runtime overhead.
27
///
28
/// If the value is not among those defined in the [`code_consts`] module, the
29
/// methods will panic.
30
///
31
/// See the [module documentation](crate::dispatch) for more information.
32
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
34
pub struct ConstCode<const CODE: usize>;
35

36
impl<const CODE: usize> ConstCode<CODE> {
37
    /// Delegates the read method to the [`DynamicCodeRead`] implementation.
38
    ///
39
    /// This inherent method is provided to reduce ambiguity in method
40
    /// resolution.
41
    #[inline(always)]
42
    pub fn read<E: Endianness, CR: CodesRead<E> + ?Sized>(
×
43
        &self,
44
        reader: &mut CR,
45
    ) -> Result<u64, CR::Error> {
46
        DynamicCodeRead::read(self, reader)
×
47
    }
48

49
    /// Delegates to the [`DynamicCodeWrite`] implementation.
50
    ///
51
    /// This inherent method is provided to reduce ambiguity in method
52
    /// resolution.
53
    #[inline(always)]
54
    pub fn write<E: Endianness, CW: CodesWrite<E> + ?Sized>(
×
55
        &self,
56
        writer: &mut CW,
57
        value: u64,
58
    ) -> Result<usize, CW::Error> {
59
        DynamicCodeWrite::write(self, writer, value)
×
60
    }
61
}
62

63
/// The constants to use as generic parameter for the [`ConstCode`] struct.
64
///
65
/// Aliases for equivalent codes (e.g., [`ZETA1`](self::code_consts::ZETA1),
66
/// [`RICE0`](self::code_consts::RICE0)) are derived from
67
/// [`Codes::canonicalize`] via [`Codes::to_code_const`], so they
68
/// are guaranteed to be consistent.
69
pub mod code_consts {
70
    use super::Codes;
71

72
    /// Unwraps a [`Codes::to_code_const`] result at compile
73
    /// time.
NEW
74
    const fn canonical(code: Codes) -> usize {
×
NEW
75
        match code.to_code_const() {
×
NEW
76
            Ok(v) => v,
×
NEW
77
            Err(_) => panic!("unsupported canonical code"),
×
78
        }
79
    }
80

81
    pub const UNARY: usize = 0;
82
    pub const GAMMA: usize = 1;
83
    pub const DELTA: usize = 2;
84
    pub const OMEGA: usize = 3;
85
    pub const VBYTE_BE: usize = 4;
86
    pub const VBYTE_LE: usize = 5;
87
    pub const ZETA1: usize = canonical(Codes::Zeta(1));
88
    pub const ZETA2: usize = 6;
89
    pub const ZETA3: usize = 7;
90
    pub const ZETA4: usize = 8;
91
    pub const ZETA5: usize = 9;
92
    pub const ZETA6: usize = 10;
93
    pub const ZETA7: usize = 11;
94
    pub const ZETA8: usize = 12;
95
    pub const ZETA9: usize = 13;
96
    pub const ZETA10: usize = 14;
97
    pub const RICE0: usize = canonical(Codes::Rice(0));
98
    pub const RICE1: usize = 15;
99
    pub const RICE2: usize = 16;
100
    pub const RICE3: usize = 17;
101
    pub const RICE4: usize = 18;
102
    pub const RICE5: usize = 19;
103
    pub const RICE6: usize = 20;
104
    pub const RICE7: usize = 21;
105
    pub const RICE8: usize = 22;
106
    pub const RICE9: usize = 23;
107
    pub const RICE10: usize = 24;
108
    pub const PI0: usize = canonical(Codes::Pi(0));
109
    pub const PI1: usize = 25;
110
    pub const PI2: usize = 26;
111
    pub const PI3: usize = 27;
112
    pub const PI4: usize = 28;
113
    pub const PI5: usize = 29;
114
    pub const PI6: usize = 30;
115
    pub const PI7: usize = 31;
116
    pub const PI8: usize = 32;
117
    pub const PI9: usize = 33;
118
    pub const PI10: usize = 34;
119
    pub const GOLOMB1: usize = canonical(Codes::Golomb(1));
120
    pub const GOLOMB2: usize = canonical(Codes::Golomb(2));
121
    pub const GOLOMB3: usize = 35;
122
    pub const GOLOMB4: usize = canonical(Codes::Golomb(4));
123
    pub const GOLOMB5: usize = 36;
124
    pub const GOLOMB6: usize = 37;
125
    pub const GOLOMB7: usize = 38;
126
    pub const GOLOMB8: usize = canonical(Codes::Golomb(8));
127
    pub const GOLOMB9: usize = 39;
128
    pub const GOLOMB10: usize = 40;
129
    pub const EXP_GOLOMB0: usize = canonical(Codes::ExpGolomb(0));
130
    pub const EXP_GOLOMB1: usize = 41;
131
    pub const EXP_GOLOMB2: usize = 42;
132
    pub const EXP_GOLOMB3: usize = 43;
133
    pub const EXP_GOLOMB4: usize = 44;
134
    pub const EXP_GOLOMB5: usize = 45;
135
    pub const EXP_GOLOMB6: usize = 46;
136
    pub const EXP_GOLOMB7: usize = 47;
137
    pub const EXP_GOLOMB8: usize = 48;
138
    pub const EXP_GOLOMB9: usize = 49;
139
    pub const EXP_GOLOMB10: usize = 50;
140
}
141

142
impl<const CODE: usize> DynamicCodeRead for ConstCode<CODE> {
143
    fn read<E: Endianness, CR: CodesRead<E> + ?Sized>(
×
144
        &self,
145
        reader: &mut CR,
146
    ) -> Result<u64, CR::Error> {
147
        match CODE {
×
148
            code_consts::UNARY => reader.read_unary(),
×
149
            code_consts::GAMMA => reader.read_gamma(),
×
150
            code_consts::DELTA => reader.read_delta(),
×
151
            code_consts::OMEGA => reader.read_omega(),
×
152
            code_consts::VBYTE_BE => reader.read_vbyte_be(),
×
153
            code_consts::VBYTE_LE => reader.read_vbyte_le(),
×
154
            code_consts::ZETA2 => reader.read_zeta(2),
×
155
            code_consts::ZETA3 => reader.read_zeta3(),
×
156
            code_consts::ZETA4 => reader.read_zeta(4),
×
157
            code_consts::ZETA5 => reader.read_zeta(5),
×
158
            code_consts::ZETA6 => reader.read_zeta(6),
×
159
            code_consts::ZETA7 => reader.read_zeta(7),
×
160
            code_consts::ZETA8 => reader.read_zeta(8),
×
161
            code_consts::ZETA9 => reader.read_zeta(9),
×
162
            code_consts::ZETA10 => reader.read_zeta(10),
×
163
            code_consts::RICE1 => reader.read_rice(1),
×
164
            code_consts::RICE2 => reader.read_rice(2),
×
165
            code_consts::RICE3 => reader.read_rice(3),
×
166
            code_consts::RICE4 => reader.read_rice(4),
×
167
            code_consts::RICE5 => reader.read_rice(5),
×
168
            code_consts::RICE6 => reader.read_rice(6),
×
169
            code_consts::RICE7 => reader.read_rice(7),
×
170
            code_consts::RICE8 => reader.read_rice(8),
×
171
            code_consts::RICE9 => reader.read_rice(9),
×
172
            code_consts::RICE10 => reader.read_rice(10),
×
173
            code_consts::PI1 => reader.read_pi(1),
×
174
            code_consts::PI2 => reader.read_pi2(),
×
175
            code_consts::PI3 => reader.read_pi(3),
×
176
            code_consts::PI4 => reader.read_pi(4),
×
177
            code_consts::PI5 => reader.read_pi(5),
×
178
            code_consts::PI6 => reader.read_pi(6),
×
179
            code_consts::PI7 => reader.read_pi(7),
×
180
            code_consts::PI8 => reader.read_pi(8),
×
181
            code_consts::PI9 => reader.read_pi(9),
×
182
            code_consts::PI10 => reader.read_pi(10),
×
183
            code_consts::GOLOMB3 => reader.read_golomb(3),
×
184
            code_consts::GOLOMB5 => reader.read_golomb(5),
×
185
            code_consts::GOLOMB6 => reader.read_golomb(6),
×
186
            code_consts::GOLOMB7 => reader.read_golomb(7),
×
187
            code_consts::GOLOMB9 => reader.read_golomb(9),
×
188
            code_consts::GOLOMB10 => reader.read_golomb(10),
×
189
            code_consts::EXP_GOLOMB1 => reader.read_exp_golomb(1),
×
190
            code_consts::EXP_GOLOMB2 => reader.read_exp_golomb(2),
×
191
            code_consts::EXP_GOLOMB3 => reader.read_exp_golomb(3),
×
192
            code_consts::EXP_GOLOMB4 => reader.read_exp_golomb(4),
×
193
            code_consts::EXP_GOLOMB5 => reader.read_exp_golomb(5),
×
194
            code_consts::EXP_GOLOMB6 => reader.read_exp_golomb(6),
×
195
            code_consts::EXP_GOLOMB7 => reader.read_exp_golomb(7),
×
196
            code_consts::EXP_GOLOMB8 => reader.read_exp_golomb(8),
×
197
            code_consts::EXP_GOLOMB9 => reader.read_exp_golomb(9),
×
198
            code_consts::EXP_GOLOMB10 => reader.read_exp_golomb(10),
×
199
            _ => panic!("Unknown code index: {}", CODE),
×
200
        }
201
    }
202
}
203

204
impl<const CODE: usize> DynamicCodeWrite for ConstCode<CODE> {
205
    fn write<E: Endianness, CW: CodesWrite<E> + ?Sized>(
×
206
        &self,
207
        writer: &mut CW,
208
        value: u64,
209
    ) -> Result<usize, CW::Error> {
210
        match CODE {
×
211
            code_consts::UNARY => writer.write_unary(value),
×
212
            code_consts::GAMMA => writer.write_gamma(value),
×
213
            code_consts::DELTA => writer.write_delta(value),
×
214
            code_consts::OMEGA => writer.write_omega(value),
×
215
            code_consts::VBYTE_BE => writer.write_vbyte_be(value),
×
216
            code_consts::VBYTE_LE => writer.write_vbyte_le(value),
×
217
            code_consts::ZETA2 => writer.write_zeta(value, 2),
×
218
            code_consts::ZETA3 => writer.write_zeta3(value),
×
219
            code_consts::ZETA4 => writer.write_zeta(value, 4),
×
220
            code_consts::ZETA5 => writer.write_zeta(value, 5),
×
221
            code_consts::ZETA6 => writer.write_zeta(value, 6),
×
222
            code_consts::ZETA7 => writer.write_zeta(value, 7),
×
223
            code_consts::ZETA8 => writer.write_zeta(value, 8),
×
224
            code_consts::ZETA9 => writer.write_zeta(value, 9),
×
225
            code_consts::ZETA10 => writer.write_zeta(value, 10),
×
226
            code_consts::RICE1 => writer.write_rice(value, 1),
×
227
            code_consts::RICE2 => writer.write_rice(value, 2),
×
228
            code_consts::RICE3 => writer.write_rice(value, 3),
×
229
            code_consts::RICE4 => writer.write_rice(value, 4),
×
230
            code_consts::RICE5 => writer.write_rice(value, 5),
×
231
            code_consts::RICE6 => writer.write_rice(value, 6),
×
232
            code_consts::RICE7 => writer.write_rice(value, 7),
×
233
            code_consts::RICE8 => writer.write_rice(value, 8),
×
234
            code_consts::RICE9 => writer.write_rice(value, 9),
×
235
            code_consts::RICE10 => writer.write_rice(value, 10),
×
236
            code_consts::PI1 => writer.write_pi(value, 1),
×
237
            code_consts::PI2 => writer.write_pi2(value),
×
238
            code_consts::PI3 => writer.write_pi(value, 3),
×
239
            code_consts::PI4 => writer.write_pi(value, 4),
×
240
            code_consts::PI5 => writer.write_pi(value, 5),
×
241
            code_consts::PI6 => writer.write_pi(value, 6),
×
242
            code_consts::PI7 => writer.write_pi(value, 7),
×
243
            code_consts::PI8 => writer.write_pi(value, 8),
×
244
            code_consts::PI9 => writer.write_pi(value, 9),
×
245
            code_consts::PI10 => writer.write_pi(value, 10),
×
246
            code_consts::GOLOMB3 => writer.write_golomb(value, 3),
×
247
            code_consts::GOLOMB5 => writer.write_golomb(value, 5),
×
248
            code_consts::GOLOMB6 => writer.write_golomb(value, 6),
×
249
            code_consts::GOLOMB7 => writer.write_golomb(value, 7),
×
250
            code_consts::GOLOMB9 => writer.write_golomb(value, 9),
×
251
            code_consts::GOLOMB10 => writer.write_golomb(value, 10),
×
252
            code_consts::EXP_GOLOMB1 => writer.write_exp_golomb(value, 1),
×
253
            code_consts::EXP_GOLOMB2 => writer.write_exp_golomb(value, 2),
×
254
            code_consts::EXP_GOLOMB3 => writer.write_exp_golomb(value, 3),
×
255
            code_consts::EXP_GOLOMB4 => writer.write_exp_golomb(value, 4),
×
256
            code_consts::EXP_GOLOMB5 => writer.write_exp_golomb(value, 5),
×
257
            code_consts::EXP_GOLOMB6 => writer.write_exp_golomb(value, 6),
×
258
            code_consts::EXP_GOLOMB7 => writer.write_exp_golomb(value, 7),
×
259
            code_consts::EXP_GOLOMB8 => writer.write_exp_golomb(value, 8),
×
260
            code_consts::EXP_GOLOMB9 => writer.write_exp_golomb(value, 9),
×
261
            code_consts::EXP_GOLOMB10 => writer.write_exp_golomb(value, 10),
×
262
            _ => panic!("Unknown code: {}", CODE),
×
263
        }
264
    }
265
}
266

267
impl<E: Endianness, CR: CodesRead<E> + ?Sized, const CODE: usize> StaticCodeRead<E, CR>
268
    for ConstCode<CODE>
269
{
270
    #[inline(always)]
271
    fn read(&self, reader: &mut CR) -> Result<u64, CR::Error> {
×
272
        <Self as DynamicCodeRead>::read(self, reader)
×
273
    }
274
}
275

276
impl<E: Endianness, CW: CodesWrite<E> + ?Sized, const CODE: usize> StaticCodeWrite<E, CW>
277
    for ConstCode<CODE>
278
{
279
    #[inline(always)]
280
    fn write(&self, writer: &mut CW, value: u64) -> Result<usize, CW::Error> {
×
281
        <Self as DynamicCodeWrite>::write(self, writer, value)
×
282
    }
283
}
284

285
impl<const CODE: usize> CodeLen for ConstCode<CODE> {
286
    #[inline]
287
    fn len(&self, value: u64) -> usize {
×
288
        match CODE {
×
289
            code_consts::UNARY => value as usize + 1,
×
290
            code_consts::GAMMA => len_gamma(value),
×
291
            code_consts::DELTA => len_delta(value),
×
292
            code_consts::OMEGA => len_omega(value),
×
293
            code_consts::VBYTE_BE | code_consts::VBYTE_LE => bit_len_vbyte(value),
×
294
            code_consts::ZETA2 => len_zeta(value, 2),
×
295
            code_consts::ZETA3 => len_zeta(value, 3),
×
296
            code_consts::ZETA4 => len_zeta(value, 4),
×
297
            code_consts::ZETA5 => len_zeta(value, 5),
×
298
            code_consts::ZETA6 => len_zeta(value, 6),
×
299
            code_consts::ZETA7 => len_zeta(value, 7),
×
300
            code_consts::ZETA8 => len_zeta(value, 8),
×
301
            code_consts::ZETA9 => len_zeta(value, 9),
×
302
            code_consts::ZETA10 => len_zeta(value, 10),
×
303
            code_consts::RICE1 => len_rice(value, 1),
×
304
            code_consts::RICE2 => len_rice(value, 2),
×
305
            code_consts::RICE3 => len_rice(value, 3),
×
306
            code_consts::RICE4 => len_rice(value, 4),
×
307
            code_consts::RICE5 => len_rice(value, 5),
×
308
            code_consts::RICE6 => len_rice(value, 6),
×
309
            code_consts::RICE7 => len_rice(value, 7),
×
310
            code_consts::RICE8 => len_rice(value, 8),
×
311
            code_consts::RICE9 => len_rice(value, 9),
×
312
            code_consts::RICE10 => len_rice(value, 10),
×
313
            code_consts::PI1 => len_pi(value, 1),
×
314
            code_consts::PI2 => len_pi(value, 2),
×
315
            code_consts::PI3 => len_pi(value, 3),
×
316
            code_consts::PI4 => len_pi(value, 4),
×
317
            code_consts::PI5 => len_pi(value, 5),
×
318
            code_consts::PI6 => len_pi(value, 6),
×
319
            code_consts::PI7 => len_pi(value, 7),
×
320
            code_consts::PI8 => len_pi(value, 8),
×
321
            code_consts::PI9 => len_pi(value, 9),
×
322
            code_consts::PI10 => len_pi(value, 10),
×
323
            code_consts::GOLOMB3 => len_golomb(value, 3),
×
324
            code_consts::GOLOMB5 => len_golomb(value, 5),
×
325
            code_consts::GOLOMB6 => len_golomb(value, 6),
×
326
            code_consts::GOLOMB7 => len_golomb(value, 7),
×
327
            code_consts::GOLOMB9 => len_golomb(value, 9),
×
328
            code_consts::GOLOMB10 => len_golomb(value, 10),
×
329
            code_consts::EXP_GOLOMB1 => len_exp_golomb(value, 1),
×
330
            code_consts::EXP_GOLOMB2 => len_exp_golomb(value, 2),
×
331
            code_consts::EXP_GOLOMB3 => len_exp_golomb(value, 3),
×
332
            code_consts::EXP_GOLOMB4 => len_exp_golomb(value, 4),
×
333
            code_consts::EXP_GOLOMB5 => len_exp_golomb(value, 5),
×
334
            code_consts::EXP_GOLOMB6 => len_exp_golomb(value, 6),
×
335
            code_consts::EXP_GOLOMB7 => len_exp_golomb(value, 7),
×
336
            code_consts::EXP_GOLOMB8 => len_exp_golomb(value, 8),
×
337
            code_consts::EXP_GOLOMB9 => len_exp_golomb(value, 9),
×
338
            code_consts::EXP_GOLOMB10 => len_exp_golomb(value, 10),
×
339
            _ => panic!("Unknown code: {}", CODE),
×
340
        }
341
    }
342
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc