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

vigna / webgraph-rs / 14999125721

13 May 2025 02:22PM UTC coverage: 49.654% (-5.7%) from 55.382%
14999125721

push

github

zommiommy
wip hyperball cli

4 of 147 new or added lines in 4 files covered. (2.72%)

477 existing lines in 46 files now uncovered.

3663 of 7377 relevant lines covered (49.65%)

25650535.86 hits per line

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

30.77
/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::bail;
12
use anyhow::Result;
13
use dsi_bitstream::dispatch::code_consts;
14
use dsi_bitstream::dispatch::factory::CodesReaderFactoryHelper;
15
use dsi_bitstream::prelude::*;
16
use epserde::deser::MemCase;
17
use sux::traits::IndexedSeq;
18

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

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

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

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

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

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

111
    #[inline(always)]
112
    fn read_reference_offset(&mut self) -> u64 {
1,732,507✔
113
        ConstCode::<REFERENCES>.read(&mut self.code_reader).unwrap()
6,930,028✔
114
    }
115

116
    #[inline(always)]
117
    fn read_block_count(&mut self) -> u64 {
1,062,515✔
118
        ConstCode::<BLOCKS>.read(&mut self.code_reader).unwrap()
4,250,060✔
119
    }
120
    #[inline(always)]
121
    fn read_block(&mut self) -> u64 {
1,862,472✔
122
        ConstCode::<BLOCKS>.read(&mut self.code_reader).unwrap()
7,449,888✔
123
    }
124

125
    #[inline(always)]
126
    fn read_interval_count(&mut self) -> u64 {
1,491,316✔
127
        ConstCode::<INTERVALS>.read(&mut self.code_reader).unwrap()
5,965,264✔
128
    }
129
    #[inline(always)]
130
    fn read_interval_start(&mut self) -> u64 {
1,235,114✔
131
        ConstCode::<INTERVALS>.read(&mut self.code_reader).unwrap()
4,940,456✔
132
    }
133
    #[inline(always)]
134
    fn read_interval_len(&mut self) -> u64 {
1,235,114✔
135
        ConstCode::<INTERVALS>.read(&mut self.code_reader).unwrap()
4,940,456✔
136
    }
137

138
    #[inline(always)]
139
    fn read_first_residual(&mut self) -> u64 {
2,050,877✔
140
        ConstCode::<RESIDUALS>.read(&mut self.code_reader).unwrap()
8,203,508✔
141
    }
142
    #[inline(always)]
143
    fn read_residual(&mut self) -> u64 {
7,674,595✔
144
        ConstCode::<RESIDUALS>.read(&mut self.code_reader).unwrap()
30,698,380✔
145
    }
146
}
147

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

167
impl<
168
        E: Endianness,
169
        F: CodesReaderFactoryHelper<E>,
170
        OFF: IndexedSeq<Input = usize, Output = usize>,
171
        const OUTDEGREES: usize,
172
        const REFERENCES: usize,
173
        const BLOCKS: usize,
174
        const INTERVALS: usize,
175
        const RESIDUALS: usize,
176
    > ConstCodesDecoderFactory<E, F, OFF, OUTDEGREES, REFERENCES, BLOCKS, INTERVALS, RESIDUALS>
177
where
178
    for<'a> &'a OFF: IntoIterator<Item = usize>, // This dependence can soon be removed, as there will be a IndexedSeq::iter method
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
        SliceSeq<usize, Box<[usize]>>,
193
        OUTDEGREES,
194
        REFERENCES,
195
        BLOCKS,
196
        INTERVALS,
197
        RESIDUALS,
198
    > {
199
        ConstCodesDecoderFactory {
200
            factory: self.factory,
×
201
            offsets: <Box<[usize]> as Into<SliceSeq<usize, Box<[usize]>>>>::into(
×
202
                self.offsets
203
                    .into_iter()
204
                    .collect::<Vec<_>>()
205
                    .into_boxed_slice(),
206
            )
207
            .into(),
208
            _marker: PhantomData,
209
        }
210
    }
211
}
212

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

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

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

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

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

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

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