use serde::{Deserialize, Deserializer, Serialize, Serializer};
pub fn serialize<S, T>(val: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Copy,
Fixint<T>: Serialize,
{
Fixint(*val).serialize(serializer)
}
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
Fixint<T>: Deserialize<'de>,
{
Fixint::<T>::deserialize(deserializer).map(|x| x.0)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(transparent)]
pub struct Fixint<T>(pub T);
impl<T> Fixint<T> {
pub const fn new(value: T) -> Self {
Self(value)
}
pub fn into_inner(self) -> T {
self.0
}
}
impl<T> From<T> for Fixint<T> {
fn from(value: T) -> Self {
Self(value)
}
}
macro_rules! impl_fixint {
($( $int:ty ),*) => {
$(
impl Serialize for Fixint<$int> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.to_le_bytes().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Fixint<$int> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
<_ as Deserialize>::deserialize(deserializer)
.map(<$int>::from_le_bytes)
.map(Self)
}
}
)*
};
}
macro_rules! impl_fixint_ptr_width {
($( $int:ty as $fixed:ty ),*) => {
$(
impl Serialize for Fixint<$int> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let value = <$fixed>::try_from(self.0).map_err(|_| {
<S::Error as serde::ser::Error>::custom(concat!(stringify!($int), " overflow"))
})?;
value.to_le_bytes().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Fixint<$int> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = <_ as Deserialize>::deserialize(deserializer).map(<$fixed>::from_le_bytes)?;
<$int>::try_from(value).map(Self).map_err(|_| {
<D::Error as serde::de::Error>::custom(concat!(stringify!($int), " overflow"))
})
}
}
)*
};
}
impl_fixint![i8, i16, i32, i64, i128, u8, u16, u32, u64, u128];
impl_fixint_ptr_width![usize as u64, isize as i64];