use super::{traits::Storable, VarVec, VarVecBitReader};
use dsi_bitstream::prelude::{BitRead, BitSeek, CodesRead, Endianness};
use std::cmp::Ordering;
use std::fmt;
use std::iter::FusedIterator;
use std::ops::Range;
#[derive(Debug, Clone)]
pub struct VarVecSlice<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> {
vec: &'a VarVec<T, E, B>,
start: usize,
len: usize,
}
impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> VarVecSlice<'a, T, E, B> {
pub(super) fn new(vec: &'a VarVec<T, E, B>, range: Range<usize>) -> Self {
Self {
vec,
start: range.start,
len: range.len(),
}
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn get(&self, index: usize) -> Option<T>
where
for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
+ CodesRead<E>
+ BitSeek<Error = core::convert::Infallible>,
{
if index >= self.len {
return None;
}
self.vec.get(self.start + index)
}
#[inline(always)]
pub unsafe fn get_unchecked(&self, index: usize) -> T
where
for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
+ CodesRead<E>
+ BitSeek<Error = core::convert::Infallible>,
{
debug_assert!(index < self.len, "Index out of bounds");
unsafe { self.vec.get_unchecked(self.start + index) }
}
pub fn iter(&self) -> VarVecSliceIter<'_, T, E, B>
where
for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
+ CodesRead<E>
+ BitSeek<Error = core::convert::Infallible>,
{
VarVecSliceIter::new(self)
}
}
impl<T, E, B> VarVecSlice<'_, T, E, B>
where
T: Storable + Ord,
E: Endianness,
B: AsRef<[u64]>,
for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
+ CodesRead<E>
+ BitSeek<Error = core::convert::Infallible>,
{
pub fn binary_search(&self, value: &T) -> Result<usize, usize> {
self.binary_search_by(|probe| probe.cmp(value))
}
#[inline]
pub fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize>
where
F: FnMut(T) -> Ordering,
{
let mut low = 0;
let mut high = self.len();
let mut reader = self.vec.reader();
while low < high {
let mid = low + (high - low) / 2;
let cmp = f(unsafe { reader.get_unchecked(self.start + mid) });
match cmp {
Ordering::Less => low = mid + 1,
Ordering::Equal => return Ok(mid),
Ordering::Greater => high = mid,
}
}
Err(low)
}
#[inline]
pub fn binary_search_by_key<K, F>(&self, b: &K, mut f: F) -> Result<usize, usize>
where
F: FnMut(T) -> K,
K: Ord,
{
self.binary_search_by(|k| f(k).cmp(b))
}
}
pub struct VarVecSliceIter<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> {
slice: &'a VarVecSlice<'a, T, E, B>,
current_index: usize,
}
impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> VarVecSliceIter<'a, T, E, B> {
fn new(slice: &'a VarVecSlice<'a, T, E, B>) -> Self {
Self {
slice,
current_index: 0,
}
}
}
impl<T, E, B> Iterator for VarVecSliceIter<'_, T, E, B>
where
T: Storable,
E: Endianness,
B: AsRef<[u64]>,
for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
+ CodesRead<E>
+ BitSeek<Error = core::convert::Infallible>,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.current_index >= self.slice.len() {
return None;
}
let value = unsafe { self.slice.get_unchecked(self.current_index) };
self.current_index += 1;
Some(value)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.slice.len().saturating_sub(self.current_index);
(remaining, Some(remaining))
}
}
impl<T, E, B> ExactSizeIterator for VarVecSliceIter<'_, T, E, B>
where
T: Storable,
E: Endianness,
B: AsRef<[u64]>,
for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
+ CodesRead<E>
+ BitSeek<Error = core::convert::Infallible>,
{
fn len(&self) -> usize {
self.slice.len().saturating_sub(self.current_index)
}
}
impl<T, E, B> FusedIterator for VarVecSliceIter<'_, T, E, B>
where
T: Storable,
E: Endianness,
B: AsRef<[u64]>,
for<'b> VarVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
+ CodesRead<E>
+ BitSeek<Error = core::convert::Infallible>,
{
}
impl<T: Storable, E: Endianness, B: AsRef<[u64]>> fmt::Debug for VarVecSliceIter<'_, T, E, B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VarVecSliceIter")
.field("remaining", &self.slice.len().saturating_sub(self.current_index))
.finish()
}
}