use std::io::{Read, Write};
use arrow::array::PrimitiveArray;
use arrow::error::Result;
use crate::{compression::Compression, write::WriteOptions};
use super::{DoubleCompression, DoubleStats, DoubleType};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct OneValue {}
impl<T: DoubleType> DoubleCompression<T> for OneValue {
fn compress(
&self,
array: &PrimitiveArray<T>,
_stats: &DoubleStats<T>,
_write_options: &WriteOptions,
output: &mut Vec<u8>,
) -> Result<usize> {
let size = output.len();
self.encode_native(output, array)?;
Ok(output.len() - size)
}
fn decompress(&self, input: &[u8], length: usize, output: &mut Vec<T>) -> Result<()> {
self.decode_native(input, length, output)?;
Ok(())
}
fn to_compression(&self) -> Compression {
Compression::OneValue
}
fn compress_ratio(&self, stats: &DoubleStats<T>) -> f64 {
if stats.unique_count <= 1 {
stats.tuple_count as f64
} else {
0.0f64
}
}
}
impl OneValue {
pub fn encode_native<T: DoubleType, W: Write>(
&self,
w: &mut W,
array: &PrimitiveArray<T>,
) -> Result<()> {
let val = array.iter().find(|v| v.is_some());
let val = match val {
Some(Some(v)) => *v,
_ => T::default(),
};
let _ = w.write(val.to_le_bytes().as_ref())?;
Ok(())
}
pub fn decode_native<T: DoubleType>(
&self,
mut input: &[u8],
length: usize,
array: &mut Vec<T>,
) -> Result<()> {
let mut bs = vec![0u8; std::mem::size_of::<T>()];
input.read_exact(&mut bs)?;
let a: T::Bytes = match bs.as_slice().try_into() {
Ok(a) => a,
Err(_) => unreachable!(),
};
let val = T::from_le_bytes(a);
array.extend(std::iter::repeat(val).take(length));
Ok(())
}
}