-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BinWrite derive doesn't work on structs with generic arguments
- Loading branch information
Showing
5 changed files
with
44 additions
and
227 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,32 @@ | ||
use std::fmt::Debug; | ||
use std::marker::PhantomData; | ||
|
||
use binrw::{binread, BinRead, BinWrite}; | ||
use binrw::{binrw, BinRead, BinWrite}; | ||
use derive_more::Deref; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[binread] | ||
#[binrw] | ||
#[derive(Debug, Serialize, Deref, Deserialize)] | ||
#[serde(transparent)] | ||
#[br(import_raw(inner: <InnerType as BinRead>::Args<'_>))] | ||
pub struct DynArray<InnerType: BinRead + 'static, SizeType: BinRead = u32> | ||
pub struct DynArray<InnerType: BinRead + BinWrite + 'static, SizeType: BinRead + BinWrite = u32> | ||
where | ||
for<'a> <InnerType as BinRead>::Args<'a>: Clone + Default, | ||
for<'a> <SizeType as BinRead>::Args<'a>: Default, | ||
SizeType: TryInto<usize>, | ||
<SizeType as TryInto<usize>>::Error: Debug, | ||
|
||
for<'a> InnerType: BinWrite<Args<'a> = ()>, | ||
for<'a> SizeType: BinWrite<Args<'a> = ()>, | ||
usize: TryInto<SizeType>, | ||
<usize as TryInto<SizeType>>::Error: Debug, | ||
{ | ||
#[br(temp)] | ||
#[bw(ignore)] | ||
#[bw(calc = data.len().try_into().unwrap())] | ||
count: SizeType, | ||
#[deref] | ||
#[br(args { count: count.try_into().unwrap(), inner: inner.clone() })] | ||
data: Vec<InnerType>, | ||
#[br(args { count: count.try_into().unwrap(), inner })] | ||
pub data: Vec<InnerType>, | ||
#[serde(skip)] | ||
_phantom: PhantomData<SizeType>, | ||
} | ||
|
||
impl<InnerType: BinWrite + BinRead + 'static, SizeType: BinWrite + BinRead> BinWrite | ||
for DynArray<InnerType, SizeType> | ||
where | ||
for<'a> <InnerType as BinRead>::Args<'a>: Clone + Default, | ||
for<'a> <SizeType as BinRead>::Args<'a>: Default, | ||
SizeType: TryInto<usize>, | ||
<SizeType as TryInto<usize>>::Error: Debug, | ||
for<'a> <InnerType as BinWrite>::Args<'a>: Clone + Default, | ||
for<'a> <SizeType as BinWrite>::Args<'a>: Default, | ||
usize: TryInto<SizeType>, | ||
<usize as TryInto<SizeType>>::Error: Debug, | ||
{ | ||
type Args<'a> = <InnerType as BinWrite>::Args<'a>; | ||
|
||
fn write_options<R: binrw::io::Write + binrw::io::Seek>( | ||
&self, | ||
reader: &mut R, | ||
endian: binrw::Endian, | ||
_args: Self::Args<'_>, | ||
) -> binrw::BinResult<()> { | ||
SizeType::write_options( | ||
&self.data.len().try_into().unwrap(), | ||
reader, | ||
endian, | ||
<_>::default(), | ||
)?; | ||
Vec::write_options(&self.data, reader, endian, <_>::default())?; | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl<InnerType: BinRead, SizeType: BinRead> From<DynArray<InnerType, SizeType>> for Vec<InnerType> | ||
where | ||
for<'a> <InnerType as BinRead>::Args<'a>: Clone + Default, | ||
for<'a> <SizeType as BinRead>::Args<'a>: Default, | ||
SizeType: TryInto<usize>, | ||
<SizeType as TryInto<usize>>::Error: Debug, | ||
{ | ||
fn from(dynarray: DynArray<InnerType, SizeType>) -> Self { | ||
dynarray.data | ||
} | ||
} | ||
|
||
impl<InnerType: BinRead, SizeType: BinRead> From<Vec<InnerType>> for DynArray<InnerType, SizeType> | ||
where | ||
for<'a> <InnerType as BinRead>::Args<'a>: Clone + Default, | ||
for<'a> <SizeType as BinRead>::Args<'a>: Default, | ||
SizeType: TryInto<usize>, | ||
<SizeType as TryInto<usize>>::Error: Debug, | ||
{ | ||
fn from(vec: Vec<InnerType>) -> Self { | ||
Self { | ||
data: vec, | ||
_phantom: PhantomData, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,30 @@ | ||
use std::fmt::Debug; | ||
use std::marker::PhantomData; | ||
|
||
use binrw::{BinRead, BinResult, BinWrite}; | ||
use binrw::{binrw, BinRead, BinWrite}; | ||
use derive_more::Deref; | ||
use num_traits::{One, Zero}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
use crate::Endian; | ||
|
||
#[binrw] | ||
#[derive(Serialize, Deref, Debug, Deserialize)] | ||
pub struct BffOption<InnerType, ConditionType = u8> { | ||
pub struct BffOption< | ||
InnerType: BinRead + BinWrite, | ||
ConditionType: BinRead + BinWrite + One + Zero + Eq = u8, | ||
> where | ||
for<'a> <InnerType as BinRead>::Args<'a>: Clone + Default, | ||
for<'a> <ConditionType as BinRead>::Args<'a>: Default, | ||
|
||
for<'a> InnerType: BinWrite<Args<'a> = ()>, | ||
for<'a> ConditionType: BinWrite<Args<'a> = ()>, | ||
{ | ||
#[br(temp)] | ||
#[bw(calc = if inner.is_some() { ConditionType::one() } else { ConditionType::zero() })] | ||
condition: ConditionType, | ||
#[deref] | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
#[br(if(condition != ConditionType::zero()))] | ||
inner: Option<InnerType>, | ||
#[serde(skip)] | ||
_phantom: PhantomData<ConditionType>, | ||
} | ||
|
||
impl<InnerType: BinRead, ConditionType: BinRead + Zero + Eq> BinRead | ||
for BffOption<InnerType, ConditionType> | ||
where | ||
for<'a> <InnerType as BinRead>::Args<'a>: Default, | ||
for<'a> <ConditionType as BinRead>::Args<'a>: Default, | ||
{ | ||
type Args<'a> = (); | ||
|
||
fn read_options<R: binrw::io::Read + binrw::io::Seek>( | ||
reader: &mut R, | ||
endian: Endian, | ||
_args: Self::Args<'_>, | ||
) -> BinResult<Self> { | ||
let condition = ConditionType::read_options(reader, endian, <_>::default())?; | ||
let inner = if condition != ConditionType::zero() { | ||
Some(InnerType::read_options(reader, endian, <_>::default())?) | ||
} else { | ||
None | ||
}; | ||
Ok(Self { | ||
inner, | ||
_phantom: PhantomData, | ||
}) | ||
} | ||
} | ||
|
||
impl<InnerType: BinWrite, ConditionType: BinWrite + Zero + One> BinWrite | ||
for BffOption<InnerType, ConditionType> | ||
where | ||
for<'a> <InnerType as BinWrite>::Args<'a>: Default, | ||
for<'a> <ConditionType as BinWrite>::Args<'a>: Default, | ||
{ | ||
type Args<'a> = (); | ||
|
||
fn write_options<R: binrw::io::Write + binrw::io::Seek>( | ||
&self, | ||
reader: &mut R, | ||
endian: Endian, | ||
_args: Self::Args<'_>, | ||
) -> BinResult<()> { | ||
ConditionType::write_options( | ||
&if self.inner.is_some() { | ||
ConditionType::one() | ||
} else { | ||
ConditionType::zero() | ||
}, | ||
reader, | ||
endian, | ||
<_>::default(), | ||
)?; | ||
if let Some(data) = &self.inner { | ||
InnerType::write_options(data, reader, endian, <_>::default())?; | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl<InnerType, ConditionType> From<Option<InnerType>> for BffOption<InnerType, ConditionType> | ||
where | ||
for<'a> InnerType: BinRead + BinWrite + Serialize + 'a, | ||
for<'a> <InnerType as BinRead>::Args<'a>: Clone + Default, | ||
for<'a> <InnerType as BinWrite>::Args<'a>: Default, | ||
|
||
ConditionType: BinRead + BinWrite + Debug + Copy + PartialEq + One + Zero, | ||
for<'a> <ConditionType as BinRead>::Args<'a>: Default, | ||
for<'a> <ConditionType as BinWrite>::Args<'a>: Default, | ||
{ | ||
fn from(inner: Option<InnerType>) -> Self { | ||
Self { | ||
inner, | ||
_phantom: PhantomData, | ||
} | ||
} | ||
} |