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}