use crate::error::Error;
use crate::encoding::hybrid_rle::{self, BitmapIter};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HybridEncoded<'a> {
Bitmap(&'a [u8], usize),
Repeated(bool, usize),
}
impl<'a> HybridEncoded<'a> {
#[inline]
pub fn len(&self) -> usize {
match self {
HybridEncoded::Bitmap(_, length) => *length,
HybridEncoded::Repeated(_, length) => *length,
}
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub trait HybridRleRunsIterator<'a>: Iterator<Item = Result<HybridEncoded<'a>, Error>> {
fn number_of_elements(&self) -> usize;
}
#[derive(Debug, Clone)]
pub struct HybridRleIter<'a, I>
where
I: Iterator<Item = Result<hybrid_rle::HybridEncoded<'a>, Error>>,
{
iter: I,
length: usize,
consumed: usize,
}
impl<'a, I> HybridRleIter<'a, I>
where
I: Iterator<Item = Result<hybrid_rle::HybridEncoded<'a>, Error>>,
{
#[inline]
pub fn new(iter: I, length: usize) -> Self {
Self {
iter,
length,
consumed: 0,
}
}
#[inline]
pub fn len(&self) -> usize {
self.length - self.consumed
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<'a, I> HybridRleRunsIterator<'a> for HybridRleIter<'a, I>
where
I: Iterator<Item = Result<hybrid_rle::HybridEncoded<'a>, Error>>,
{
fn number_of_elements(&self) -> usize {
self.len()
}
}
impl<'a, I> Iterator for HybridRleIter<'a, I>
where
I: Iterator<Item = Result<hybrid_rle::HybridEncoded<'a>, Error>>,
{
type Item = Result<HybridEncoded<'a>, Error>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.consumed == self.length {
return None;
};
let run = self.iter.next()?;
Some(run.map(|run| match run {
hybrid_rle::HybridEncoded::Bitpacked(pack) => {
let pack_size = pack.len() * 8;
let additional = pack_size.min(self.len());
self.consumed += additional;
HybridEncoded::Bitmap(pack, additional)
}
hybrid_rle::HybridEncoded::Rle(value, length) => {
let is_set = value[0] == 1;
let additional = length.min(self.len());
self.consumed += additional;
HybridEncoded::Repeated(is_set, additional)
}
}))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
pub type HybridDecoderBitmapIter<'a> = HybridRleIter<'a, hybrid_rle::Decoder<'a>>;
#[derive(Debug)]
enum HybridBooleanState<'a> {
Bitmap(BitmapIter<'a>),
Repeated(bool, usize),
}
#[derive(Debug)]
pub struct HybridRleBooleanIter<'a, I>
where
I: Iterator<Item = Result<HybridEncoded<'a>, Error>>,
{
iter: I,
current_run: Option<HybridBooleanState<'a>>,
}
impl<'a, I> HybridRleBooleanIter<'a, I>
where
I: Iterator<Item = Result<HybridEncoded<'a>, Error>>,
{
pub fn new(iter: I) -> Self {
Self {
iter,
current_run: None,
}
}
}
impl<'a, I> Iterator for HybridRleBooleanIter<'a, I>
where
I: HybridRleRunsIterator<'a>,
{
type Item = Result<bool, Error>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let Some(run) = &mut self.current_run {
match run {
HybridBooleanState::Bitmap(bitmap) => bitmap.next().map(Ok),
HybridBooleanState::Repeated(value, remaining) => if *remaining == 0 {
None
} else {
*remaining -= 1;
Some(*value)
}
.map(Ok),
}
} else if let Some(run) = self.iter.next() {
let run = run.map(|run| match run {
HybridEncoded::Bitmap(bitmap, length) => {
HybridBooleanState::Bitmap(BitmapIter::new(bitmap, 0, length))
}
HybridEncoded::Repeated(value, length) => {
HybridBooleanState::Repeated(value, length)
}
});
match run {
Ok(run) => {
self.current_run = Some(run);
self.next()
}
Err(e) => Some(Err(e)),
}
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let exact = self.iter.number_of_elements();
(exact, Some(exact))
}
}
pub type HybridRleDecoderIter<'a> = HybridRleBooleanIter<'a, HybridDecoderBitmapIter<'a>>;