use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
pub fn serialize<S, T>(val: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Copy,
Varfloat<T>: Serialize,
{
Varfloat(*val).serialize(serializer)
}
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
Varfloat<T>: Deserialize<'de>,
{
Varfloat::<T>::deserialize(deserializer).map(|x| x.0)
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
#[repr(transparent)]
pub struct Varfloat<T>(pub T);
impl<T> Varfloat<T> {
pub const fn new(value: T) -> Self {
Self(value)
}
pub fn into_inner(self) -> T {
self.0
}
}
impl<T> From<T> for Varfloat<T> {
fn from(value: T) -> Self {
Self(value)
}
}
macro_rules! impl_varfloat {
($( $float:ty as $bits:ty ),*) => {
$(
impl Serialize for Varfloat<$float> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let bits = self.0.to_bits();
let bytes = bits.to_be_bytes();
let len = bytes.len() - (bits.trailing_zeros() / 8) as usize;
serializer.serialize_bytes(&bytes[..len])
}
}
impl<'de> Deserialize<'de> for Varfloat<$float> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct FloatVisitor;
impl<'de> serde::de::Visitor<'de> for FloatVisitor {
type Value = Varfloat<$float>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, concat!("a variable length ", stringify!($float)))
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
const LEN: usize = size_of::<$float>();
if v.len() > LEN || v.last() == Some(&0) {
return Err(E::custom(concat!("invalid ", stringify!($float))));
}
let mut bytes = [0; LEN];
bytes[..v.len()].copy_from_slice(v);
Ok(Varfloat(<$float>::from_bits(<$bits>::from_be_bytes(bytes))))
}
}
deserializer.deserialize_bytes(FloatVisitor)
}
}
)*
};
}
impl_varfloat![f32 as u32, f64 as u64];