use std::cmp::Ordering;
use std::fmt;
use std::mem::size_of;
use std::ops::Deref;
use crate::codec::SketchBytes;
use crate::codec::SketchSlice;
use crate::codec::assert::insufficient_data;
use crate::error::Error;
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, PartialOrd)]
pub struct KllFloat<T>(T);
impl<T> KllFloat<T> {
#[inline(always)]
pub fn into_inner(self) -> T {
self.0
}
}
impl<T> Deref for KllFloat<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: fmt::Debug> fmt::Debug for KllFloat<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T: fmt::Display> fmt::Display for KllFloat<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl KllFloat<f32> {
#[inline(always)]
pub fn new(value: f32) -> Result<Self, Error> {
if value.is_nan() {
Err(Error::invalid_argument("KLL float must not be NaN"))
} else {
Ok(Self(value))
}
}
}
impl Eq for KllFloat<f32> {}
impl Ord for KllFloat<f32> {
#[inline(always)]
fn cmp(&self, other: &Self) -> Ordering {
self.0.partial_cmp(&other.0).unwrap()
}
}
impl KllFloat<f64> {
#[inline(always)]
pub fn new(value: f64) -> Result<Self, Error> {
if value.is_nan() {
Err(Error::invalid_argument("KLL float must not be NaN"))
} else {
Ok(Self(value))
}
}
}
impl Eq for KllFloat<f64> {}
impl Ord for KllFloat<f64> {
#[inline(always)]
fn cmp(&self, other: &Self) -> Ordering {
self.0.partial_cmp(&other.0).unwrap()
}
}
pub trait KllValue: Clone {
const MIN_SERIALIZED_SIZE: usize;
fn serialized_size(value: &Self) -> usize;
fn serialize(value: &Self, bytes: &mut SketchBytes);
fn deserialize(input: &mut SketchSlice<'_>) -> Result<Self, Error>;
}
impl KllValue for KllFloat<f32> {
const MIN_SERIALIZED_SIZE: usize = size_of::<f32>();
fn serialized_size(_value: &Self) -> usize {
size_of::<f32>()
}
fn serialize(value: &Self, bytes: &mut SketchBytes) {
bytes.write_f32_le(value.0);
}
fn deserialize(input: &mut SketchSlice<'_>) -> Result<Self, Error> {
let value = input
.read_f32_le()
.map_err(insufficient_data("KLL f32 item"))?;
Self::new(value).map_err(|_| Error::deserial("KLL float must not be NaN"))
}
}
impl KllValue for KllFloat<f64> {
const MIN_SERIALIZED_SIZE: usize = size_of::<f64>();
fn serialized_size(_value: &Self) -> usize {
size_of::<f64>()
}
fn serialize(value: &Self, bytes: &mut SketchBytes) {
bytes.write_f64_le(value.0);
}
fn deserialize(input: &mut SketchSlice<'_>) -> Result<Self, Error> {
let value = input
.read_f64_le()
.map_err(insufficient_data("KLL f64 item"))?;
Self::new(value).map_err(|_| Error::deserial("KLL float must not be NaN"))
}
}
impl KllValue for i64 {
const MIN_SERIALIZED_SIZE: usize = 8;
fn serialized_size(_value: &Self) -> usize {
8
}
fn serialize(value: &Self, bytes: &mut SketchBytes) {
bytes.write_i64_le(*value);
}
fn deserialize(input: &mut SketchSlice<'_>) -> Result<Self, Error> {
input
.read_i64_le()
.map_err(insufficient_data("KLL i64 item"))
}
}
impl KllValue for String {
const MIN_SERIALIZED_SIZE: usize = 4;
fn serialized_size(value: &Self) -> usize {
4 + value.len()
}
fn serialize(value: &Self, bytes: &mut SketchBytes) {
bytes.write_u32_le(value.len() as u32);
bytes.write(value.as_bytes());
}
fn deserialize(input: &mut SketchSlice<'_>) -> Result<Self, Error> {
let len = input
.read_u32_le()
.map_err(insufficient_data("KLL string length"))? as usize;
let available_bytes = input.remaining().len();
if available_bytes < len {
return Err(Error::insufficient_data_of(
"KLL string payload",
format_args!("expected {len} bytes, got {available_bytes}"),
));
}
let value = std::str::from_utf8(&input.remaining()[..len])
.map_err(|error| Error::deserial(format!("invalid UTF-8 string: {error}")))?
.to_owned();
input.advance(len as u64);
Ok(value)
}
}