1- //! # `FixedVec` Iterators
1+ //! # [ `FixedVec`] Iterators
22//!
33//! This module provides iterators for sequential access to the elements of a
44//! [`FixedVec`]. The iterators decode values on the fly without allocating an
55//! intermediate buffer, making them efficient for processing large datasets.
66//!
7+ //! The core iterators ([`FixedVecIter`], [`FixedVecSliceIter`]) are stateful and
8+ //! employ a bit-windowing technique. They decode values on the fly without
9+ //! allocating an intermediate buffer. They support both forward and reverse
10+ //! iteration.
11+ //!
712//! # Provided Iterators
813//!
9- //! - [`FixedVecIter`]: A bidirectional iterator over the elements of a `FixedVec`.
10- //! - [`FixedVecIntoIter`]: A consuming iterator that takes ownership of a `FixedVec`.
11- //! - [`Chunks`]: An iterator that yields non-overlapping, immutable slices.
12- //! - [`Windows`]: An iterator that yields overlapping, immutable slices.
14+ //! - [`FixedVecIter`]: A stateful, bidirectional iterator over the elements of a borrowed [`FixedVec`].
15+ //! - [`FixedVecIntoIter`]: A consuming, bidirectional iterator that takes ownership of a [`FixedVec`].
16+ //! - [`FixedVecSliceIter`]: A stateful, bidirectional iterator over the elements of a [`FixedVecSlice`].
17+ //! - [`Chunks`]: An iterator that yields non-overlapping, immutable slices ([`FixedVecSlice`]).
18+ //! - [`Windows`]: An iterator that yields overlapping, immutable slices ([`FixedVecSlice`]).
19+ //! - [`FixedVecUncheckedIter`]: An `unsafe` bidirectional iterator that omits bounds checks for maximum performance.
1320//!
1421//! # Examples
1522//!
2835//!
2936//! assert_eq!(sum, 200);
3037//! ```
38+ //!
39+ //! ## Bidirectional Iteration
40+ //!
41+ //! The main iterators implement [`DoubleEndedIterator`], allowing for
42+ //! traversal from both ends of the sequence.
43+ //!
44+ //! ```rust
45+ //! use compressed_intvec::fixed::{FixedVec, UFixedVec};
46+ //!
47+ //! let vec: UFixedVec<u8> = (0..=5u8).collect();
48+ //! let mut iter = vec.iter();
49+ //!
50+ //! assert_eq!(iter.next(), Some(0));
51+ //! assert_eq!(iter.next_back(), Some(5));
52+ //! assert_eq!(iter.next(), Some(1));
53+ //! assert_eq!(iter.next_back(), Some(4));
54+ //!
55+ //! // The iterator correctly tracks its remaining length.
56+ //! assert_eq!(iter.len(), 2);
57+ //!
58+ //! assert_eq!(iter.next(), Some(2));
59+ //! assert_eq!(iter.next(), Some(3));
60+ //! assert_eq!(iter.next(), None);
61+ //! ```
62+ //!
63+ //! ## Iterating over a Slice
64+ //!
65+ //! You can also create an iterator over a zero-copy slice of a vector.
66+ //!
67+ //! ```rust
68+ //! use compressed_intvec::fixed::{FixedVec, UFixedVec};
69+ //!
70+ //! let vec: UFixedVec<u32> = (0..100u32).collect();
71+ //!
72+ //! // Create a slice containing elements from index 20 to 29.
73+ //! let slice = vec.slice(20, 10).unwrap();
74+ //! assert_eq!(slice.len(), 10);
75+ //!
76+ //! // The slice iterator will yield the elements from the slice.
77+ //! let collected: Vec<u32> = slice.iter().collect();
78+ //! let expected: Vec<u32> = (20..30).collect();
79+ //!
80+ //! assert_eq!(collected, expected);
81+ //! ```
3182
3283use crate :: fixed:: {
3384 slice:: FixedVecSlice ,
@@ -119,7 +170,7 @@ where
119170 E : Endianness ,
120171 B : AsRef < [ W ] > ,
121172{
122- /// Creates a new stateful, bidirectional iterator for a given `FixedVec`.
173+ /// Creates a new stateful, bidirectional iterator for a given [ `FixedVec`] .
123174 pub ( super ) fn new ( vec : & ' a FixedVec < T , W , E , B > ) -> Self {
124175 if vec. is_empty ( ) {
125176 return Self {
@@ -137,7 +188,7 @@ where
137188 }
138189
139190 let limbs = vec. as_limbs ( ) ;
140- let bits_per_word = <W as Word >:: BITS ;
191+ let bits_per_word: usize = <W as Word >:: BITS ;
141192
142193 // --- Setup forward state ---
143194 let front_word_index = 1 ;
@@ -257,7 +308,7 @@ where
257308 }
258309
259310 let bit_width = self . vec . bit_width ( ) ;
260- let bits_per_word = <W as Word >:: BITS ;
311+ let bits_per_word: usize = <W as Word >:: BITS ;
261312
262313 if self . back_bits_in_window >= bit_width {
263314 self . back_bits_in_window -= bit_width;
@@ -354,6 +405,19 @@ where
354405 }
355406}
356407
408+ impl < T , W , E , B > DoubleEndedIterator for FixedVecIntoIter < ' _ , T , W , E , B >
409+ where
410+ T : Storable < W > ,
411+ W : Word ,
412+ E : Endianness ,
413+ B : AsRef < [ W ] > ,
414+ {
415+ #[ inline]
416+ fn next_back ( & mut self ) -> Option < Self :: Item > {
417+ self . iter . next_back ( )
418+ }
419+ }
420+
357421impl < T , W , E , B > ExactSizeIterator for FixedVecIntoIter < ' _ , T , W , E , B >
358422where
359423 T : Storable < W > ,
@@ -369,7 +433,8 @@ where
369433/// An iterator over the elements of a [`FixedVecSlice`].
370434///
371435/// This struct is created by the [`iter`](super::slice::FixedVecSlice::iter)
372- /// method on [`FixedVecSlice`].
436+ /// method on [`FixedVecSlice`]. It is a stateful bitstream reader that decodes
437+ /// values on the fly for both forward and reverse iteration.
373438pub struct FixedVecSliceIter < ' s , T , W , E , B , V >
374439where
375440 T : Storable < W > ,
@@ -379,7 +444,19 @@ where
379444 V : Deref < Target = FixedVec < T , W , E , B > > ,
380445{
381446 slice : & ' s FixedVecSlice < V > ,
382- current_index : usize ,
447+ front_index : usize , // index relative to slice start
448+ back_index : usize , // index relative to slice start
449+
450+ // State for forward iteration.
451+ front_window : W ,
452+ front_bits_in_window : usize ,
453+ front_word_index : usize ,
454+
455+ // State for backward iteration.
456+ back_window : W ,
457+ back_bits_in_window : usize ,
458+ back_word_index : usize ,
459+
383460 _phantom : PhantomData < ( T , W , E , B ) > ,
384461}
385462
@@ -391,11 +468,62 @@ where
391468 B : AsRef < [ W ] > ,
392469 V : Deref < Target = FixedVec < T , W , E , B > > ,
393470{
394- /// Creates a new iterator for a given `FixedVecSlice`.
471+ /// Creates a new stateful, bidirectional iterator for a given `FixedVecSlice`.
395472 pub ( super ) fn new ( slice : & ' s FixedVecSlice < V > ) -> Self {
473+ let parent_vec = & slice. parent ;
474+ if slice. is_empty ( ) {
475+ return Self {
476+ slice,
477+ front_index : 0 ,
478+ back_index : 0 ,
479+ front_window : W :: ZERO ,
480+ front_bits_in_window : 0 ,
481+ front_word_index : 0 ,
482+ back_window : W :: ZERO ,
483+ back_bits_in_window : 0 ,
484+ back_word_index : 0 ,
485+ _phantom : PhantomData ,
486+ } ;
487+ }
488+
489+ let bits_per_word: usize = <W as Word >:: BITS ;
490+ let bit_width: usize = parent_vec. bit_width ( ) ;
491+ let limbs: & [ W ] = parent_vec. as_limbs ( ) ;
492+ let slice_start_abs: usize = slice. range . start ;
493+ let slice_end_abs: usize = slice. range . end ;
494+
495+ // --- Setup forward state ---
496+ let start_bit_pos: usize = slice_start_abs * bit_width;
497+ let start_word_index: usize = start_bit_pos / bits_per_word;
498+ let start_bit_offset: usize = start_bit_pos % bits_per_word;
499+
500+ let front_window_raw: W = unsafe { * limbs. get_unchecked ( start_word_index) } ;
501+ let front_window: W = front_window_raw >> start_bit_offset;
502+ let front_bits_in_window: usize = bits_per_word - start_bit_offset;
503+ let front_word_index: usize = start_word_index + 1 ;
504+
505+ // --- Setup backward state ---
506+ let end_bit_pos: usize = slice_end_abs * bit_width;
507+ let back_word_index: usize = ( end_bit_pos. saturating_sub ( 1 ) ) / bits_per_word;
508+ let back_window: W = unsafe { * limbs. get_unchecked ( back_word_index) } ;
509+
510+ let back_bits_in_window = end_bit_pos % bits_per_word;
511+ let back_bits_in_window = if back_bits_in_window == 0 && end_bit_pos > 0 {
512+ bits_per_word
513+ } else {
514+ back_bits_in_window
515+ } ;
516+
396517 Self {
397518 slice,
398- current_index : 0 ,
519+ front_index : 0 ,
520+ back_index : slice. len ( ) ,
521+ front_window,
522+ front_bits_in_window,
523+ front_word_index,
524+ back_window,
525+ back_bits_in_window,
526+ back_word_index,
399527 _phantom : PhantomData ,
400528 }
401529 }
@@ -413,21 +541,107 @@ where
413541
414542 #[ inline]
415543 fn next ( & mut self ) -> Option < Self :: Item > {
416- if self . current_index >= self . slice . len ( ) {
544+ if self . front_index >= self . back_index {
417545 return None ;
418546 }
419- // SAFETY: The iterator's logic guarantees the index is in bounds.
420- let value = unsafe { self . slice . get_unchecked ( self . current_index ) } ;
421- self . current_index += 1 ;
422- Some ( value)
547+
548+ let parent_vec = & self . slice . parent ;
549+ let bit_width = parent_vec. bit_width ( ) ;
550+ let mask = parent_vec. mask ;
551+
552+ let abs_index = self . slice . range . start + self . front_index ;
553+ self . front_index += 1 ;
554+
555+ if bit_width == <W as Word >:: BITS {
556+ let val = unsafe { * parent_vec. as_limbs ( ) . get_unchecked ( abs_index) } ;
557+ let final_val = if E :: IS_BIG { W :: from_be ( val) } else { val } ;
558+ return Some ( <T as Storable < W > >:: from_word ( final_val) ) ;
559+ }
560+
561+ if E :: IS_BIG {
562+ return Some ( unsafe { parent_vec. get_unchecked ( abs_index) } ) ;
563+ }
564+
565+ if self . front_bits_in_window >= bit_width {
566+ let value = self . front_window & mask;
567+ self . front_window >>= bit_width;
568+ self . front_bits_in_window -= bit_width;
569+ return Some ( <T as Storable < W > >:: from_word ( value) ) ;
570+ }
571+
572+ unsafe {
573+ let limbs = parent_vec. as_limbs ( ) ;
574+ let bits_from_old = self . front_bits_in_window ;
575+ let mut result = self . front_window ;
576+
577+ self . front_window = * limbs. get_unchecked ( self . front_word_index ) ;
578+ self . front_word_index += 1 ;
579+ result |= self . front_window << bits_from_old;
580+ let value = result & mask;
581+
582+ let bits_from_new = bit_width - bits_from_old;
583+ self . front_window >>= bits_from_new;
584+ self . front_bits_in_window = <W as Word >:: BITS - bits_from_new;
585+
586+ Some ( <T as Storable < W > >:: from_word ( value) )
587+ }
423588 }
424589
425590 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
426- let remaining = self . slice . len ( ) . saturating_sub ( self . current_index ) ;
591+ let remaining = self . back_index . saturating_sub ( self . front_index ) ;
427592 ( remaining, Some ( remaining) )
428593 }
429594}
430595
596+ impl < T , W , E , B , V > DoubleEndedIterator for FixedVecSliceIter < ' _ , T , W , E , B , V >
597+ where
598+ T : Storable < W > ,
599+ W : Word ,
600+ E : Endianness ,
601+ B : AsRef < [ W ] > ,
602+ V : Deref < Target = FixedVec < T , W , E , B > > ,
603+ {
604+ #[ inline]
605+ fn next_back ( & mut self ) -> Option < Self :: Item > {
606+ if self . front_index >= self . back_index {
607+ return None ;
608+ }
609+ self . back_index -= 1 ;
610+ let abs_index = self . slice . range . start + self . back_index ;
611+ let parent_vec = & self . slice . parent ;
612+
613+ if E :: IS_BIG || parent_vec. bit_width ( ) == <W as Word >:: BITS {
614+ return Some ( unsafe { parent_vec. get_unchecked ( abs_index) } ) ;
615+ }
616+
617+ let bit_width = parent_vec. bit_width ( ) ;
618+ let bits_per_word: usize = <W as Word >:: BITS ;
619+
620+ if self . back_bits_in_window >= bit_width {
621+ self . back_bits_in_window -= bit_width;
622+ let value = ( self . back_window >> self . back_bits_in_window ) & parent_vec. mask ;
623+ return Some ( <T as Storable < W > >:: from_word ( value) ) ;
624+ }
625+
626+ unsafe {
627+ let limbs = parent_vec. as_limbs ( ) ;
628+ let bits_from_old = self . back_bits_in_window ;
629+ let mut result = self . back_window ;
630+
631+ self . back_word_index -= 1 ;
632+ self . back_window = * limbs. get_unchecked ( self . back_word_index ) ;
633+
634+ result &= ( W :: ONE << bits_from_old) . wrapping_sub ( W :: ONE ) ;
635+ let bits_from_new = bit_width - bits_from_old;
636+ result <<= bits_from_new;
637+ result |= self . back_window >> ( bits_per_word - bits_from_new) ;
638+
639+ self . back_bits_in_window = bits_per_word - bits_from_new;
640+ Some ( <T as Storable < W > >:: from_word ( result) )
641+ }
642+ }
643+ }
644+
431645impl < T , W , E , B , V > ExactSizeIterator for FixedVecSliceIter < ' _ , T , W , E , B , V >
432646where
433647 T : Storable < W > ,
@@ -437,7 +651,7 @@ where
437651 V : Deref < Target = FixedVec < T , W , E , B > > ,
438652{
439653 fn len ( & self ) -> usize {
440- self . slice . len ( ) . saturating_sub ( self . current_index )
654+ self . back_index . saturating_sub ( self . front_index )
441655 }
442656}
443657
@@ -578,4 +792,14 @@ where
578792 // The primary gain here is removing the check in `next()`.
579793 self . iter . next ( ) . unwrap_unchecked ( )
580794 }
581- }
795+
796+ /// Returns the next element from the back without bounds checking.
797+ ///
798+ /// # Safety
799+ ///
800+ /// Calling this method when the iterator is exhausted is undefined behavior.
801+ #[ inline]
802+ pub unsafe fn next_back_unchecked ( & mut self ) -> T {
803+ self . iter . next_back ( ) . unwrap_unchecked ( )
804+ }
805+ }
0 commit comments