use crate::error::{OutOfSpecSnafu, Result};
use super::PrimitiveValueDecoder;
mod sealed {
use std::io::Read;
use crate::encoding::{
byte::ByteRleDecoder,
integer::{rle_v1::RleV1Decoder, rle_v2::RleV2Decoder, EncodingSign, NInt},
};
pub trait Rle {}
impl<R: Read> Rle for ByteRleDecoder<R> {}
impl<N: NInt, R: Read, S: EncodingSign> Rle for RleV1Decoder<N, R, S> {}
impl<N: NInt, R: Read, S: EncodingSign> Rle for RleV2Decoder<N, R, S> {}
}
pub trait GenericRle<V: Copy> {
fn advance(&mut self, n: usize);
fn available(&self) -> &[V];
fn decode_batch(&mut self) -> Result<()>;
fn skip_values(&mut self, n: usize) -> Result<()>;
}
impl<V: Copy, G: GenericRle<V> + sealed::Rle> PrimitiveValueDecoder<V> for G {
fn skip(&mut self, n: usize) -> Result<()> {
self.skip_values(n)
}
fn decode(&mut self, out: &mut [V]) -> Result<()> {
let available = self.available();
if available.len() >= out.len() {
out.copy_from_slice(&available[..out.len()]);
self.advance(out.len());
return Ok(());
}
let len_to_copy = out.len();
let mut copied = 0;
while copied < len_to_copy {
if self.available().is_empty() {
self.decode_batch()?;
}
let copying = self.available().len();
let copying = copying.min(len_to_copy - copied);
let out = &mut out[copied..];
out[..copying].copy_from_slice(&self.available()[..copying]);
copied += copying;
self.advance(copying);
}
if copied != out.len() {
OutOfSpecSnafu {
msg: "Array length less than expected",
}
.fail()
} else {
Ok(())
}
}
}