use binrw::{binrw, BinRead, BinWrite}; use diff::{Diff, VecDiff}; use num::Num; use std::{ fmt::{Debug, Display}, marker::PhantomData, ops::{Deref, DerefMut}, }; /// Wrapper to prefix array of primitives (u8/u32/etc) #[binrw] #[derive(Clone, Default, PartialEq)] pub struct ArrayOfPrimitive where // Static bounds due to https://github.com/jam1garner/binrw/issues/199 T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: Num + 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { // Temporary variable that holds number of elements #[br(temp)] #[bw(try_calc(S::try_from(value.len())))] count: S, #[br(count = count)] pub value: Vec, _marker: PhantomData, } impl Debug for ArrayOfPrimitive where T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: Debug + Num + 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self.value) } } // Custom Diff implementation to only diff internal value impl Diff for ArrayOfPrimitive where T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: Diff + PartialEq + Num + 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + Display + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { type Repr = VecDiff; 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: vec![], _marker: PhantomData, } } } impl From> for ArrayOfPrimitive where T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: Num + 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { fn from(value: Vec) -> Self { Self { value, _marker: PhantomData, } } } /// Wrapper to prefix array of single non-primitive type #[binrw] #[derive(Clone, PartialEq)] pub struct ArrayOf where // Static bounds due to https://github.com/jam1garner/binrw/issues/199 T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { // Temporary variable that holds number of elements #[br(temp)] #[bw(try_calc(S::try_from(value.len())))] count: S, #[br(count = count)] pub value: Vec, _marker: PhantomData, } // Custom Diff implementation to only diff internal value impl Diff for ArrayOf where T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: Diff + PartialEq + 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + Display + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { type Repr = VecDiff; 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: vec![], _marker: PhantomData, } } } impl Debug for ArrayOf where T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: Debug + 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + Display + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:#?}", self.value) } } impl Deref for ArrayOf where T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { type Target = Vec; fn deref(&self) -> &Self::Target { &self.value } } impl DerefMut for ArrayOf where T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.value } } impl From> for ArrayOf where T: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, T: 'static, S: for<'a> BinRead = ()> + for<'a> BinWrite = ()>, S: TryFrom + Copy + Clone + Debug + 'static, >::Error: Display + Debug + Send + Sync, usize: TryFrom, { fn from(value: Vec) -> Self { Self { value, _marker: PhantomData, } } }