use binrw::{binrw, BinRead, BinWrite}; use diff::Diff; use std::{ fmt::{Debug, Display}, mem::size_of, ops::{Deref, DerefMut}, }; /// Wrapper to prefix arbitrary types with size of type as u32 #[binrw] #[derive(Clone, Copy, Default, PartialEq)] pub struct FieldOf where T: for<'a> BinRead = ()>, T: for<'a> BinWrite = ()>, { // Temporary variable that must match size of value #[br(temp, assert(size == size_of::().try_into().unwrap()))] #[bw(try_calc(u32::try_from(size_of::())))] size: u32, pub value: T, } // Custom Diff implementation to only diff internal value impl Diff for FieldOf where T: for<'a> BinRead = ()>, T: for<'a> BinWrite = ()>, T: Diff + Default, { type Repr = ::Repr; fn diff(&self, other: &Self) -> Self::Repr { self.value.diff(&other.value) } fn apply(&mut self, diff: &Self::Repr) { self.value.apply(diff) } fn identity() -> Self { Self { value: T::default(), } } } impl Deref for FieldOf where T: for<'a> BinRead = ()>, T: for<'a> BinWrite = ()>, { type Target = T; fn deref(&self) -> &Self::Target { &self.value } } impl DerefMut for FieldOf where T: for<'a> BinRead = ()>, T: for<'a> BinWrite = ()>, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.value } } impl Debug for FieldOf where T: for<'a> BinRead = ()>, T: for<'a> BinWrite = ()>, T: Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self.value) } } impl Display for FieldOf where T: for<'a> BinRead = ()>, T: for<'a> BinWrite = ()>, T: Display, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.value) } } impl From for FieldOf where T: for<'a> BinRead = ()>, T: for<'a> BinWrite = ()>, { fn from(value: T) -> Self { Self { value } } }