use std::{
convert::TryFrom,
fmt, io,
marker::PhantomData,
ops::{Deref, DerefMut},
};
use crate::{
io::ParseBuf,
proto::{MyDeserialize, MySerialize},
};
use super::{int::IntRepr, RawInt};
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct Const<T, U>(pub T, PhantomData<U>);
impl<T, U> Const<T, U> {
pub fn new(t: T) -> Self {
Self(t, PhantomData)
}
}
impl<T, U> Deref for Const<T, U> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, U> DerefMut for Const<T, U> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'de, T, U> MyDeserialize<'de> for Const<T, U>
where
U: IntRepr,
T: TryFrom<U::Primitive>,
<T as TryFrom<U::Primitive>>::Error: std::error::Error + Send + Sync + 'static,
{
const SIZE: Option<usize> = U::SIZE;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
let raw_val = buf.parse_unchecked::<RawInt<U>>(())?;
T::try_from(*raw_val)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.map(Const::new)
}
}
impl<T, U> MySerialize for Const<T, U>
where
T: Copy,
T: Into<U::Primitive>,
U: IntRepr,
{
fn serialize(&self, buf: &mut Vec<u8>) {
RawInt::<U>::new(self.0.into()).serialize(buf);
}
}
#[derive(Clone, Default, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct RawConst<T: IntRepr, U>(pub T::Primitive, PhantomData<U>);
impl<T: IntRepr, U> RawConst<T, U> {
pub fn new(t: T::Primitive) -> Self {
Self(t, PhantomData)
}
}
impl<T: IntRepr, U> Deref for RawConst<T, U> {
type Target = T::Primitive;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: IntRepr, U> DerefMut for RawConst<T, U> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: IntRepr, U> RawConst<T, U>
where
T::Primitive: Copy,
U: TryFrom<T::Primitive>,
{
pub fn get(&self) -> Result<U, U::Error> {
U::try_from(self.0)
}
}
impl<T: IntRepr, U> fmt::Debug for RawConst<T, U>
where
T: fmt::Debug,
T::Primitive: Copy,
U: fmt::Debug + TryFrom<T::Primitive>,
U::Error: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match U::try_from(self.0) {
Ok(u) => u.fmt(f),
Err(t) => write!(
f,
"Unknown value for type {}: {:?}",
std::any::type_name::<U>(),
t
),
}
}
}
impl<'de, T: IntRepr, U> MyDeserialize<'de> for RawConst<T, U> {
const SIZE: Option<usize> = T::SIZE;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
let value = buf.parse_unchecked::<RawInt<T>>(())?.0;
Ok(Self::new(value))
}
}
impl<T: IntRepr, U> MySerialize for RawConst<T, U> {
fn serialize(&self, buf: &mut Vec<u8>) {
RawInt::<T>::new(self.0).serialize(buf);
}
}