dsi_bitstream/dispatch/
factory.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 factories for readers with a lifetime.
10//!
11//! # Motivation
12//!
13//! [`FuncCodeReader`] already provides dynamic dispatching of read functions,
14//! but in some uses cases the reader has to reference some data (e.g., readers
15//! based on the same memory buffer). In this case, one would need to create a
16//! dispatching function pointer for each code and each reader because the
17//! lifetime of different readers make the function pointers incompatible.
18//!
19//! The trait [`CodesReaderFactory`] solves this problem by providing a way to
20//! create a [`CodesRead`] with a lifetime that can reference data owned by the
21//! factory. This trait must be implemented by client applications.
22//!
23//! At the point, one can create a [`FactoryFuncCodeReader`] depending on a
24//! specific [`CodesReaderFactory`]. The [`FactoryFuncCodeReader`] will store a
25//! function pointer with a generic lifetime that can be downcast to a specific
26//! lifetime. Thus, the function pointer is created just once at the creation of
27//! the [`FactoryFuncCodeReader`], and can be reused to create
28//! [`FuncCodeReader`]s with any lifetime using [`FactoryFuncCodeReader::get`].
29//!
30//! # Implementation Notes
31//!
32//! In principle, we would like to have inside a [`FactoryFuncCodeReader`] a
33//! field with type
34//!
35//! ```ignore
36//! for<'a> FuncCodeReader<E, CRF::CodesReader<'a>>
37//! ```
38//!
39//! However, this is not possible in the Rust type system. We can however write
40//! the type
41//!
42//! ```ignore
43//! for<'a> fn(&mut CRF::CodesReader<'a>) -> Result<u64>
44//! ```
45//!
46//! This workaround is not perfect as we cannot properly specify the error type:
47//! ```ignore
48//! Result<u64, <CRF::CodesReader<'a> as BitRead<E>>::Error>
49//! ```
50//! The compiler here complains that the return type has a lifetime not
51//! constrained by the input arguments.
52//!
53//! To work around this problem, we could add an otherwise useless associated
54//! type `CodesReaderFactory::Error` to the [`CodesReaderFactory`] trait,
55//! imposing that the error type of [`CodesReaderFactory::CodesReader`] is the
56//! same. Unfortunately, this requires that all users of the factory add a `where`
57//! constraint in which the error type is written explicitly.
58//!
59//! To mitigate this problem, we provide instead a helper trait
60//! [`CodesReaderFactoryHelper`] that extends [`CodesReaderFactory`]; the helper
61//! trait contains an `Error` associated type and [uses higher-rank trait
62//! bounds](https://users.rust-lang.org/t/extracting-static-associated-type-from-type-with-lifetime/126880)
63//! to bind the associated type to the error type of the
64//! [`CodesReaderFactory::CodesReader`]. The user can implement
65//! [`CodesReaderFactory`] on its own types and write trait bounds using
66//! [`CodesReaderFactoryHelper`]:
67//! ```ignore
68//! fn test<E: Endianness, CRF: CodesReaderFactoryHelper<E>>(factory: CRF)
69//! {
70//!     let reader = factory.new_reader();
71//!     // do something with the reader
72//!     // CRF::Error is the error type of CRF::CodesReader<'a>
73//! }
74//! ```
75
76use super::*;
77use anyhow::Result;
78use core::fmt::Debug;
79/// A trait that models a type that can return a [`CodesRead`] that can reference
80/// data owned by the factory. The typical case is a factory that owns the
81/// bit stream, and returns a [`CodesRead`] that can read from it.
82pub trait CodesReaderFactory<E: Endianness> {
83    type CodesReader<'a>
84    where
85        Self: 'a;
86
87    /// Create a new code reader that can reference data owned by the factory.
88    fn new_reader(&self) -> Self::CodesReader<'_>;
89}
90
91/// Extension helper trait for [`CodesReaderFactory`].
92///
93/// By writing trait bounds using this helper instead of [`CodesReaderFactory`],
94/// you can access the error type of the [`CodesReaderFactory::CodesReader`] through
95/// [`CodesReaderFactoryHelper::Error`].
96pub trait CodesReaderFactoryHelper<E: Endianness>:
97    for<'a> CodesReaderFactory<E, CodesReader<'a>: CodesRead<E, Error = Self::Error>>
98{
99    type Error;
100}
101
102impl<E: Endianness, F, ERR> CodesReaderFactoryHelper<E> for F
103where
104    F: ?Sized + for<'a> CodesReaderFactory<E, CodesReader<'a>: CodesRead<E, Error = ERR>>,
105{
106    type Error = ERR;
107}
108
109/// The function type stored in a [`FactoryFuncCodeReader`].
110///
111/// The role of this type is analogous to that of `ReadFn` in [`FuncCodeReader`],
112/// but we have an extra lifetime parameter to handle the lifetime
113/// of the [`CodesReaderFactory::CodesReader`].
114type FactoryReadFn<E, CRF> = for<'a> fn(
115    &mut <CRF as CodesReaderFactory<E>>::CodesReader<'a>,
116)
117    -> Result<u64, <CRF as CodesReaderFactoryHelper<E>>::Error>;
118
119/// A newtype depending on a [`CodesReaderFactory`] and containing a function
120/// pointer dispatching the read method for a code.
121///
122/// It is essentially a version of [`FuncCodeReader`] that depends on a
123/// [`CodesReaderFactory`] and its associated
124/// [`CodesReaderFactory::CodesReader`] instead of a generic [`CodesRead`].
125#[derive(Debug, Copy, PartialEq, Eq)]
126pub struct FactoryFuncCodeReader<E: Endianness, CRF: CodesReaderFactoryHelper<E> + ?Sized>(
127    FactoryReadFn<E, CRF>,
128);
129
130/// Manually implement [`Clone`] to avoid the [`Clone`] bound on `CR` and `E`.
131impl<E: Endianness, CRF: CodesReaderFactoryHelper<E> + ?Sized> Clone
132    for FactoryFuncCodeReader<E, CRF>
133{
134    #[inline(always)]
135    fn clone(&self) -> Self {
136        Self(self.0)
137    }
138}
139
140impl<E: Endianness, CRF: CodesReaderFactoryHelper<E> + ?Sized> FactoryFuncCodeReader<E, CRF> {
141    // due to the added lifetime generic we cannot just re-use the FuncCodeReader definitions
142    const UNARY: FactoryReadFn<E, CRF> = |reader| reader.read_unary();
143    const GAMMA: FactoryReadFn<E, CRF> = |reader| reader.read_gamma();
144    const DELTA: FactoryReadFn<E, CRF> = |reader| reader.read_delta();
145    const OMEGA: FactoryReadFn<E, CRF> = |reader| reader.read_omega();
146    const VBYTE_BE: FactoryReadFn<E, CRF> = |reader| reader.read_vbyte_be();
147    const VBYTE_LE: FactoryReadFn<E, CRF> = |reader| reader.read_vbyte_le();
148    const ZETA2: FactoryReadFn<E, CRF> = |reader| reader.read_zeta(2);
149    const ZETA3: FactoryReadFn<E, CRF> = |reader| reader.read_zeta3();
150    const ZETA4: FactoryReadFn<E, CRF> = |reader| reader.read_zeta(4);
151    const ZETA5: FactoryReadFn<E, CRF> = |reader| reader.read_zeta(5);
152    const ZETA6: FactoryReadFn<E, CRF> = |reader| reader.read_zeta(6);
153    const ZETA7: FactoryReadFn<E, CRF> = |reader| reader.read_zeta(7);
154    const ZETA8: FactoryReadFn<E, CRF> = |reader| reader.read_zeta(8);
155    const ZETA9: FactoryReadFn<E, CRF> = |reader| reader.read_zeta(9);
156    const ZETA10: FactoryReadFn<E, CRF> = |reader| reader.read_zeta(10);
157    const RICE1: FactoryReadFn<E, CRF> = |reader| reader.read_rice(1);
158    const RICE2: FactoryReadFn<E, CRF> = |reader| reader.read_rice(2);
159    const RICE3: FactoryReadFn<E, CRF> = |reader| reader.read_rice(3);
160    const RICE4: FactoryReadFn<E, CRF> = |reader| reader.read_rice(4);
161    const RICE5: FactoryReadFn<E, CRF> = |reader| reader.read_rice(5);
162    const RICE6: FactoryReadFn<E, CRF> = |reader| reader.read_rice(6);
163    const RICE7: FactoryReadFn<E, CRF> = |reader| reader.read_rice(7);
164    const RICE8: FactoryReadFn<E, CRF> = |reader| reader.read_rice(8);
165    const RICE9: FactoryReadFn<E, CRF> = |reader| reader.read_rice(9);
166    const RICE10: FactoryReadFn<E, CRF> = |reader| reader.read_rice(10);
167    const PI1: FactoryReadFn<E, CRF> = |reader| reader.read_pi(1);
168    const PI2: FactoryReadFn<E, CRF> = |reader| reader.read_pi(2);
169    const PI3: FactoryReadFn<E, CRF> = |reader| reader.read_pi(3);
170    const PI4: FactoryReadFn<E, CRF> = |reader| reader.read_pi(4);
171    const PI5: FactoryReadFn<E, CRF> = |reader| reader.read_pi(5);
172    const PI6: FactoryReadFn<E, CRF> = |reader| reader.read_pi(6);
173    const PI7: FactoryReadFn<E, CRF> = |reader| reader.read_pi(7);
174    const PI8: FactoryReadFn<E, CRF> = |reader| reader.read_pi(8);
175    const PI9: FactoryReadFn<E, CRF> = |reader| reader.read_pi(9);
176    const PI10: FactoryReadFn<E, CRF> = |reader| reader.read_pi(10);
177    const GOLOMB3: FactoryReadFn<E, CRF> = |reader| reader.read_golomb(3);
178    const GOLOMB5: FactoryReadFn<E, CRF> = |reader| reader.read_golomb(5);
179    const GOLOMB6: FactoryReadFn<E, CRF> = |reader| reader.read_golomb(6);
180    const GOLOMB7: FactoryReadFn<E, CRF> = |reader| reader.read_golomb(7);
181    const GOLOMB9: FactoryReadFn<E, CRF> = |reader| reader.read_golomb(9);
182    const GOLOMB10: FactoryReadFn<E, CRF> = |reader| reader.read_golomb(10);
183    const EXP_GOLOMB1: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(1);
184    const EXP_GOLOMB2: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(2);
185    const EXP_GOLOMB3: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(3);
186    const EXP_GOLOMB4: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(4);
187    const EXP_GOLOMB5: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(5);
188    const EXP_GOLOMB6: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(6);
189    const EXP_GOLOMB7: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(7);
190    const EXP_GOLOMB8: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(8);
191    const EXP_GOLOMB9: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(9);
192    const EXP_GOLOMB10: FactoryReadFn<E, CRF> = |reader| reader.read_exp_golomb(10);
193
194    /// Return a new [`FactoryFuncCodeReader`] for the given code.
195    ///
196    /// # Errors
197    ///
198    /// The method will return an error if there is no constant
199    /// for the given code in [`FactoryFuncCodeReader`].
200    pub fn new(code: Codes) -> anyhow::Result<Self> {
201        let read_func = match code {
202            Codes::Unary => Self::UNARY,
203            Codes::Gamma => Self::GAMMA,
204            Codes::Delta => Self::DELTA,
205            Codes::Omega => Self::OMEGA,
206            Codes::VByteBe => Self::VBYTE_BE,
207            Codes::VByteLe => Self::VBYTE_LE,
208            Codes::Zeta { k: 1 } => Self::GAMMA,
209            Codes::Zeta { k: 2 } => Self::ZETA2,
210            Codes::Zeta { k: 3 } => Self::ZETA3,
211            Codes::Zeta { k: 4 } => Self::ZETA4,
212            Codes::Zeta { k: 5 } => Self::ZETA5,
213            Codes::Zeta { k: 6 } => Self::ZETA6,
214            Codes::Zeta { k: 7 } => Self::ZETA7,
215            Codes::Zeta { k: 8 } => Self::ZETA8,
216            Codes::Zeta { k: 9 } => Self::ZETA9,
217            Codes::Zeta { k: 10 } => Self::ZETA10,
218            Codes::Rice { log2_b: 0 } => Self::UNARY,
219            Codes::Rice { log2_b: 1 } => Self::RICE1,
220            Codes::Rice { log2_b: 2 } => Self::RICE2,
221            Codes::Rice { log2_b: 3 } => Self::RICE3,
222            Codes::Rice { log2_b: 4 } => Self::RICE4,
223            Codes::Rice { log2_b: 5 } => Self::RICE5,
224            Codes::Rice { log2_b: 6 } => Self::RICE6,
225            Codes::Rice { log2_b: 7 } => Self::RICE7,
226            Codes::Rice { log2_b: 8 } => Self::RICE8,
227            Codes::Rice { log2_b: 9 } => Self::RICE9,
228            Codes::Rice { log2_b: 10 } => Self::RICE10,
229            Codes::Pi { k: 0 } => Self::GAMMA,
230            Codes::Pi { k: 1 } => Self::PI1,
231            Codes::Pi { k: 2 } => Self::PI2,
232            Codes::Pi { k: 3 } => Self::PI3,
233            Codes::Pi { k: 4 } => Self::PI4,
234            Codes::Pi { k: 5 } => Self::PI5,
235            Codes::Pi { k: 6 } => Self::PI6,
236            Codes::Pi { k: 7 } => Self::PI7,
237            Codes::Pi { k: 8 } => Self::PI8,
238            Codes::Pi { k: 9 } => Self::PI9,
239            Codes::Pi { k: 10 } => Self::PI10,
240            Codes::Golomb { b: 1 } => Self::UNARY,
241            Codes::Golomb { b: 2 } => Self::RICE1,
242            Codes::Golomb { b: 3 } => Self::GOLOMB3,
243            Codes::Golomb { b: 4 } => Self::RICE2,
244            Codes::Golomb { b: 5 } => Self::GOLOMB5,
245            Codes::Golomb { b: 6 } => Self::GOLOMB6,
246            Codes::Golomb { b: 7 } => Self::GOLOMB7,
247            Codes::Golomb { b: 8 } => Self::RICE3,
248            Codes::Golomb { b: 9 } => Self::GOLOMB9,
249            Codes::Golomb { b: 10 } => Self::GOLOMB10,
250            Codes::ExpGolomb { k: 0 } => Self::GAMMA,
251            Codes::ExpGolomb { k: 1 } => Self::EXP_GOLOMB1,
252            Codes::ExpGolomb { k: 2 } => Self::EXP_GOLOMB2,
253            Codes::ExpGolomb { k: 3 } => Self::EXP_GOLOMB3,
254            Codes::ExpGolomb { k: 4 } => Self::EXP_GOLOMB4,
255            Codes::ExpGolomb { k: 5 } => Self::EXP_GOLOMB5,
256            Codes::ExpGolomb { k: 6 } => Self::EXP_GOLOMB6,
257            Codes::ExpGolomb { k: 7 } => Self::EXP_GOLOMB7,
258            Codes::ExpGolomb { k: 8 } => Self::EXP_GOLOMB8,
259            Codes::ExpGolomb { k: 9 } => Self::EXP_GOLOMB9,
260            Codes::ExpGolomb { k: 10 } => Self::EXP_GOLOMB10,
261            _ => anyhow::bail!("Unsupported read dispatch for code {:?}", code),
262        };
263        Ok(Self(read_func))
264    }
265
266    /// Returns a new [`FactoryFuncCodeReader`] for the given function.
267    #[inline(always)]
268    pub fn new_with_func(read_func: FactoryReadFn<E, CRF>) -> Self {
269        Self(read_func)
270    }
271
272    /// Returns the function pointer for the code.
273    #[inline(always)]
274    pub fn inner(&self) -> FactoryReadFn<E, CRF> {
275        self.0
276    }
277
278    /// Returns a [`FuncCodeReader`] compatible with `CRF`'s
279    /// [`CodesReaderFactory::CodesReader`] for a given lifetime `'a`.
280    #[inline(always)]
281    pub fn get<'a>(
282        &self,
283    ) -> super::FuncCodeReader<E, <CRF as CodesReaderFactory<E>>::CodesReader<'a>> {
284        super::FuncCodeReader::new_with_func(self.0)
285    }
286}