Skip to main content

compressed_intvec/variable/
iter.rs

1//! Iterators for [`VarVec`].
2//!
3//! This module provides the iterators for [`VarVec`]. Due to the nature of
4//! variable-length encoding, an [`VarVec`] is immutable once created, as
5//! modifying an element would require re-encoding the rest of the data stream.
6//!
7//! [`VarVec`]: crate::variable::VarVec
8
9use super::{traits::Storable, VarVec};
10use crate::common::codec_reader::{CodecReader, VarVecBitReader};
11use dsi_bitstream::{
12    dispatch::{CodesRead, StaticCodeRead},
13    prelude::{BitRead, BitSeek, Endianness},
14};
15use std::fmt;
16use std::iter::FusedIterator;
17use std::marker::PhantomData;
18
19/// A borrowing iterator over the values of an [`VarVec`].
20///
21/// This struct is created by the [`iter`](VarVec::iter) method on [`VarVec`].
22/// It provides a sequential, forward-only scan over the compressed data,
23/// decompressing values on the fly.
24///
25/// # Examples
26///
27/// ```
28/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
29/// use compressed_intvec::variable::{VarVec, UVarVec};
30///
31/// let data: &[u32] = &[10, 20, 30, 40, 50];
32/// let vec: UVarVec<u32> = VarVec::from_slice(data)?;
33///
34/// let mut sum = 0;
35/// for value in vec.iter() {
36///     sum += value;
37/// }
38///
39/// assert_eq!(sum, 150);
40/// # Ok(())
41/// # }
42/// ```
43pub struct VarVecIter<'a, T: Storable, E: Endianness, B: AsRef<[u64]>>
44where
45    for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
46        + CodesRead<E>
47        + BitSeek<Error = core::convert::Infallible>,
48{
49    len: usize,
50    reader: VarVecBitReader<'a, E>,
51    /// The hybrid dispatcher that handles codec reading robustly.
52    code_reader: CodecReader<'a, E>,
53    current_index: usize,
54    _markers: PhantomData<(&'a B, T)>,
55}
56
57impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> VarVecIter<'a, T, E, B>
58where
59    for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
60        + CodesRead<E>
61        + BitSeek<Error = core::convert::Infallible>,
62{
63    /// Creates a new iterator.
64    pub(super) fn new(intvec: &'a VarVec<T, E, B>) -> Self {
65        let reader = VarVecBitReader::<E>::new(dsi_bitstream::impls::MemWordReader::new_inf(
66            intvec.data.as_ref(),
67        ));
68        // Instantiate the robust hybrid dispatcher. This will not panic.
69        let code_reader = CodecReader::new(intvec.encoding);
70
71        Self {
72            len: intvec.len,
73            reader,
74            code_reader,
75            current_index: 0,
76            _markers: PhantomData,
77        }
78    }
79}
80
81impl<T: Storable, E: Endianness, B: AsRef<[u64]>> Iterator for VarVecIter<'_, T, E, B>
82where
83    for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
84        + CodesRead<E>
85        + BitSeek<Error = core::convert::Infallible>,
86{
87    type Item = T;
88
89    #[inline]
90    fn next(&mut self) -> Option<Self::Item> {
91        if self.current_index >= self.len {
92            return None;
93        }
94        // The read operation is infallible due to the robust dispatcher.
95        let value = self.code_reader.read(&mut self.reader).unwrap();
96        self.current_index += 1;
97        Some(Storable::from_word(value))
98    }
99
100    fn size_hint(&self) -> (usize, Option<usize>) {
101        let remaining = self.len.saturating_sub(self.current_index);
102        (remaining, Some(remaining))
103    }
104}
105
106impl<T: Storable, E: Endianness, B: AsRef<[u64]>> ExactSizeIterator for VarVecIter<'_, T, E, B>
107where
108    for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
109        + CodesRead<E>
110        + BitSeek<Error = core::convert::Infallible>,
111{
112    fn len(&self) -> usize {
113        self.len.saturating_sub(self.current_index)
114    }
115}
116
117impl<T: Storable, E: Endianness, B: AsRef<[u64]>> FusedIterator for VarVecIter<'_, T, E, B> where
118    for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
119        + CodesRead<E>
120        + BitSeek<Error = core::convert::Infallible>
121{
122}
123
124impl<T: Storable, E: Endianness, B: AsRef<[u64]>> fmt::Debug for VarVecIter<'_, T, E, B>
125where
126    for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
127        + CodesRead<E>
128        + BitSeek<Error = core::convert::Infallible>,
129{
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        f.debug_struct("VarVecIter")
132            .field("remaining", &self.len.saturating_sub(self.current_index))
133            .finish()
134    }
135}
136
137/// An owning iterator over the values of an [`VarVec`].
138///
139/// This struct is created by the [`into_iter`](VarVec::into_iter) method on
140/// [`VarVec`] (or by using a `for` loop on an owned [`VarVec`]). It takes ownership
141/// of the vector and decodes its values on the fly.
142///
143/// # Examples
144///
145/// ```
146/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
147/// use compressed_intvec::variable::{VarVec, SVarVec};
148///
149/// let data: &[i16] = &[-1, -2, -3, -4];
150/// let vec: SVarVec<i16> = VarVec::from_slice(data)?;
151///
152/// // The `into_iter` call is implicit in the for loop.
153/// // This loop consumes `vec`.
154/// let collected: Vec<i16> = vec.into_iter().map(|v| v * 2).collect();
155///
156/// assert_eq!(collected, &[-2, -4, -6, -8]);
157/// # Ok(())
158/// # }
159/// ```
160pub struct VarVecIntoIter<T, E>
161where
162    T: Storable + 'static,
163    E: Endianness + 'static,
164    for<'a> VarVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
165        + CodesRead<E>
166        + BitSeek<Error = core::convert::Infallible>,
167{
168    /// The number of elements remaining in the iterator.
169    len: usize,
170    /// The current position in the sequence.
171    current_index: usize,
172    /// A stateful reader that borrows from `_data_owner`.
173    reader: VarVecBitReader<'static, E>,
174    /// The hybrid dispatcher for decoding.
175    code_reader: CodecReader<'static, E>,
176    /// This field owns the data buffer, ensuring it lives as long as the iterator.
177    _data_owner: Vec<u64>,
178    /// Phantom data to hold the generic type `T`.
179    _markers: PhantomData<T>,
180}
181
182impl<T, E> VarVecIntoIter<T, E>
183where
184    T: Storable + 'static,
185    E: Endianness + 'static,
186    for<'a> VarVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
187        + CodesRead<E>
188        + BitSeek<Error = core::convert::Infallible>,
189{
190    /// Creates a new, efficient owning iterator from a [`VarVec`].
191    pub(super) fn new(vec: VarVec<T, E, Vec<u64>>) -> Self {
192        // This is a self-referential struct. We move the owned data buffer into `_data_owner`.
193        // Then, we create a 'static reference to that data to initialize the reader.
194        // This is safe because `_data_owner` is part of the same struct as `reader`,
195        // guaranteeing that the data outlives the reference.
196        let data_ref: &'static [u64] = unsafe { std::mem::transmute(vec.data.as_slice()) };
197
198        let reader = VarVecBitReader::<E>::new(dsi_bitstream::impls::MemWordReader::new_inf(data_ref));
199        let code_reader = CodecReader::new(vec.encoding);
200
201        Self {
202            len: vec.len,
203            current_index: 0,
204            reader,
205            code_reader,
206            _data_owner: vec.data,
207            _markers: PhantomData,
208        }
209    }
210}
211
212impl<T, E> Iterator for VarVecIntoIter<T, E>
213where
214    T: Storable + 'static,
215    E: Endianness + 'static,
216    for<'a> VarVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
217        + CodesRead<E>
218        + BitSeek<Error = core::convert::Infallible>,
219{
220    type Item = T;
221
222    #[inline]
223    fn next(&mut self) -> Option<Self::Item> {
224        if self.current_index >= self.len {
225            return None;
226        }
227        let value = self.code_reader.read(&mut self.reader).unwrap();
228        self.current_index += 1;
229        Some(Storable::from_word(value))
230    }
231
232    fn size_hint(&self) -> (usize, Option<usize>) {
233        let remaining = self.len.saturating_sub(self.current_index);
234        (remaining, Some(remaining))
235    }
236}
237
238impl<T, E> ExactSizeIterator for VarVecIntoIter<T, E>
239where
240    T: Storable + 'static,
241    E: Endianness + 'static,
242    for<'a> VarVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
243        + CodesRead<E>
244        + BitSeek<Error = core::convert::Infallible>,
245{
246    fn len(&self) -> usize {
247        self.len.saturating_sub(self.current_index)
248    }
249}
250
251impl<T, E> FusedIterator for VarVecIntoIter<T, E>
252where
253    T: Storable + 'static,
254    E: Endianness + 'static,
255    for<'a> VarVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
256        + CodesRead<E>
257        + BitSeek<Error = core::convert::Infallible>,
258{
259}
260
261impl<T, E> fmt::Debug for VarVecIntoIter<T, E>
262where
263    T: Storable + 'static,
264    E: Endianness + 'static,
265    for<'a> VarVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
266        + CodesRead<E>
267        + BitSeek<Error = core::convert::Infallible>,
268{
269    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270        f.debug_struct("VarVecIntoIter")
271            .field("remaining", &self.len.saturating_sub(self.current_index))
272            .finish()
273    }
274}