use crate::fixed::{
FixedVec,
slice::FixedVecSlice,
traits::{Storable, Word},
};
use dsi_bitstream::prelude::Endianness;
use std::{marker::PhantomData, ops::Deref};
use std::cmp::min;
#[derive(Debug)]
pub struct FixedVecIter<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
vec: &'a FixedVec<T, W, E, B>,
front_index: usize,
back_index: usize,
front_window: W,
front_bits_in_window: usize,
front_word_index: usize,
back_window: W,
back_bits_in_window: usize,
back_word_index: usize,
_phantom: PhantomData<T>,
}
#[derive(Debug)]
pub struct Chunks<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
vec: &'a FixedVec<T, W, E, B>,
chunk_size: usize,
current_pos: usize,
}
impl<'a, T, W, E, B> FixedVecIter<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
pub(super) fn new(vec: &'a FixedVec<T, W, E, B>) -> Self {
if vec.is_empty() {
return Self {
vec,
front_index: 0,
back_index: 0,
front_window: W::ZERO,
front_bits_in_window: 0,
front_word_index: 0,
back_window: W::ZERO,
back_bits_in_window: 0,
back_word_index: 0,
_phantom: PhantomData,
};
}
let limbs = vec.as_limbs();
let bits_per_word: usize = <W as Word>::BITS;
let front_word_index = 1;
let front_window = unsafe { *limbs.get_unchecked(0) };
let front_bits_in_window = bits_per_word;
let total_bits = vec.len() * vec.bit_width();
let back_word_index = (total_bits.saturating_sub(1)) / bits_per_word;
let back_window = unsafe { *limbs.get_unchecked(back_word_index) };
let back_bits_in_window = total_bits % bits_per_word;
let back_bits_in_window = if back_bits_in_window == 0 {
bits_per_word
} else {
back_bits_in_window
};
Self {
vec,
front_index: 0,
back_index: vec.len(),
front_window,
front_bits_in_window,
front_word_index,
back_window,
back_bits_in_window,
back_word_index,
_phantom: PhantomData,
}
}
}
impl<T, W, E, B> Iterator for FixedVecIter<'_, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.front_index >= self.back_index {
return None;
}
let index = self.front_index;
self.front_index += 1;
let bit_width = self.vec.bit_width();
if bit_width == <W as Word>::BITS {
let val = unsafe { *self.vec.as_limbs().get_unchecked(index) };
let final_val = if E::IS_BIG { W::from_be(val) } else { val };
return Some(<T as Storable<W>>::from_word(final_val));
}
if E::IS_BIG {
return Some(unsafe { self.vec.get_unchecked(index) });
}
let mask = self.vec.mask;
if self.front_bits_in_window >= bit_width {
let value = self.front_window & mask;
self.front_window >>= bit_width;
self.front_bits_in_window -= bit_width;
return Some(<T as Storable<W>>::from_word(value));
}
unsafe {
let limbs = self.vec.as_limbs();
let bits_from_old = self.front_bits_in_window;
let mut result = self.front_window;
self.front_window = *limbs.get_unchecked(self.front_word_index);
self.front_word_index += 1;
result |= self.front_window << bits_from_old;
let value = result & mask;
let bits_from_new = bit_width - bits_from_old;
self.front_window >>= bits_from_new;
self.front_bits_in_window = <W as Word>::BITS - bits_from_new;
Some(<T as Storable<W>>::from_word(value))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.back_index.saturating_sub(self.front_index);
(remaining, Some(remaining))
}
}
impl<T, W, E, B> DoubleEndedIterator for FixedVecIter<'_, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
if self.front_index >= self.back_index {
return None;
}
self.back_index -= 1;
let index = self.back_index;
if E::IS_BIG || self.vec.bit_width() == <W as Word>::BITS {
return Some(unsafe { self.vec.get_unchecked(index) });
}
let bit_width = self.vec.bit_width();
let bits_per_word: usize = <W as Word>::BITS;
if self.back_bits_in_window >= bit_width {
self.back_bits_in_window -= bit_width;
let value = (self.back_window >> self.back_bits_in_window) & self.vec.mask;
return Some(<T as Storable<W>>::from_word(value));
}
unsafe {
let limbs = self.vec.as_limbs();
let bits_from_old = self.back_bits_in_window;
let mut result = self.back_window;
self.back_word_index -= 1;
self.back_window = *limbs.get_unchecked(self.back_word_index);
result &= (W::ONE << bits_from_old).wrapping_sub(W::ONE);
let bits_from_new = bit_width - bits_from_old;
result <<= bits_from_new;
result |= self.back_window >> (bits_per_word - bits_from_new);
self.back_bits_in_window = bits_per_word - bits_from_new;
Some(<T as Storable<W>>::from_word(result))
}
}
}
impl<T, W, E, B> ExactSizeIterator for FixedVecIter<'_, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
fn len(&self) -> usize {
self.back_index.saturating_sub(self.front_index)
}
}
pub struct FixedVecIntoIter<T, W, E>
where
T: Storable<W> + 'static,
W: Word,
E: Endianness,
{
iter: FixedVecIter<'static, T, W, E, Vec<W>>,
_vec_owner: Box<FixedVec<T, W, E, Vec<W>>>,
}
impl<T, W, E> FixedVecIntoIter<T, W, E>
where
T: Storable<W> + 'static,
W: Word,
E: Endianness,
{
pub(super) fn new(vec: FixedVec<T, W, E, Vec<W>>) -> Self {
let boxed = Box::new(vec);
let iter = unsafe {
let vec_ref: &'static FixedVec<T, W, E, Vec<W>> =
std::mem::transmute(&*boxed as &FixedVec<T, W, E, Vec<W>>);
FixedVecIter::new(vec_ref)
};
Self {
iter,
_vec_owner: boxed,
}
}
}
impl<T, W, E> Iterator for FixedVecIntoIter<T, W, E>
where
T: Storable<W> + 'static,
W: Word,
E: Endianness,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T, W, E> DoubleEndedIterator for FixedVecIntoIter<T, W, E>
where
T: Storable<W> + 'static,
W: Word,
E: Endianness,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
}
impl<T, W, E> ExactSizeIterator for FixedVecIntoIter<T, W, E>
where
T: Storable<W> + 'static,
W: Word,
E: Endianness,
{
fn len(&self) -> usize {
self.iter.len()
}
}
pub struct FixedVecSliceIter<'s, T, W, E, B, V>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
V: Deref<Target = FixedVec<T, W, E, B>>,
{
slice: &'s FixedVecSlice<V>,
front_index: usize, back_index: usize,
front_window: W,
front_bits_in_window: usize,
front_word_index: usize,
back_window: W,
back_bits_in_window: usize,
back_word_index: usize,
_phantom: PhantomData<(T, W, E, B)>,
}
impl<'s, T, W, E, B, V> FixedVecSliceIter<'s, T, W, E, B, V>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
V: Deref<Target = FixedVec<T, W, E, B>>,
{
pub(super) fn new(slice: &'s FixedVecSlice<V>) -> Self {
let parent_vec = &slice.parent;
if slice.is_empty() {
return Self {
slice,
front_index: 0,
back_index: 0,
front_window: W::ZERO,
front_bits_in_window: 0,
front_word_index: 0,
back_window: W::ZERO,
back_bits_in_window: 0,
back_word_index: 0,
_phantom: PhantomData,
};
}
let bits_per_word: usize = <W as Word>::BITS;
let bit_width: usize = parent_vec.bit_width();
let limbs: &[W] = parent_vec.as_limbs();
let slice_start_abs: usize = slice.range.start;
let slice_end_abs: usize = slice.range.end;
let start_bit_pos: usize = slice_start_abs * bit_width;
let start_word_index: usize = start_bit_pos / bits_per_word;
let start_bit_offset: usize = start_bit_pos % bits_per_word;
let front_window_raw: W = unsafe { *limbs.get_unchecked(start_word_index) };
let front_window: W = front_window_raw >> start_bit_offset;
let front_bits_in_window: usize = bits_per_word - start_bit_offset;
let front_word_index: usize = start_word_index + 1;
let end_bit_pos: usize = slice_end_abs * bit_width;
let back_word_index: usize = (end_bit_pos.saturating_sub(1)) / bits_per_word;
let back_window: W = unsafe { *limbs.get_unchecked(back_word_index) };
let back_bits_in_window = end_bit_pos % bits_per_word;
let back_bits_in_window = if back_bits_in_window == 0 && end_bit_pos > 0 {
bits_per_word
} else {
back_bits_in_window
};
Self {
slice,
front_index: 0,
back_index: slice.len(),
front_window,
front_bits_in_window,
front_word_index,
back_window,
back_bits_in_window,
back_word_index,
_phantom: PhantomData,
}
}
}
impl<T, W, E, B, V> Iterator for FixedVecSliceIter<'_, T, W, E, B, V>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
V: Deref<Target = FixedVec<T, W, E, B>>,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.front_index >= self.back_index {
return None;
}
let parent_vec = &self.slice.parent;
let bit_width = parent_vec.bit_width();
let mask = parent_vec.mask;
let abs_index = self.slice.range.start + self.front_index;
self.front_index += 1;
if bit_width == <W as Word>::BITS {
let val = unsafe { *parent_vec.as_limbs().get_unchecked(abs_index) };
let final_val = if E::IS_BIG { W::from_be(val) } else { val };
return Some(<T as Storable<W>>::from_word(final_val));
}
if E::IS_BIG {
return Some(unsafe { parent_vec.get_unchecked(abs_index) });
}
if self.front_bits_in_window >= bit_width {
let value = self.front_window & mask;
self.front_window >>= bit_width;
self.front_bits_in_window -= bit_width;
return Some(<T as Storable<W>>::from_word(value));
}
unsafe {
let limbs = parent_vec.as_limbs();
let bits_from_old = self.front_bits_in_window;
let mut result = self.front_window;
self.front_window = *limbs.get_unchecked(self.front_word_index);
self.front_word_index += 1;
result |= self.front_window << bits_from_old;
let value = result & mask;
let bits_from_new = bit_width - bits_from_old;
self.front_window >>= bits_from_new;
self.front_bits_in_window = <W as Word>::BITS - bits_from_new;
Some(<T as Storable<W>>::from_word(value))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.back_index.saturating_sub(self.front_index);
(remaining, Some(remaining))
}
}
impl<T, W, E, B, V> DoubleEndedIterator for FixedVecSliceIter<'_, T, W, E, B, V>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
V: Deref<Target = FixedVec<T, W, E, B>>,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
if self.front_index >= self.back_index {
return None;
}
self.back_index -= 1;
let abs_index = self.slice.range.start + self.back_index;
let parent_vec = &self.slice.parent;
if E::IS_BIG || parent_vec.bit_width() == <W as Word>::BITS {
return Some(unsafe { parent_vec.get_unchecked(abs_index) });
}
let bit_width = parent_vec.bit_width();
let bits_per_word: usize = <W as Word>::BITS;
if self.back_bits_in_window >= bit_width {
self.back_bits_in_window -= bit_width;
let value = (self.back_window >> self.back_bits_in_window) & parent_vec.mask;
return Some(<T as Storable<W>>::from_word(value));
}
unsafe {
let limbs = parent_vec.as_limbs();
let bits_from_old = self.back_bits_in_window;
let mut result = self.back_window;
self.back_word_index -= 1;
self.back_window = *limbs.get_unchecked(self.back_word_index);
result &= (W::ONE << bits_from_old).wrapping_sub(W::ONE);
let bits_from_new = bit_width - bits_from_old;
result <<= bits_from_new;
result |= self.back_window >> (bits_per_word - bits_from_new);
self.back_bits_in_window = bits_per_word - bits_from_new;
Some(<T as Storable<W>>::from_word(result))
}
}
}
impl<T, W, E, B, V> ExactSizeIterator for FixedVecSliceIter<'_, T, W, E, B, V>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
V: Deref<Target = FixedVec<T, W, E, B>>,
{
fn len(&self) -> usize {
self.back_index.saturating_sub(self.front_index)
}
}
impl<'a, T, W, E, B> Chunks<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
pub(super) fn new(vec: &'a FixedVec<T, W, E, B>, chunk_size: usize) -> Self {
assert!(chunk_size != 0, "chunk_size cannot be zero");
Self {
vec,
chunk_size,
current_pos: 0,
}
}
}
impl<'a, T, W, E, B> Iterator for Chunks<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
type Item = FixedVecSlice<&'a FixedVec<T, W, E, B>>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_pos >= self.vec.len() {
return None;
}
let len = min(self.chunk_size, self.vec.len() - self.current_pos);
let slice = FixedVecSlice::new(self.vec, self.current_pos..self.current_pos + len);
self.current_pos += len;
Some(slice)
}
}
pub struct Windows<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
vec: &'a FixedVec<T, W, E, B>,
size: usize,
current_pos: usize,
}
impl<'a, T, W, E, B> Windows<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
pub(super) fn new(vec: &'a FixedVec<T, W, E, B>, size: usize) -> Self {
Self {
vec,
size,
current_pos: 0,
}
}
}
impl<'a, T, W, E, B> Iterator for Windows<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
type Item = FixedVecSlice<&'a FixedVec<T, W, E, B>>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_pos + self.size > self.vec.len() {
return None;
}
let slice = FixedVecSlice::new(self.vec, self.current_pos..self.current_pos + self.size);
self.current_pos += 1;
Some(slice)
}
}
pub struct FixedVecUncheckedIter<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
iter: FixedVecIter<'a, T, W, E, B>,
}
impl<'a, T, W, E, B> FixedVecUncheckedIter<'a, T, W, E, B>
where
T: Storable<W>,
W: Word,
E: Endianness,
B: AsRef<[W]>,
{
pub(super) fn new(vec: &'a FixedVec<T, W, E, B>) -> Self {
Self {
iter: FixedVecIter::new(vec),
}
}
#[inline]
pub unsafe fn next_unchecked(&mut self) -> T {
unsafe { self.iter.next().unwrap_unchecked() }
}
#[inline]
pub unsafe fn next_back_unchecked(&mut self) -> T {
unsafe { self.iter.next_back().unwrap_unchecked() }
}
}