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

vigna / webgraph-rs / 20017908129

08 Dec 2025 05:36AM UTC coverage: 62.065% (+0.4%) from 61.641%
20017908129

push

github

zommiommy
Fix doctests

5435 of 8757 relevant lines covered (62.06%)

46674689.93 hits per line

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

0.0
/webgraph/src/graphs/bvgraph/codecs/dec_const.rs
1
/*
2
 * SPDX-FileCopyrightText: 2023 Inria
3
 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
4
 *
5
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
6
 */
7

8
use std::marker::PhantomData;
9

10
use super::super::*;
11
use anyhow::Result;
12
use anyhow::bail;
13
use dsi_bitstream::dispatch::code_consts;
14
use dsi_bitstream::dispatch::factory::CodesReaderFactoryHelper;
15
use dsi_bitstream::prelude::*;
16

17
use epserde::deser::MemCase;
18
use epserde::deser::Owned;
19
use sux::traits::IndexedSeq;
20

21
#[repr(transparent)]
22
/// An implementation of [`Decode`]  with compile-time defined codes.
23
#[derive(Debug, Clone)]
24
pub struct ConstCodesDecoder<
25
    E: Endianness,
26
    CR: CodesRead<E>,
27
    const OUTDEGREES: usize = { code_consts::GAMMA },
28
    const REFERENCES: usize = { code_consts::UNARY },
29
    const BLOCKS: usize = { code_consts::GAMMA },
30
    const INTERVALS: usize = { code_consts::GAMMA },
31
    const RESIDUALS: usize = { code_consts::ZETA3 },
32
> {
33
    /// The inner codes reader we will dispatch to
34
    pub(crate) code_reader: CR,
35
    /// Make the compiler happy with the generics we don't use in the struct
36
    /// (but we need them to be able to use the trait)
37
    pub(crate) _marker: core::marker::PhantomData<E>,
38
}
39

40
impl<
41
    E: Endianness,
42
    CR: CodesRead<E> + BitSeek,
43
    const OUTDEGREES: usize,
44
    const REFERENCES: usize,
45
    const BLOCKS: usize,
46
    const INTERVALS: usize,
47
    const RESIDUALS: usize,
48
> BitSeek for ConstCodesDecoder<E, CR, OUTDEGREES, REFERENCES, BLOCKS, INTERVALS, RESIDUALS>
49
{
50
    type Error = <CR as BitSeek>::Error;
51

52
    fn set_bit_pos(&mut self, bit_index: u64) -> Result<(), Self::Error> {
×
53
        self.code_reader.set_bit_pos(bit_index)
×
54
    }
55

56
    fn bit_pos(&mut self) -> Result<u64, Self::Error> {
×
57
        self.code_reader.bit_pos()
×
58
    }
59
}
60

61
impl<
62
    E: Endianness,
63
    CR: CodesRead<E>,
64
    const OUTDEGREES: usize,
65
    const REFERENCES: usize,
66
    const BLOCKS: usize,
67
    const INTERVALS: usize,
68
    const RESIDUALS: usize,
69
> ConstCodesDecoder<E, CR, OUTDEGREES, REFERENCES, BLOCKS, INTERVALS, RESIDUALS>
70
{
71
    /// Creates a new [`ConstCodesEncoder`] from a [`CodesRead`] implementation.
72
    /// and a [`CompFlags`] struct
73
    /// # Errors
74
    /// If the codes in the [`CompFlags`] do not match the compile-time defined codes
75
    pub fn new(code_reader: CR, comp_flags: &CompFlags) -> Result<Self> {
×
76
        if comp_flags.outdegrees.to_code_const()? != OUTDEGREES {
×
77
            bail!("Code for outdegrees does not match");
×
78
        }
79
        if comp_flags.references.to_code_const()? != REFERENCES {
×
80
            bail!("Cod for references does not match");
×
81
        }
82
        if comp_flags.blocks.to_code_const()? != BLOCKS {
×
83
            bail!("Code for blocks does not match");
×
84
        }
85
        if comp_flags.intervals.to_code_const()? != INTERVALS {
×
86
            bail!("Code for intervals does not match");
×
87
        }
88
        if comp_flags.residuals.to_code_const()? != RESIDUALS {
×
89
            bail!("Code for residuals does not match");
×
90
        }
91
        Ok(Self {
×
92
            code_reader,
×
93
            _marker: core::marker::PhantomData,
×
94
        })
95
    }
96
}
97

