Skip to main content

compressed_intvec/seq/
iter.rs

1//! Iterators for [`SeqVec`].
2//!
3//! This module provides iterator types for accessing sequences and their elements
4//! within a [`SeqVec`]. The design prioritizes zero-allocation iteration and
5//! efficient bit-level termination detection.
6//!
7//! The primary types are:
8//!
9//! - [`SeqIter`]: Iterator over the elements of a single sequence.
10//! - [`SeqVecIter`]: Iterator over all sequences in a [`SeqVec`].
11//!
12//! [`SeqVec`]: crate::seq::SeqVec
13
14use crate::common::codec_reader::CodecReader;
15use crate::fixed::FixedVec;
16use crate::variable::traits::Storable;
17use dsi_bitstream::{
18    codes::params::DefaultReadParams,
19    dispatch::{Codes, CodesRead, StaticCodeRead},
20    impls::{BufBitReader, MemWordReader},
21    prelude::{BitRead, BitSeek, Endianness},
22};
23use std::marker::PhantomData;
24
25/// Type alias for the bit reader used internally by [`SeqVec`] accessors.
26///
27/// This reader is configured for in-memory buffers with infallible reads,
28/// matching the configuration used in the [`variable`] module.
29///
30/// [`SeqVec`]: crate::seq::SeqVec
31/// [`variable`]: crate::variable
32pub(crate) type SeqVecBitReader<'a, E> =
33    BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>;
34
35/// A zero-allocation iterator over the elements of a single sequence.
36///
37/// This iterator decodes elements lazily from the compressed bitstream. It
38/// determines when to stop by comparing the current bit position against the
39/// end boundary of the sequence. This approach avoids storing explicit lengths.
40///
41/// ## Termination Logic
42///
43/// Each call to [`next`](Iterator::next) performs:
44/// 1. A comparison: `current_bit_pos >= end_bit`.
45/// 2. If not at end, a variable-length decode operation.
46///
47/// The comparison involves two `u64` values and is highly predictable (almost
48/// always `false` until the sequence ends), making it effectively free due to
49/// branch prediction.
50///
51/// ## Exact Size Hint
52///
53/// This iterator only implements [`ExactSizeIterator`] when the sequence length
54/// is known upfront (e.g., when created from [`SeqVecIter`] with pre-stored lengths).
55/// If lengths are not pre-stored, computing the size requires decoding the entire
56/// remaining sequence—an O(n) operation that would be deceptive if hidden behind
57/// the `ExactSizeIterator` contract (which users expect to be O(1)).
58///
59/// Call [`size_hint()`](Iterator::size_hint) for a lower bound without full decoding.
60///
61/// ## Trait Implementations
62///
63/// - [`Iterator`]: Core iteration functionality.
64/// - [`std::iter::FusedIterator`]: Guarantees that after returning `None`, all subsequent
65///   calls return `None`.
66/// - [`ExactSizeIterator`]: Only when sequence length is known upfront.
67///
68/// ## Examples
69///
70/// ```
71/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
72/// use compressed_intvec::seq::{SeqVec, LESeqVec};
73///
74/// let sequences: &[&[u32]] = &[&[10, 20, 30], &[100, 200]];
75/// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
76///
77/// // Iterate over the first sequence
78/// let mut sum = 0u32;
79/// for value in vec.get(0).unwrap() {
80///     sum += value;
81/// }
82/// assert_eq!(sum, 60);
83/// #     Ok(())
84/// # }
85/// ```
86pub struct SeqIter<'a, T: Storable, E: Endianness>
87where
88    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
89        + CodesRead<E>
90        + BitSeek<Error = core::convert::Infallible>,
91{
92    /// The bitstream reader, positioned at the current element.
93    reader: SeqVecBitReader<'a, E>,
94    /// The hybrid codec reader for decoding elements.
95    /// Provides fast-path optimization via function pointers for common codecs,
96    /// with fallback to dynamic dispatch for uncommon parameter combinations.
97    code_reader: CodecReader<'a, E>,
98    /// The bit position at which this sequence ends (exclusive).
99    end_bit: u64,
100    /// The known length of the sequence, if available.
101    /// When `None`, length is not pre-computed; call `count()` on the iterator
102    /// if an exact count is needed.
103    known_len: Option<usize>,
104    /// Marker for the element type.
105    _marker: PhantomData<T>,
106}
107
108impl<'a, T: Storable, E: Endianness> SeqIter<'a, T, E>
109where
110    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
111        + CodesRead<E>
112        + BitSeek<Error = core::convert::Infallible>,
113{
114    /// Creates a new iterator over a sequence.
115    ///
116    /// The iterator decodes elements starting from `start_bit` and stops when
117    /// the bit position reaches or exceeds `end_bit`.
118    ///
119    /// ## Arguments
120    ///
121    /// * `data` - The compressed data buffer containing all sequences.
122    /// * `start_bit` - The bit offset where this sequence begins.
123    /// * `end_bit` - The bit offset where this sequence ends (exclusive).
124    /// * `encoding` - The codec used for compression.
125    #[inline]
126    pub(crate) fn new(data: &'a [u64], start_bit: u64, end_bit: u64, encoding: Codes) -> Self {
127        let mut reader = SeqVecBitReader::<E>::new(MemWordReader::new_inf(data));
128
129        // Seek to the start of this sequence. The operation is infallible for
130        // in-memory readers, but we handle the Result for type correctness.
131        let _ = reader.set_bit_pos(start_bit);
132
133        // Create the hybrid codec reader for efficient decoding.
134        let code_reader = CodecReader::new(encoding);
135
136        Self {
137            reader,
138            code_reader,
139            end_bit,
140            known_len: None,
141            _marker: PhantomData,
142        }
143    }
144
145    /// Creates a new iterator over a sequence with a known length.
146    ///
147    /// This constructor is used when explicit sequence lengths are stored,
148    /// enabling [`ExactSizeIterator`] without additional decoding.
149    #[inline]
150    pub(crate) fn new_with_len(
151        data: &'a [u64],
152        start_bit: u64,
153        end_bit: u64,
154        encoding: Codes,
155        len: Option<usize>,
156    ) -> Self {
157        let mut iter = Self::new(data, start_bit, end_bit, encoding);
158        iter.known_len = len;
159        iter
160    }
161
162    /// Returns the ending bit position for this sequence (exclusive).
163    ///
164    /// This is useful for understanding the memory footprint of the sequence
165    /// when compressed.
166    #[inline]
167    pub fn end_bit(&self) -> u64 {
168        self.end_bit
169    }
170}
171
172impl<'a, T: Storable, E: Endianness> Iterator for SeqIter<'a, T, E>
173where
174    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
175        + CodesRead<E>
176        + BitSeek<Error = core::convert::Infallible>,
177{
178    type Item = T;
179
180    #[inline]
181    fn next(&mut self) -> Option<Self::Item> {
182        // When length is known, use counted termination to avoid bit_pos() overhead.
183        // The branch discriminant is stable across all iterations, so the branch
184        // predictor learns the pattern with ~100% accuracy after 1-2 iterations,
185        // making misprediction cost amortized to essentially zero.
186        if let Some(ref mut remaining) = self.known_len {
187            if *remaining == 0 {
188                return None;
189            }
190            *remaining -= 1;
191
192            // Decode element using optimized codec reader.
193            let word = self.code_reader.read(&mut self.reader).unwrap();
194            return Some(T::from_word(word));
195        }
196
197        // Fallback to bit-bounded termination when length is unknown.
198        // This path performs a multi-instruction bit_pos() computation per element,
199        // so only use it when length is not pre-stored.
200        if self.reader.bit_pos().unwrap() >= self.end_bit {
201            return None;
202        }
203
204        // Decode element using optimized codec reader.
205        let word = self.code_reader.read(&mut self.reader).unwrap();
206        Some(T::from_word(word))
207    }
208
209    #[inline]
210    fn size_hint(&self) -> (usize, Option<usize>) {
211        // If length is known, provide exact size hint.
212        if let Some(len) = self.known_len {
213            return (len, Some(len));
214        }
215        // Otherwise, provide no hint (length unknown).
216        (0, None)
217    }
218}
219
220impl<'a, T: Storable, E: Endianness> std::iter::FusedIterator for SeqIter<'a, T, E> where
221    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
222        + CodesRead<E>
223        + BitSeek<Error = core::convert::Infallible>
224{
225}
226
227/// Conditional [`ExactSizeIterator`] implementation for [`SeqIter`].
228///
229/// This is only implemented when the sequence length is known upfront (i.e., when
230/// created with `new_with_len` and `known_len` is `Some`). This ensures the
231/// `len()` method is O(1) and doesn't require expensive decoding.
232///
233/// If the length is unknown, users can call `count()` on the iterator to consume
234/// it and get the exact count, but this is explicit and O(n).
235impl<'a, T: Storable, E: Endianness> ExactSizeIterator for SeqIter<'a, T, E>
236where
237    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
238        + CodesRead<E>
239        + BitSeek<Error = core::convert::Infallible>,
240{
241    /// Returns the exact number of remaining elements.
242    ///
243    /// # Panics
244    ///
245    /// Panics if the length was not known upfront (i.e., this iterator was created
246    /// with `new` instead of `new_with_len` with a `Some` value). Use `count()`
247    /// instead if the length is unknown; it will consume the iterator but provide
248    /// the exact count.
249    #[inline]
250    fn len(&self) -> usize {
251        self.known_len.expect(
252            "SeqIter::len() called on iterator with unknown length. \
253             This can only happen if the iterator was not created with a pre-stored \
254             length. Use count() instead.",
255        )
256    }
257}
258
259/// An iterator over all sequences in a [`SeqVec`].
260///
261/// This iterator is created by the [`iter`] method on [`SeqVec`]. Each call to
262/// [`next`](Iterator::next) returns a [`SeqIter`] for the corresponding sequence.
263///
264/// ## Trait Implementations
265///
266/// - [`Iterator`]: Core iteration.
267/// - [`ExactSizeIterator`]: The number of sequences is known.
268/// - [`std::iter::FusedIterator`]: After `None`, always returns `None`.
269/// - [`DoubleEndedIterator`]: Supports iteration from both ends.
270///
271/// ## Examples
272///
273/// ```
274/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
275/// use compressed_intvec::seq::{SeqVec, LESeqVec};
276///
277/// let sequences: &[&[u32]] = &[&[1, 2], &[3], &[4, 5, 6]];
278/// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
279///
280/// // Collect all sequences into vectors
281/// let all: Vec<Vec<u32>> = vec.iter().map(|s| s.collect()).collect();
282/// assert_eq!(all, vec![vec![1, 2], vec![3], vec![4, 5, 6]]);
283/// #     Ok(())
284/// # }
285/// ```
286///
287/// [`SeqVec`]: crate::seq::SeqVec
288/// [`iter`]: crate::seq::SeqVec::iter
289pub struct SeqVecIter<'a, T: Storable, E: Endianness, B: AsRef<[u64]>>
290where
291    SeqVecBitReader<'a, E>: CodesRead<E>,
292{
293    /// Reference to the compressed data buffer.
294    data: &'a [u64],
295    /// Reference to the bit offsets index.
296    bit_offsets: &'a FixedVec<u64, u64, E, B>,
297    /// Optional reference to stored sequence lengths.
298    seq_lengths: Option<&'a FixedVec<u64, u64, E, Vec<u64>>>,
299    /// The codec used for compression.
300    encoding: Codes,
301    /// Current front index (for forward iteration).
302    front: usize,
303    /// Current back index (exclusive, for backward iteration).
304    back: usize,
305    /// Markers for type parameters.
306    _marker: PhantomData<(T, E)>,
307}
308
309impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVecIter<'a, T, E, B>
310where
311    SeqVecBitReader<'a, E>: CodesRead<E>,
312{
313    /// Creates a new iterator over all sequences.
314    ///
315    /// ## Arguments
316    ///
317    /// * `data` - The compressed data buffer.
318    /// * `bit_offsets` - The index of bit offsets for each sequence.
319    /// * `encoding` - The codec used for compression.
320    /// * `num_sequences` - The total number of sequences.
321    #[inline]
322    pub(crate) fn new(
323        data: &'a [u64],
324        bit_offsets: &'a FixedVec<u64, u64, E, B>,
325        seq_lengths: Option<&'a FixedVec<u64, u64, E, Vec<u64>>>,
326        encoding: Codes,
327        num_sequences: usize,
328    ) -> Self {
329        Self {
330            data,
331            bit_offsets,
332            seq_lengths,
333            encoding,
334            front: 0,
335            back: num_sequences,
336            _marker: PhantomData,
337        }
338    }
339
340    /// Returns the number of sequences remaining in this iterator.
341    #[inline]
342    pub fn remaining(&self) -> usize {
343        self.back.saturating_sub(self.front)
344    }
345}
346
347impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> Iterator for SeqVecIter<'a, T, E, B>
348where
349    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
350        + CodesRead<E>
351        + BitSeek<Error = core::convert::Infallible>,
352{
353    type Item = SeqIter<'a, T, E>;
354
355    #[inline]
356    fn next(&mut self) -> Option<Self::Item> {
357        if self.front >= self.back {
358            return None;
359        }
360
361        // SAFETY: front < back <= num_sequences, and bit_offsets has
362        // num_sequences + 1 elements, so indices front and front + 1 are valid.
363        let start_bit = unsafe { self.bit_offsets.get_unchecked(self.front) };
364        let end_bit = unsafe { self.bit_offsets.get_unchecked(self.front + 1) };
365        let len = self
366            .seq_lengths
367            .map(|lengths| unsafe { lengths.get_unchecked(self.front) as usize });
368
369        self.front += 1;
370
371        Some(SeqIter::new_with_len(
372            self.data,
373            start_bit,
374            end_bit,
375            self.encoding,
376            len,
377        ))
378    }
379
380    #[inline]
381    fn size_hint(&self) -> (usize, Option<usize>) {
382        let remaining = self.remaining();
383        (remaining, Some(remaining))
384    }
385
386    #[inline]
387    fn count(self) -> usize {
388        self.remaining()
389    }
390
391    #[inline]
392    fn nth(&mut self, n: usize) -> Option<Self::Item> {
393        if n >= self.remaining() {
394            self.front = self.back;
395            return None;
396        }
397        self.front += n;
398        self.next()
399    }
400}
401
402impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> DoubleEndedIterator
403    for SeqVecIter<'a, T, E, B>
404where
405    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
406        + CodesRead<E>
407        + BitSeek<Error = core::convert::Infallible>,
408{
409    #[inline]
410    fn next_back(&mut self) -> Option<Self::Item> {
411        if self.front >= self.back {
412            return None;
413        }
414
415        self.back -= 1;
416
417        // SAFETY: back was decremented from a value > front, so back is a valid
418        // index, and back + 1 <= original num_sequences.
419        let start_bit = unsafe { self.bit_offsets.get_unchecked(self.back) };
420        let end_bit = unsafe { self.bit_offsets.get_unchecked(self.back + 1) };
421        let len = self
422            .seq_lengths
423            .map(|lengths| unsafe { lengths.get_unchecked(self.back) as usize });
424
425        Some(SeqIter::new_with_len(
426            self.data,
427            start_bit,
428            end_bit,
429            self.encoding,
430            len,
431        ))
432    }
433
434    #[inline]
435    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
436        if n >= self.remaining() {
437            self.back = self.front;
438            return None;
439        }
440        self.back -= n;
441        self.next_back()
442    }
443}
444
445impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> ExactSizeIterator for SeqVecIter<'a, T, E, B>
446where
447    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
448        + CodesRead<E>
449        + BitSeek<Error = core::convert::Infallible>,
450{
451    #[inline]
452    fn len(&self) -> usize {
453        self.remaining()
454    }
455}
456
457impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> std::iter::FusedIterator
458    for SeqVecIter<'a, T, E, B>
459where
460    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
461        + CodesRead<E>
462        + BitSeek<Error = core::convert::Infallible>,
463{
464}
465
466/// An owning iterator over all sequences in a [`SeqVec`].
467///
468/// This iterator consumes a `SeqVec<T, E, Vec<u64>>` and yields [`SeqIter`]
469/// instances for each sequence. The iterator owns the underlying data buffer,
470/// ensuring it lives as long as the iterator.
471///
472/// ## Design
473///
474/// This is a self-referential struct similar to [`VarVecIntoIter`].
475/// The data buffer is stored in `_data_owner`, and a transmuted `'static` reference
476/// is used to create the reader. This is safe because `_data_owner` is part of
477/// the same struct, guaranteeing the data outlives the reader.
478///
479/// ## Bit Offsets Storage
480///
481/// Rather than decoding all offsets from the [`FixedVec`] upfront (O(n) operation),
482/// we store the raw bit width and offsets backing storage. Offsets are decoded
483/// lazily during iteration via `get_offset()`.
484///
485/// [`SeqVec`]: crate::seq::SeqVec
486/// [`VarVecIntoIter`]: crate::variable::iter::VarVecIntoIter
487/// [`FixedVec`]: crate::fixed::FixedVec
488///
489/// ## Trait Implementations
490///
491/// - [`Iterator`]: Core iteration.
492/// - [`ExactSizeIterator`]: The number of sequences is known.
493/// - [`DoubleEndedIterator`]: Supports iteration from both ends.
494/// - [`std::iter::FusedIterator`]: After `None`, always returns `None`.
495///
496/// ## Examples
497///
498/// ```
499/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
500/// use compressed_intvec::seq::{SeqVec, LESeqVec};
501///
502/// let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5]];
503/// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
504///
505/// // Consume the vec and iterate over sequences
506/// let mut count = 0;
507/// for seq in vec {
508///     count += 1;
509///     let _ = seq.collect::<Vec<_>>();
510/// }
511/// assert_eq!(count, 2);
512/// #     Ok(())
513/// # }
514/// ```
515pub struct SeqVecIntoIter<T, E>
516where
517    T: Storable + 'static,
518    E: Endianness + 'static,
519    for<'a> SeqVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
520        + CodesRead<E>
521        + BitSeek<Error = core::convert::Infallible>,
522{
523    // Immutable fields (configuration and backing storage)
524    /// Reference to the compressed data buffer. This is a transmuted reference
525    /// that is guaranteed to be valid for the lifetime of `_data_owner`.
526    data: &'static [u64],
527    /// The codec used for decoding.
528    encoding: Codes,
529    /// The bit offsets backing storage (raw limbs).
530    bit_offsets_data: &'static [u64],
531    /// Number of bits per offset value.
532    bit_offsets_num_bits: u64,
533    /// Total number of bit offsets (including sentinel at N+1).
534    bit_offsets_len: usize,
535    /// Optional stored sequence lengths.
536    seq_lengths: Option<FixedVec<u64, u64, E, Vec<u64>>>,
537    /// This field owns the data buffer, ensuring it lives as long as the iterator.
538    _data_owner: Vec<u64>,
539    /// This field owns the bit offsets buffer.
540    _bit_offsets_owner: Vec<u64>,
541
542    // Mutable fields (iteration state)
543    /// The number of sequences remaining in the iterator.
544    num_sequences: usize,
545    /// The current sequence index being iterated.
546    current_index: usize,
547    /// Cached end_bit from previous iteration to avoid redundant offset decoding.
548    /// For sequential access, the end_bit of iteration i becomes start_bit of iteration i+1.
549    last_end_bit: u64,
550
551    // Marker fields
552    /// Phantom data to hold the generic types.
553    _markers: PhantomData<(T, E)>,
554}
555
556impl<T, E> SeqVecIntoIter<T, E>
557where
558    T: Storable + 'static,
559    E: Endianness + 'static,
560    for<'a> SeqVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
561        + CodesRead<E>
562        + BitSeek<Error = core::convert::Infallible>,
563{
564    /// Creates a new owning iterator from a [`SeqVec`] with owned data.
565    ///
566    /// This constructor avoids decoding all offsets upfront. Instead, it stores
567    /// the raw bit width and backing data of the [`FixedVec`], allowing offsets
568    /// to be decoded lazily during iteration.
569    ///
570    /// [`SeqVec`]: crate::seq::SeqVec
571    /// [`FixedVec`]: crate::fixed::FixedVec
572    pub(crate) fn new(vec: super::SeqVec<T, E, Vec<u64>>) -> Self {
573        let encoding = vec.encoding;
574        let num_sequences = vec.num_sequences();
575        let seq_lengths = vec.seq_lengths;
576        let _data_owner = vec.data;
577        let _bit_offsets_owner = vec.bit_offsets.as_limbs().to_vec();
578
579        // Store bit offset metadata for lazy decoding during iteration.
580        let bit_offsets_num_bits = vec.bit_offsets.bit_width() as u64;
581        let bit_offsets_len = vec.bit_offsets.len();
582
583        // Create transmuted 'static references. This is safe because _data_owner
584        // and _bit_offsets_owner are part of this struct.
585        let data_ref: &'static [u64] = unsafe { std::mem::transmute(_data_owner.as_slice()) };
586        let bit_offsets_ref: &'static [u64] =
587            unsafe { std::mem::transmute(_bit_offsets_owner.as_slice()) };
588
589        Self {
590            data: data_ref,
591            encoding,
592            bit_offsets_data: bit_offsets_ref,
593            bit_offsets_num_bits,
594            bit_offsets_len,
595            seq_lengths,
596            _data_owner,
597            _bit_offsets_owner,
598            num_sequences,
599            current_index: 0,
600            last_end_bit: 0,
601            _markers: PhantomData,
602        }
603    }
604
605    /// Lazily decodes the bit offset for the given index.
606    ///
607    /// This avoids decoding all offsets upfront, achieving O(1) amortized cost
608    /// during forward iteration.
609    #[inline]
610    fn get_offset(&self, index: usize) -> u64 {
611        if index >= self.bit_offsets_len {
612            return 0; // Out of bounds: return sentinel
613        }
614
615        let offset_bits = self.bit_offsets_num_bits;
616        let start_bit = (index as u64) * offset_bits;
617
618        // Create a reader over the bit offsets data and extract the value.
619        let mut reader = SeqVecBitReader::<E>::new(MemWordReader::new_inf(self.bit_offsets_data));
620        let _ = reader.set_bit_pos(start_bit);
621
622        // Read the offset value. For typical cases with explicit bit widths,
623        // this is a simple bit extraction.
624        reader.read_bits(offset_bits as usize).unwrap_or(0)
625    }
626}
627
628impl<T, E> Iterator for SeqVecIntoIter<T, E>
629where
630    T: Storable + 'static,
631    E: Endianness + 'static,
632    for<'a> SeqVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
633        + CodesRead<E>
634        + BitSeek<Error = core::convert::Infallible>,
635{
636    type Item = SeqIter<'static, T, E>;
637
638    #[inline]
639    fn next(&mut self) -> Option<Self::Item> {
640        if self.current_index >= self.num_sequences {
641            return None;
642        }
643
644        // Optimize sequential access: reuse cached end_bit from previous iteration.
645        // For forward iteration, the end_bit of iteration i becomes the start_bit
646        // of iteration i+1, eliminating a redundant offset decode operation.
647        let start_bit = if self.current_index == 0 {
648            self.get_offset(0)
649        } else {
650            self.last_end_bit
651        };
652
653        let end_bit = self.get_offset(self.current_index + 1);
654        self.last_end_bit = end_bit;
655
656        let len = self
657            .seq_lengths
658            .as_ref()
659            .map(|lengths| unsafe { lengths.get_unchecked(self.current_index) as usize });
660
661        self.current_index += 1;
662
663        Some(SeqIter::new_with_len(
664            self.data,
665            start_bit,
666            end_bit,
667            self.encoding,
668            len,
669        ))
670    }
671
672    #[inline]
673    fn size_hint(&self) -> (usize, Option<usize>) {
674        let remaining = self.num_sequences.saturating_sub(self.current_index);
675        (remaining, Some(remaining))
676    }
677}
678
679impl<T, E> ExactSizeIterator for SeqVecIntoIter<T, E>
680where
681    T: Storable + 'static,
682    E: Endianness + 'static,
683    for<'a> SeqVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
684        + CodesRead<E>
685        + BitSeek<Error = core::convert::Infallible>,
686{
687    #[inline]
688    fn len(&self) -> usize {
689        self.num_sequences.saturating_sub(self.current_index)
690    }
691}
692
693impl<T, E> DoubleEndedIterator for SeqVecIntoIter<T, E>
694where
695    T: Storable + 'static,
696    E: Endianness + 'static,
697    for<'a> SeqVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
698        + CodesRead<E>
699        + BitSeek<Error = core::convert::Infallible>,
700{
701    #[inline]
702    fn next_back(&mut self) -> Option<Self::Item> {
703        if self.current_index >= self.num_sequences {
704            return None;
705        }
706
707        self.num_sequences -= 1;
708
709        let start_bit = self.get_offset(self.num_sequences);
710        let end_bit = self.get_offset(self.num_sequences + 1);
711
712        let len = self
713            .seq_lengths
714            .as_ref()
715            .map(|lengths| unsafe { lengths.get_unchecked(self.num_sequences) as usize });
716
717        Some(SeqIter::new_with_len(
718            self.data,
719            start_bit,
720            end_bit,
721            self.encoding,
722            len,
723        ))
724    }
725}
726
727impl<T, E> std::iter::FusedIterator for SeqVecIntoIter<T, E>
728where
729    T: Storable + 'static,
730    E: Endianness + 'static,
731    for<'a> SeqVecBitReader<'a, E>: BitRead<E, Error = core::convert::Infallible>
732        + CodesRead<E>
733        + BitSeek<Error = core::convert::Infallible>,
734{
735}