dsi_bitstream/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
16use super::*;
17
18#[cfg(feature = "mem_dbg")]
19use mem_dbg::{MemDbg, MemSize};
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
23/// A zero-sized struct with a const generic parameter representing a code using
24/// the values exported by the [`code_consts`] module.
25///
26/// Methods for all traits are implemented for this struct using a match on the
27/// value of the const type parameter. Since the parameter is a constant, the
28/// match is resolved at compile time, so there will be no runtime overhead.
29///
30/// If the value is not among those defined in the [`code_consts`] module, the
31/// methods will panic.
32///
33/// See the [module documentation](crate::dispatch) for more information.
34pub struct ConstCode<const CODE: usize>;
35
36impl<const CODE: usize> ConstCode<CODE> {
37    /// Delegate 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    /// Delegate 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.
64pub mod code_consts {
65    pub const UNARY: usize = 0;
66    pub const GAMMA: usize = 1;
67    pub const DELTA: usize = 2;
68    pub const OMEGA: usize = 3;
69    pub const VBYTE_BE: usize = 4;
70    pub const VBYTE_LE: usize = 5;
71    pub const ZETA1: usize = GAMMA;
72    pub const ZETA2: usize = 6;
73    pub const ZETA3: usize = 7;
74    pub const ZETA4: usize = 8;
75    pub const ZETA5: usize = 9;
76    pub const ZETA6: usize = 10;
77    pub const ZETA7: usize = 11;
78    pub const ZETA8: usize = 12;
79    pub const ZETA9: usize = 13;
80    pub const ZETA10: usize = 14;
81    pub const RICE0: usize = UNARY;
82    pub const RICE1: usize = 15;
83    pub const RICE2: usize = 16;
84    pub const RICE3: usize = 17;
85    pub const RICE4: usize = 18;
86    pub const RICE5: usize = 19;
87    pub const RICE6: usize = 20;
88    pub const RICE7: usize = 21;
89    pub const RICE8: usize = 22;
90    pub const RICE9: usize = 23;
91    pub const RICE10: usize = 24;
92    pub const PI0: usize = GAMMA;
93    pub const PI1: usize = 25;
94    pub const PI2: usize = 26;
95    pub const PI3: usize = 27;
96    pub const PI4: usize = 28;
97    pub const PI5: usize = 29;
98    pub const PI6: usize = 30;
99    pub const PI7: usize = 31;
100    pub const PI8: usize = 32;
101    pub const PI9: usize = 33;
102    pub const PI10: usize = 34;
103    pub const GOLOMB1: usize = UNARY;
104    pub const GOLOMB2: usize = RICE1;
105    pub const GOLOMB3: usize = 35;
106    pub const GOLOMB4: usize = RICE2;
107    pub const GOLOMB5: usize = 36;
108    pub const GOLOMB6: usize = 37;
109    pub const GOLOMB7: usize = 38;
110    pub const GOLOMB8: usize = RICE3;
111    pub const GOLOMB9: usize = 39;
112    pub const GOLOMB10: usize = 40;
113    pub const EXP_GOLOMB0: usize = GAMMA;
114    pub const EXP_GOLOMB1: usize = 41;
115    pub const EXP_GOLOMB2: usize = 42;
116    pub const EXP_GOLOMB3: usize = 43;
117    pub const EXP_GOLOMB4: usize = 44;
118    pub const EXP_GOLOMB5: usize = 45;
119    pub const EXP_GOLOMB6: usize = 46;
120    pub const EXP_GOLOMB7: usize = 47;
121    pub const EXP_GOLOMB8: usize = 48;
122    pub const EXP_GOLOMB9: usize = 49;
123    pub const EXP_GOLOMB10: usize = 50;
124}
125
126impl<const CODE: usize> DynamicCodeRead for ConstCode<CODE> {
127    fn read<E: Endianness, CR: CodesRead<E> + ?Sized>(
128        &self,
129        reader: &mut CR,
130    ) -> Result<u64, CR::Error> {
131        match CODE {
132            code_consts::UNARY => reader.read_unary(),
133            code_consts::GAMMA => reader.read_gamma(),
134            code_consts::DELTA => reader.read_delta(),
135            code_consts::OMEGA => reader.read_omega(),
136            code_consts::VBYTE_BE => reader.read_vbyte_be(),
137            code_consts::VBYTE_LE => reader.read_vbyte_le(),
138            code_consts::ZETA2 => reader.read_zeta(2),
139            code_consts::ZETA3 => reader.read_zeta3(),
140            code_consts::ZETA4 => reader.read_zeta(4),
141            code_consts::ZETA5 => reader.read_zeta(5),
142            code_consts::ZETA6 => reader.read_zeta(6),
143            code_consts::ZETA7 => reader.read_zeta(7),
144            code_consts::ZETA8 => reader.read_zeta(8),
145            code_consts::ZETA9 => reader.read_zeta(9),
146            code_consts::ZETA10 => reader.read_zeta(10),
147            code_consts::RICE1 => reader.read_rice(1),
148            code_consts::RICE2 => reader.read_rice(2),
149            code_consts::RICE3 => reader.read_rice(3),
150            code_consts::RICE4 => reader.read_rice(4),
151            code_consts::RICE5 => reader.read_rice(5),
152            code_consts::RICE6 => reader.read_rice(6),
153            code_consts::RICE7 => reader.read_rice(7),
154            code_consts::RICE8 => reader.read_rice(8),
155            code_consts::RICE9 => reader.read_rice(9),
156            code_consts::RICE10 => reader.read_rice(10),
157            code_consts::PI1 => reader.read_pi(1),
158            code_consts::PI2 => reader.read_pi(2),
159            code_consts::PI3 => reader.read_pi(3),
160            code_consts::PI4 => reader.read_pi(4),
161            code_consts::PI5 => reader.read_pi(5),
162            code_consts::PI6 => reader.read_pi(6),
163            code_consts::PI7 => reader.read_pi(7),
164            code_consts::PI8 => reader.read_pi(8),
165            code_consts::PI9 => reader.read_pi(9),
166            code_consts::PI10 => reader.read_pi(10),
167            code_consts::GOLOMB3 => reader.read_golomb(3),
168            code_consts::GOLOMB5 => reader.read_golomb(5),
169            code_consts::GOLOMB6 => reader.read_golomb(6),
170            code_consts::GOLOMB7 => reader.read_golomb(7),
171            code_consts::GOLOMB9 => reader.read_golomb(9),
172            code_consts::GOLOMB10 => reader.read_golomb(10),
173            code_consts::EXP_GOLOMB1 => reader.read_exp_golomb(1),
174            code_consts::EXP_GOLOMB2 => reader.read_exp_golomb(2),
175            code_consts::EXP_GOLOMB3 => reader.read_exp_golomb(3),
176            code_consts::EXP_GOLOMB4 => reader.read_exp_golomb(4),
177            code_consts::EXP_GOLOMB5 => reader.read_exp_golomb(5),
178            code_consts::EXP_GOLOMB6 => reader.read_exp_golomb(6),
179            code_consts::EXP_GOLOMB7 => reader.read_exp_golomb(7),
180            code_consts::EXP_GOLOMB8 => reader.read_exp_golomb(8),
181            code_consts::EXP_GOLOMB9 => reader.read_exp_golomb(9),
182            code_consts::EXP_GOLOMB10 => reader.read_exp_golomb(10),
183            _ => panic!("Unknown code index: {}", CODE),
184        }
185    }
186}
187
188impl<const CODE: usize> DynamicCodeWrite for ConstCode<CODE> {
189    fn write<E: Endianness, CW: CodesWrite<E> + ?Sized>(
190        &self,
191        writer: &mut CW,
192        value: u64,
193    ) -> Result<usize, CW::Error> {
194        match CODE {
195            code_consts::UNARY => writer.write_unary(value),
196            code_consts::GAMMA => writer.write_gamma(value),
197            code_consts::DELTA => writer.write_delta(value),
198            code_consts::OMEGA => writer.write_omega(value),
199            code_consts::VBYTE_BE => writer.write_vbyte_be(value),
200            code_consts::VBYTE_LE => writer.write_vbyte_le(value),
201            code_consts::ZETA2 => writer.write_zeta(value, 2),
202            code_consts::ZETA3 => writer.write_zeta3(value),
203            code_consts::ZETA4 => writer.write_zeta(value, 4),
204            code_consts::ZETA5 => writer.write_zeta(value, 5),
205            code_consts::ZETA6 => writer.write_zeta(value, 6),
206            code_consts::ZETA7 => writer.write_zeta(value, 7),
207            code_consts::ZETA8 => writer.write_zeta(value, 8),
208            code_consts::ZETA9 => writer.write_zeta(value, 9),
209            code_consts::ZETA10 => writer.write_zeta(value, 10),
210            code_consts::RICE1 => writer.write_rice(value, 1),
211            code_consts::RICE2 => writer.write_rice(value, 2),
212            code_consts::RICE3 => writer.write_rice(value, 3),
213            code_consts::RICE4 => writer.write_rice(value, 4),
214            code_consts::RICE5 => writer.write_rice(value, 5),
215            code_consts::RICE6 => writer.write_rice(value, 6),
216            code_consts::RICE7 => writer.write_rice(value, 7),
217            code_consts::RICE8 => writer.write_rice(value, 8),
218            code_consts::RICE9 => writer.write_rice(value, 9),
219            code_consts::RICE10 => writer.write_rice(value, 10),
220            code_consts::PI1 => writer.write_pi(value, 2),
221            code_consts::PI2 => writer.write_pi(value, 2),
222            code_consts::PI3 => writer.write_pi(value, 3),
223            code_consts::PI4 => writer.write_pi(value, 4),
224            code_consts::PI5 => writer.write_pi(value, 5),
225            code_consts::PI6 => writer.write_pi(value, 6),
226            code_consts::PI7 => writer.write_pi(value, 7),
227            code_consts::PI8 => writer.write_pi(value, 8),
228            code_consts::PI9 => writer.write_pi(value, 9),
229            code_consts::PI10 => writer.write_pi(value, 10),
230            code_consts::GOLOMB3 => writer.write_golomb(value, 3),
231            code_consts::GOLOMB5 => writer.write_golomb(value, 5),
232            code_consts::GOLOMB6 => writer.write_golomb(value, 6),
233            code_consts::GOLOMB7 => writer.write_golomb(value, 7),
234            code_consts::GOLOMB9 => writer.write_golomb(value, 9),
235            code_consts::GOLOMB10 => writer.write_golomb(value, 10),
236            code_consts::EXP_GOLOMB1 => writer.write_exp_golomb(value, 1),
237            code_consts::EXP_GOLOMB2 => writer.write_exp_golomb(value, 2),
238            code_consts::EXP_GOLOMB3 => writer.write_exp_golomb(value, 3),
239            code_consts::EXP_GOLOMB4 => writer.write_exp_golomb(value, 4),
240            code_consts::EXP_GOLOMB5 => writer.write_exp_golomb(value, 5),
241            code_consts::EXP_GOLOMB6 => writer.write_exp_golomb(value, 6),
242            code_consts::EXP_GOLOMB7 => writer.write_exp_golomb(value, 7),
243            code_consts::EXP_GOLOMB8 => writer.write_exp_golomb(value, 8),
244            code_consts::EXP_GOLOMB9 => writer.write_exp_golomb(value, 9),
245            code_consts::EXP_GOLOMB10 => writer.write_exp_golomb(value, 10),
246            _ => panic!("Unknown code: {}", CODE),
247        }
248    }
249}
250
251impl<E: Endianness, CR: CodesRead<E> + ?Sized, const CODE: usize> StaticCodeRead<E, CR>
252    for ConstCode<CODE>
253{
254    #[inline(always)]
255    fn read(&self, reader: &mut CR) -> Result<u64, CR::Error> {
256        <Self as DynamicCodeRead>::read(self, reader)
257    }
258}
259
260impl<E: Endianness, CW: CodesWrite<E> + ?Sized, const CODE: usize> StaticCodeWrite<E, CW>
261    for ConstCode<CODE>
262{
263    #[inline(always)]
264    fn write(&self, writer: &mut CW, value: u64) -> Result<usize, CW::Error> {
265        <Self as DynamicCodeWrite>::write(self, writer, value)
266    }
267}
268
269impl<const CODE: usize> CodeLen for ConstCode<CODE> {
270    #[inline]
271    fn len(&self, value: u64) -> usize {
272        match CODE {
273            code_consts::UNARY => value as usize + 1,
274            code_consts::GAMMA => len_gamma(value),
275            code_consts::DELTA => len_delta(value),
276            code_consts::OMEGA => len_omega(value),
277            code_consts::VBYTE_BE | code_consts::VBYTE_LE => bit_len_vbyte(value),
278            code_consts::ZETA2 => len_zeta(value, 2),
279            code_consts::ZETA3 => len_zeta(value, 3),
280            code_consts::ZETA4 => len_zeta(value, 4),
281            code_consts::ZETA5 => len_zeta(value, 5),
282            code_consts::ZETA6 => len_zeta(value, 6),
283            code_consts::ZETA7 => len_zeta(value, 7),
284            code_consts::ZETA8 => len_zeta(value, 8),
285            code_consts::ZETA9 => len_zeta(value, 9),
286            code_consts::ZETA10 => len_zeta(value, 10),
287            code_consts::RICE1 => len_rice(value, 1),
288            code_consts::RICE2 => len_rice(value, 2),
289            code_consts::RICE3 => len_rice(value, 3),
290            code_consts::RICE4 => len_rice(value, 4),
291            code_consts::RICE5 => len_rice(value, 5),
292            code_consts::RICE6 => len_rice(value, 6),
293            code_consts::RICE7 => len_rice(value, 7),
294            code_consts::RICE8 => len_rice(value, 8),
295            code_consts::RICE9 => len_rice(value, 9),
296            code_consts::RICE10 => len_rice(value, 10),
297            code_consts::PI1 => len_pi(value, 1),
298            code_consts::PI2 => len_pi(value, 2),
299            code_consts::PI3 => len_pi(value, 3),
300            code_consts::PI4 => len_pi(value, 4),
301            code_consts::PI5 => len_pi(value, 5),
302            code_consts::PI6 => len_pi(value, 6),
303            code_consts::PI7 => len_pi(value, 7),
304            code_consts::PI8 => len_pi(value, 8),
305            code_consts::PI9 => len_pi(value, 9),
306            code_consts::PI10 => len_pi(value, 10),
307            code_consts::GOLOMB3 => len_golomb(value, 3),
308            code_consts::GOLOMB5 => len_golomb(value, 5),
309            code_consts::GOLOMB6 => len_golomb(value, 6),
310            code_consts::GOLOMB7 => len_golomb(value, 7),
311            code_consts::GOLOMB9 => len_golomb(value, 9),
312            code_consts::GOLOMB10 => len_golomb(value, 10),
313            code_consts::EXP_GOLOMB1 => len_exp_golomb(value, 1),
314            code_consts::EXP_GOLOMB2 => len_exp_golomb(value, 2),
315            code_consts::EXP_GOLOMB3 => len_exp_golomb(value, 3),
316            code_consts::EXP_GOLOMB4 => len_exp_golomb(value, 4),
317            code_consts::EXP_GOLOMB5 => len_exp_golomb(value, 5),
318            code_consts::EXP_GOLOMB6 => len_exp_golomb(value, 6),
319            code_consts::EXP_GOLOMB7 => len_exp_golomb(value, 7),
320            code_consts::EXP_GOLOMB8 => len_exp_golomb(value, 8),
321            code_consts::EXP_GOLOMB9 => len_exp_golomb(value, 9),
322            code_consts::EXP_GOLOMB10 => len_exp_golomb(value, 10),
323            _ => panic!("Unknown code: {}", CODE),
324        }
325    }
326}