98
impl<
99
    E: Endianness,
100
    CR: CodesRead<E>,
101
    const OUTDEGREES: usize,
102
    const REFERENCES: usize,
103
    const BLOCKS: usize,
104
    const INTERVALS: usize,
105
    const RESIDUALS: usize,
106
> Decode for ConstCodesDecoder<E, CR, OUTDEGREES, REFERENCES, BLOCKS, INTERVALS, RESIDUALS>
107
{
108
    #[inline(always)]
109
    fn read_outdegree(&mut self) -> u64 {
×
110
        ConstCode::<OUTDEGREES>.read(&mut self.code_reader).unwrap()
×
111
    }
112

113
    #[inline(always)]
114
    fn read_reference_offset(&mut self) -> u64 {
×
115
        ConstCode::<REFERENCES>.read(&mut self.code_reader).unwrap()
×
116
    }
117

118
    #[inline(always)]
119
    fn read_block_count(&mut self) -> u64 {
×
120
        ConstCode::<BLOCKS>.read(&mut self.code_reader).unwrap()
×
121
    }
122
    #[inline(always)]
123
    fn read_block(&mut self) -> u64 {
×
124
        ConstCode::<BLOCKS>.read(&mut self.code_reader).unwrap()
×
125
    }
126

127
    #[inline(always)]
128
    fn read_interval_count(&mut self) -> u64 {
×
129
        ConstCode::<INTERVALS>.read(&mut self.code_reader).unwrap()
×
130
    }
131
    #[inline(always)]
132
    fn read_interval_start(&mut self) -> u64 {
×
133
        ConstCode::<INTERVALS>.read(&mut self.code_reader).unwrap()
×
134
    }
135
    #[inline(always)]
136
    fn read_interval_len(&mut self) -> u64 {
×
137
        ConstCode::<INTERVALS>.read(&mut self.code_reader).unwrap()
×
138
    }
139

140
    #[inline(always)]
141
    fn read_first_residual(&mut self) -> u64 {
×
142
        ConstCode::<RESIDUALS>.read(&mut self.code_reader).unwrap()
×
143
    }
144
    #[inline(always)]
145
    fn read_residual(&mut self) -> u64 {
×
146
        ConstCode::<RESIDUALS>.read(&mut self.code_reader).unwrap()
×
147
    }
148
}
149

150
pub struct ConstCodesDecoderFactory<
151
    E: Endianness,
152
    F: CodesReaderFactoryHelper<E>,
153
    OFF: Offsets,
154
    const OUTDEGREES: usize = { code_consts::GAMMA },
155
    const REFERENCES: usize = { code_consts::UNARY },
156
    const BLOCKS: usize = { code_consts::GAMMA },
157
    const INTERVALS: usize = { code_consts::GAMMA },
158
    const RESIDUALS: usize = { code_consts::ZETA3 },
159
> {
160
    /// The owned data
161
    factory: F,
162
    /// The offsets into the data.
163
    offsets: MemCase<OFF>,
164
    /// Tell the compiler that's Ok that we don't store `E` but we need it
165
    /// for typing.
166
    _marker: core::marker::PhantomData<E>,
167
}
168

169
impl<
170
    E: Endianness,
171
    F: CodesReaderFactoryHelper<E>,
172
    OFF: Offsets,
173
    const OUTDEGREES: usize,
174
    const REFERENCES: usize,
175
    const BLOCKS: usize,
176
    const INTERVALS: usize,
177
    const RESIDUALS: usize,
178
> ConstCodesDecoderFactory<E, F, OFF, OUTDEGREES, REFERENCES, BLOCKS, INTERVALS, RESIDUALS>
179
{
180
    /// Remaps the offsets in a slice of `usize`.
181
    ///
182
    /// This method is mainly useful for benchmarking and testing purposes, as
183
    /// representing the offsets as a slice increasing significantly the
184
    /// memory footprint.
185
    ///
186
    /// This method is used by [`BvGraph::offsets_to_slice`].
187
    pub fn offsets_to_slice(
×
188
        self,
189
    ) -> ConstCodesDecoderFactory<
190
        E,
191
        F,
192
        Owned<Box<[usize]>>,
193
        OUTDEGREES,
194
        REFERENCES,
195
        BLOCKS,
196
        INTERVALS,
197
        RESIDUALS,
198
    > {
199
        let offsets = self.offsets.uncase();
×
200
        ConstCodesDecoderFactory {
201
            factory: self.factory,
×
202
            offsets: (0..offsets.len())
×
203
                .map(|i| unsafe { offsets.get_unchecked(i) })
204
                .collect::<Vec<_>>()
205
                .into_boxed_slice()
206
                .into(),
207
            _marker: PhantomData,
208
        }
209
    }
210
}
211

