use num_traits::{Bounded, PrimInt};
use std::{fmt, io, marker::PhantomData, mem::size_of};
use crate::{
bitflags_ext::Bitflags,
io::ParseBuf,
proto::{MyDeserialize, MySerialize},
};
use super::{int::IntRepr, RawInt};
#[derive(Clone, Default, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct RawFlags<T: Bitflags, U>(pub T::Repr, PhantomData<U>);
impl<T: Bitflags, U> RawFlags<T, U> {
pub fn new(value: T::Repr) -> Self {
Self(value, PhantomData)
}
pub fn get(&self) -> T {
T::from_bits_truncate(self.0)
}
}
impl<T: fmt::Debug, U> fmt::Debug for RawFlags<T, U>
where
T: Bitflags,
T::Repr: fmt::Binary,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.get())?;
let unknown_bits = self.0 & (T::Repr::max_value() ^ T::all().bits());
if unknown_bits.count_ones() > 0 {
write!(
f,
" (Unknown bits: {:0width$b})",
unknown_bits,
width = T::Repr::max_value().count_ones() as usize,
)?
}
Ok(())
}
}
impl<'de, T: Bitflags, U> MyDeserialize<'de> for RawFlags<T, U>
where
U: IntRepr<Primitive = T::Repr>,
{
const SIZE: Option<usize> = Some(size_of::<T::Repr>());
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
let value = buf.parse_unchecked::<RawInt<U>>(())?;
Ok(Self::new(*value))
}
}
impl<T: Bitflags, U> MySerialize for RawFlags<T, U>
where
U: IntRepr<Primitive = T::Repr>,
{
fn serialize(&self, buf: &mut Vec<u8>) {
RawInt::<U>::new(self.0).serialize(buf);
}
}