dsi_bitstream/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
16use super::*;
17#[cfg(feature = "mem_dbg")]
18use mem_dbg::{MemDbg, MemSize};
19
20type 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, PartialEq, Eq)]
38#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
39pub 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
42impl<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
49impl<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    /// Return 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,
115            Codes::Zeta { k: 1 } => Self::GAMMA,
116            Codes::Zeta { k: 2 } => Self::ZETA2,
117            Codes::Zeta { k: 3 } => Self::ZETA3,
118            Codes::Zeta { k: 4 } => Self::ZETA4,
119            Codes::Zeta { k: 5 } => Self::ZETA5,
120            Codes::Zeta { k: 6 } => Self::ZETA6,
121            Codes::Zeta { k: 7 } => Self::ZETA7,
122            Codes::Zeta { k: 8 } => Self::ZETA8,
123            Codes::Zeta { k: 9 } => Self::ZETA9,
124            Codes::Zeta { k: 10 } => Self::ZETA10,
125            Codes::Rice { log2_b: 0 } => Self::UNARY,
126            Codes::Rice { log2_b: 1 } => Self::RICE1,
127            Codes::Rice { log2_b: 2 } => Self::RICE2,
128            Codes::Rice { log2_b: 3 } => Self::RICE3,
129            Codes::Rice { log2_b: 4 } => Self::RICE4,
130            Codes::Rice { log2_b: 5 } => Self::RICE5,
131            Codes::Rice { log2_b: 6 } => Self::RICE6,
132            Codes::Rice { log2_b: 7 } => Self::RICE7,
133            Codes::Rice { log2_b: 8 } => Self::RICE8,
134            Codes::Rice { log2_b: 9 } => Self::RICE9,
135            Codes::Rice { log2_b: 10 } => Self::RICE10,
136            Codes::Pi { k: 0 } => Self::GAMMA,
137            Codes::Pi { k: 1 } => Self::PI1,
138            Codes::Pi { k: 2 } => Self::PI2,
139            Codes::Pi { k: 3 } => Self::PI3,
140            Codes::Pi { k: 4 } => Self::PI4,
141            Codes::Pi { k: 5 } => Self::PI5,
142            Codes::Pi { k: 6 } => Self::PI6,
143            Codes::Pi { k: 7 } => Self::PI7,
144            Codes::Pi { k: 8 } => Self::PI8,
145            Codes::Pi { k: 9 } => Self::PI9,
146            Codes::Pi { k: 10 } => Self::PI10,
147            Codes::Golomb { b: 1 } => Self::UNARY,
148            Codes::Golomb { b: 2 } => Self::RICE1,
149            Codes::Golomb { b: 3 } => Self::GOLOMB3,
150            Codes::Golomb { b: 4 } => Self::RICE2,
151            Codes::Golomb { b: 5 } => Self::GOLOMB5,
152            Codes::Golomb { b: 6 } => Self::GOLOMB6,
153            Codes::Golomb { b: 7 } => Self::GOLOMB7,
154            Codes::Golomb { b: 8 } => Self::RICE3,
155            Codes::Golomb { b: 9 } => Self::GOLOMB9,
156            Codes::Golomb { b: 10 } => Self::GOLOMB10,
157            Codes::ExpGolomb { k: 0 } => Self::GAMMA,
158            Codes::ExpGolomb { k: 1 } => Self::EXP_GOLOMB1,
159            Codes::ExpGolomb { k: 2 } => Self::EXP_GOLOMB2,
160            Codes::ExpGolomb { k: 3 } => Self::EXP_GOLOMB3,
161            Codes::ExpGolomb { k: 4 } => Self::EXP_GOLOMB4,
162            Codes::ExpGolomb { k: 5 } => Self::EXP_GOLOMB5,
163            Codes::ExpGolomb { k: 6 } => Self::EXP_GOLOMB6,
164            Codes::ExpGolomb { k: 7 } => Self::EXP_GOLOMB7,
165            Codes::ExpGolomb { k: 8 } => Self::EXP_GOLOMB8,
166            Codes::ExpGolomb { k: 9 } => Self::EXP_GOLOMB9,
167            Codes::ExpGolomb { k: 10 } => Self::EXP_GOLOMB10,
168            _ => anyhow::bail!("Unsupported read dispatch for code {:?}", code),
169        };
170        Ok(Self(read_func))
171    }
172
173    /// Return 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    /// Get the function pointer for the code.
180    #[inline(always)]
181    pub fn get_func(&self) -> ReadFn<E, CR> {
182        self.0
183    }
184}
185
186impl<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
193type 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, PartialEq, Eq)]
211#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
212pub 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
215impl<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
222impl<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    /// Return 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,
299            Codes::Zeta { k: 1 } => Self::GAMMA,
300            Codes::Zeta { k: 2 } => Self::ZETA2,
301            Codes::Zeta { k: 3 } => Self::ZETA3,
302            Codes::Zeta { k: 4 } => Self::ZETA4,
303            Codes::Zeta { k: 5 } => Self::ZETA5,
304            Codes::Zeta { k: 6 } => Self::ZETA6,
305            Codes::Zeta { k: 7 } => Self::ZETA7,
306            Codes::Zeta { k: 8 } => Self::ZETA8,
307            Codes::Zeta { k: 9 } => Self::ZETA9,
308            Codes::Zeta { k: 10 } => Self::ZETA10,
309            Codes::Rice { log2_b: 0 } => Self::UNARY,
310            Codes::Rice { log2_b: 1 } => Self::RICE1,
311            Codes::Rice { log2_b: 2 } => Self::RICE2,
312            Codes::Rice { log2_b: 3 } => Self::RICE3,
313            Codes::Rice { log2_b: 4 } => Self::RICE4,
314            Codes::Rice { log2_b: 5 } => Self::RICE5,
315            Codes::Rice { log2_b: 6 } => Self::RICE6,
316            Codes::Rice { log2_b: 7 } => Self::RICE7,
317            Codes::Rice { log2_b: 8 } => Self::RICE8,
318            Codes::Rice { log2_b: 9 } => Self::RICE9,
319            Codes::Rice { log2_b: 10 } => Self::RICE10,
320            Codes::Pi { k: 0 } => Self::GAMMA,
321            Codes::Pi { k: 1 } => Self::PI1,
322            Codes::Pi { k: 2 } => Self::PI2,
323            Codes::Pi { k: 3 } => Self::PI3,
324            Codes::Pi { k: 4 } => Self::PI4,
325            Codes::Pi { k: 5 } => Self::PI5,
326            Codes::Pi { k: 6 } => Self::PI6,
327            Codes::Pi { k: 7 } => Self::PI7,
328            Codes::Pi { k: 8 } => Self::PI8,
329            Codes::Pi { k: 9 } => Self::PI9,
330            Codes::Pi { k: 10 } => Self::PI10,
331            Codes::Golomb { b: 1 } => Self::UNARY,
332            Codes::Golomb { b: 2 } => Self::RICE1,
333            Codes::Golomb { b: 3 } => Self::GOLOMB3,
334            Codes::Golomb { b: 4 } => Self::RICE2,
335            Codes::Golomb { b: 5 } => Self::GOLOMB5,
336            Codes::Golomb { b: 6 } => Self::GOLOMB6,
337            Codes::Golomb { b: 7 } => Self::GOLOMB7,
338            Codes::Golomb { b: 8 } => Self::RICE3,
339            Codes::Golomb { b: 9 } => Self::GOLOMB9,
340            Codes::Golomb { b: 10 } => Self::GOLOMB10,
341            Codes::ExpGolomb { k: 0 } => Self::GAMMA,
342            Codes::ExpGolomb { k: 1 } => Self::EXP_GOLOMB1,
343            Codes::ExpGolomb { k: 2 } => Self::EXP_GOLOMB2,
344            Codes::ExpGolomb { k: 3 } => Self::EXP_GOLOMB3,
345            Codes::ExpGolomb { k: 4 } => Self::EXP_GOLOMB4,
346            Codes::ExpGolomb { k: 5 } => Self::EXP_GOLOMB5,
347            Codes::ExpGolomb { k: 6 } => Self::EXP_GOLOMB6,
348            Codes::ExpGolomb { k: 7 } => Self::EXP_GOLOMB7,
349            Codes::ExpGolomb { k: 8 } => Self::EXP_GOLOMB8,
350            Codes::ExpGolomb { k: 9 } => Self::EXP_GOLOMB9,
351            Codes::ExpGolomb { k: 10 } => Self::EXP_GOLOMB10,
352            _ => anyhow::bail!("Unsupported write dispatch for code {:?}", code),
353        };
354        Ok(Self(write_func))
355    }
356
357    /// Return 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    /// Get the function pointer for the code.
364    #[inline(always)]
365    pub fn get_func(&self) -> WriteFn<E, CW> {
366        self.0
367    }
368}
369
370impl<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
377type 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, PartialEq, Eq)]
393#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
394pub struct FuncCodeLen(LenFn);
395
396impl 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    /// Return 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,
462            Codes::Zeta { k: 1 } => Self::GAMMA,
463            Codes::Zeta { k: 2 } => Self::ZETA2,
464            Codes::Zeta { k: 3 } => Self::ZETA3,
465            Codes::Zeta { k: 4 } => Self::ZETA4,
466            Codes::Zeta { k: 5 } => Self::ZETA5,
467            Codes::Zeta { k: 6 } => Self::ZETA6,
468            Codes::Zeta { k: 7 } => Self::ZETA7,
469            Codes::Zeta { k: 8 } => Self::ZETA8,
470            Codes::Zeta { k: 9 } => Self::ZETA9,
471            Codes::Zeta { k: 10 } => Self::ZETA10,
472            Codes::Rice { log2_b: 0 } => Self::UNARY,
473            Codes::Rice { log2_b: 1 } => Self::RICE1,
474            Codes::Rice { log2_b: 2 } => Self::RICE2,
475            Codes::Rice { log2_b: 3 } => Self::RICE3,
476            Codes::Rice { log2_b: 4 } => Self::RICE4,
477            Codes::Rice { log2_b: 5 } => Self::RICE5,
478            Codes::Rice { log2_b: 6 } => Self::RICE6,
479            Codes::Rice { log2_b: 7 } => Self::RICE7,
480            Codes::Rice { log2_b: 8 } => Self::RICE8,
481            Codes::Rice { log2_b: 9 } => Self::RICE9,
482            Codes::Rice { log2_b: 10 } => Self::RICE10,
483            Codes::Pi { k: 0 } => Self::GAMMA,
484            Codes::Pi { k: 1 } => Self::PI1,
485            Codes::Pi { k: 2 } => Self::PI2,
486            Codes::Pi { k: 3 } => Self::PI3,
487            Codes::Pi { k: 4 } => Self::PI4,
488            Codes::Pi { k: 5 } => Self::PI5,
489            Codes::Pi { k: 6 } => Self::PI6,
490            Codes::Pi { k: 7 } => Self::PI7,
491            Codes::Pi { k: 8 } => Self::PI8,
492            Codes::Pi { k: 9 } => Self::PI9,
493            Codes::Pi { k: 10 } => Self::PI10,
494            Codes::Golomb { b: 1 } => Self::UNARY,
495            Codes::Golomb { b: 2 } => Self::RICE1,
496            Codes::Golomb { b: 3 } => Self::GOLOMB3,
497            Codes::Golomb { b: 4 } => Self::RICE2,
498            Codes::Golomb { b: 5 } => Self::GOLOMB5,
499            Codes::Golomb { b: 6 } => Self::GOLOMB6,
500            Codes::Golomb { b: 7 } => Self::GOLOMB7,
501            Codes::Golomb { b: 8 } => Self::RICE3,
502            Codes::Golomb { b: 9 } => Self::GOLOMB9,
503            Codes::Golomb { b: 10 } => Self::GOLOMB10,
504            Codes::ExpGolomb { k: 0 } => Self::GAMMA,
505            Codes::ExpGolomb { k: 1 } => Self::EXP_GOLOMB1,
506            Codes::ExpGolomb { k: 2 } => Self::EXP_GOLOMB2,
507            Codes::ExpGolomb { k: 3 } => Self::EXP_GOLOMB3,
508            Codes::ExpGolomb { k: 4 } => Self::EXP_GOLOMB4,
509            Codes::ExpGolomb { k: 5 } => Self::EXP_GOLOMB5,
510            Codes::ExpGolomb { k: 6 } => Self::EXP_GOLOMB6,
511            Codes::ExpGolomb { k: 7 } => Self::EXP_GOLOMB7,
512            Codes::ExpGolomb { k: 8 } => Self::EXP_GOLOMB8,
513            Codes::ExpGolomb { k: 9 } => Self::EXP_GOLOMB9,
514            Codes::ExpGolomb { k: 10 } => Self::EXP_GOLOMB10,
515            _ => anyhow::bail!("Unsupported read dispatch for code {:?}", code),
516        };
517        Ok(Self(len_func))
518    }
519
520    /// Return 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    /// Get 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.
534impl CodeLen for FuncCodeLen {
535    #[inline(always)]
536    fn len(&self, value: u64) -> usize {
537        (self.0)(value)
538    }
539}