212
impl<
213
    E: Endianness,
214
    F: CodesReaderFactoryHelper<E>,
215
    OFF: Offsets,
216
    const OUTDEGREES: usize,
217
    const REFERENCES: usize,
218
    const BLOCKS: usize,
219
    const INTERVALS: usize,
220
    const RESIDUALS: usize,
221
> ConstCodesDecoderFactory<E, F, OFF, OUTDEGREES, REFERENCES, BLOCKS, INTERVALS, RESIDUALS>
222
{
223
    /// Creates a new builder from the given data and compression flags.
224
    pub fn new(factory: F, offsets: MemCase<OFF>, comp_flags: CompFlags) -> anyhow::Result<Self> {
×
225
        if comp_flags.outdegrees.to_code_const()? != OUTDEGREES {
×
226
            bail!("Code for outdegrees does not match");
×
227
        }
228
        if comp_flags.references.to_code_const()? != REFERENCES {
×
229
            bail!("Cod for references does not match");
×
230
        }
231
        if comp_flags.blocks.to_code_const()? != BLOCKS {
×
232
            bail!("Code for blocks does not match");
×
233
        }
234
        if comp_flags.intervals.to_code_const()? != INTERVALS {
×
235
            bail!("Code for intervals does not match");
×
236
        }
237
        if comp_flags.residuals.to_code_const()? != RESIDUALS {
×
238
            bail!("Code for residuals does not match");
×
239
        }
240
        Ok(Self {
×
241
            factory,
×
242
            offsets,
×
243
            _marker: core::marker::PhantomData,
×
244
        })
245
    }
246
}
247

248
impl<
249
    E: Endianness,
250
    F: CodesReaderFactoryHelper<E>,
251
    OFF: Offsets,
252
    const OUTDEGREES: usize,
253
    const REFERENCES: usize,
254
    const BLOCKS: usize,
255
    const INTERVALS: usize,
256
    const RESIDUALS: usize,
257
> RandomAccessDecoderFactory
258
    for ConstCodesDecoderFactory<E, F, OFF, OUTDEGREES, REFERENCES, BLOCKS, INTERVALS, RESIDUALS>
259
where
260
    for<'a> <F as CodesReaderFactory<E>>::CodesReader<'a>: BitSeek,
261
{
262
    type Decoder<'a>
263
        = ConstCodesDecoder<E, <F as CodesReaderFactory<E>>::CodesReader<'a>>
264
    where
265
        Self: 'a;
266

267
    fn new_decoder(&self, offset: usize) -> anyhow::Result<Self::Decoder<'_>> {
×
268
        let mut code_reader = self.factory.new_reader();
×
269
        code_reader.set_bit_pos(unsafe { self.offsets.uncase().get_unchecked(offset) } as u64)?;
×
270

271
        Ok(ConstCodesDecoder {
×
272
            code_reader,
×
273
            _marker: PhantomData,
×
274
        })
275
    }
276
}
277

278
impl<
279
    E: Endianness,
280
    F: CodesReaderFactoryHelper<E>,
281
    OFF: Offsets,
282
    const OUTDEGREES: usize,
283
    const REFERENCES: usize,
284
    const BLOCKS: usize,
285
    const INTERVALS: usize,
286
    const RESIDUALS: usize,
287
> SequentialDecoderFactory
288
    for ConstCodesDecoderFactory<E, F, OFF, OUTDEGREES, REFERENCES, BLOCKS, INTERVALS, RESIDUALS>
289
{
290
    type Decoder<'a>
291
        = ConstCodesDecoder<E, <F as CodesReaderFactory<E>>::CodesReader<'a>>
292
    where
293
        Self: 'a;
294

295
    fn new_decoder(&self) -> anyhow::Result<Self::Decoder<'_>> {
×
296
        let code_reader = self.factory.new_reader();
×
297

298
        Ok(ConstCodesDecoder {
×
299
            code_reader,
×
300
            _marker: PhantomData,
×
301
        })
302
    }
303
}
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