use std::hash::Hash;
use crate::codec::SketchBytes;
use crate::codec::SketchSlice;
use crate::error::Error;
pub const SERIAL_VERSION: u8 = 1;
pub const PREAMBLE_LONGS_EMPTY: u8 = 1;
pub const PREAMBLE_LONGS_NONEMPTY: u8 = 4;
pub const EMPTY_FLAG_MASK: u8 = 5;
pub trait FrequentItemValue: Sized + Eq + Hash + Clone {
fn serialize_size(item: &Self) -> usize;
fn serialize_value(&self, bytes: &mut SketchBytes);
fn deserialize_value(cursor: &mut SketchSlice<'_>) -> Result<Self, Error>;
}
impl FrequentItemValue for String {
fn serialize_size(item: &Self) -> usize {
size_of::<u32>() + item.len()
}
fn serialize_value(&self, bytes: &mut SketchBytes) {
let bs = self.as_bytes();
bytes.write_u32_le(bs.len() as u32);
bytes.write(bs);
}
fn deserialize_value(cursor: &mut SketchSlice<'_>) -> Result<Self, Error> {
let len = cursor.read_u32_le().map_err(|_| {
Error::insufficient_data("failed to read string item length".to_string())
})?;
let mut slice = vec![0; len as usize];
cursor.read_exact(&mut slice).map_err(|_| {
Error::insufficient_data("failed to read string item bytes".to_string())
})?;
String::from_utf8(slice)
.map_err(|_| Error::deserial("invalid UTF-8 string payload".to_string()))
}
}
macro_rules! impl_primitive {
($name:ty, $read:ident, $write:ident) => {
impl FrequentItemValue for $name {
fn serialize_size(_item: &Self) -> usize {
size_of::<$name>()
}
fn serialize_value(&self, bytes: &mut SketchBytes) {
bytes.$write(*self);
}
fn deserialize_value(cursor: &mut SketchSlice<'_>) -> Result<Self, Error> {
cursor.$read().map_err(|_| {
Error::insufficient_data(
concat!("failed to read ", stringify!($name), " item bytes").to_string(),
)
})
}
}
};
}
impl_primitive!(i64, read_i64_le, write_i64_le);
impl_primitive!(u64, read_u64_le, write_u64_le);