Skip to content

Commit

Permalink
Enable borrowing within Args using GATs
Browse files Browse the repository at this point in the history
Closes #97.
  • Loading branch information
csnover authored and jam1garner committed Nov 29, 2022
1 parent ed89b93 commit 5b7ac71
Show file tree
Hide file tree
Showing 23 changed files with 432 additions and 159 deletions.
75 changes: 49 additions & 26 deletions binrw/src/binread/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ macro_rules! binread_impl {
($($type_name:ty),*$(,)?) => {
$(
impl BinRead for $type_name {
type Args = ();
type Args<'a> = ();

fn read_options<R: Read + Seek>(reader: &mut R, endian: Endian, _: Self::Args) -> BinResult<Self> {
fn read_options<R: Read + Seek>(reader: &mut R, endian: Endian, _: Self::Args<'_>) -> BinResult<Self> {
let mut val = [0; core::mem::size_of::<$type_name>()];
let pos = reader.stream_position()?;

Expand Down Expand Up @@ -49,12 +49,12 @@ macro_rules! binread_nonzero_impl {
($($Ty:ty, $Int:ty),* $(,)?) => {
$(
impl BinRead for $Ty {
type Args = ();
type Args<'a> = ();

fn read_options<R: Read + Seek>(
reader: &mut R,
endian: Endian,
_: Self::Args,
_: Self::Args<'_>,
) -> BinResult<Self> {
match <$Ty>::new(<$Int>::read_options(reader, endian, ())?) {
Some(x) => Ok(x),
Expand Down Expand Up @@ -133,18 +133,27 @@ pub struct VecArgs<Inner: Clone> {
pub inner: Inner,
}

impl<B: BinRead> BinRead for Vec<B> {
type Args = VecArgs<B::Args>;
impl<B> BinRead for Vec<B>
where
B: BinRead + 'static,
for<'a> B::Args<'a>: Clone,
{
type Args<'a> = VecArgs<B::Args<'a>>;

fn read_options<R: Read + Seek>(
reader: &mut R,
endian: Endian,
args: Self::Args,
args: Self::Args<'_>,
) -> BinResult<Self> {
crate::helpers::count_with(args.count, B::read_options)(reader, endian, args.inner)
}

fn after_parse<R>(&mut self, reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<()>
fn after_parse<R>(
&mut self,
reader: &mut R,
endian: Endian,
args: Self::Args<'_>,
) -> BinResult<()>
where
R: Read + Seek,
{
Expand All @@ -156,18 +165,27 @@ impl<B: BinRead> BinRead for Vec<B> {
}
}

impl<B: BinRead, const N: usize> BinRead for [B; N] {
type Args = B::Args;
impl<B, const N: usize> BinRead for [B; N]
where
B: BinRead,
for<'a> B::Args<'a>: Clone,
{
type Args<'a> = B::Args<'a>;

fn read_options<R: Read + Seek>(
reader: &mut R,
endian: Endian,
args: Self::Args,
args: Self::Args<'_>,
) -> BinResult<Self> {
array_init::try_array_init(|_| BinRead::read_options(reader, endian, args.clone()))
}

fn after_parse<R>(&mut self, reader: &mut R, endian: Endian, args: B::Args) -> BinResult<()>
fn after_parse<R>(
&mut self,
reader: &mut R,
endian: Endian,
args: Self::Args<'_>,
) -> BinResult<()>
where
R: Read + Seek,
{
Expand All @@ -182,10 +200,10 @@ impl<B: BinRead, const N: usize> BinRead for [B; N] {
macro_rules! binread_tuple_impl {
($type1:ident $(, $types:ident)*) => {
#[allow(non_camel_case_types)]
impl<Args: Clone, $type1: BinRead<Args=Args>, $($types: BinRead<Args=Args>),*> BinRead for ($type1, $($types),*) {
type Args = Args;
impl<Args: Clone, $type1: for<'a> BinRead<Args<'a> = Args>, $($types: for<'a> BinRead<Args<'a> = Args>),*> BinRead for ($type1, $($types),*) {
type Args<'a> = Args;

fn read_options<R: Read + Seek>(reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<Self> {
fn read_options<R: Read + Seek>(reader: &mut R, endian: Endian, args: Self::Args<'_>) -> BinResult<Self> {
Ok((
BinRead::read_options(reader, endian, args.clone())?,
$(
Expand All @@ -194,7 +212,7 @@ macro_rules! binread_tuple_impl {
))
}

fn after_parse<R: Read + Seek>(&mut self, reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<()> {
fn after_parse<R: Read + Seek>(&mut self, reader: &mut R, endian: Endian, args: Self::Args<'_>) -> BinResult<()> {
let ($type1, $(
$types
),*) = self;
Expand All @@ -220,37 +238,42 @@ binread_tuple_impl!(
);

impl BinRead for () {
type Args = ();
type Args<'a> = ();

fn read_options<R: Read + Seek>(_: &mut R, _: Endian, _: Self::Args) -> BinResult<Self> {
fn read_options<R: Read + Seek>(_: &mut R, _: Endian, _: Self::Args<'_>) -> BinResult<Self> {
Ok(())
}
}

impl<T: BinRead> BinRead for Box<T> {
type Args = T::Args;
type Args<'a> = T::Args<'a>;

fn read_options<R: Read + Seek>(
reader: &mut R,
endian: Endian,
args: Self::Args,
args: Self::Args<'_>,
) -> BinResult<Self> {
Ok(Box::new(T::read_options(reader, endian, args)?))
}
}

impl<T: BinRead> BinRead for Option<T> {
type Args = T::Args;
type Args<'a> = T::Args<'a>;

fn read_options<R: Read + Seek>(
reader: &mut R,
endian: Endian,
args: Self::Args,
args: Self::Args<'_>,
) -> BinResult<Self> {
Ok(Some(T::read_options(reader, endian, args)?))
}

fn after_parse<R>(&mut self, reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<()>
fn after_parse<R>(
&mut self,
reader: &mut R,
endian: Endian,
args: Self::Args<'_>,
) -> BinResult<()>
where
R: Read + Seek,
{
Expand All @@ -261,10 +284,10 @@ impl<T: BinRead> BinRead for Option<T> {
}
}

impl<T: 'static> BinRead for core::marker::PhantomData<T> {
type Args = ();
impl<T> BinRead for core::marker::PhantomData<T> {
type Args<'a> = ();

fn read_options<R: Read + Seek>(_: &mut R, _: Endian, _: Self::Args) -> BinResult<Self> {
fn read_options<R: Read + Seek>(_: &mut R, _: Endian, _: Self::Args<'_>) -> BinResult<Self> {
Ok(core::marker::PhantomData)
}
}
68 changes: 44 additions & 24 deletions binrw/src/binread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use impls::VecArgs;
/// [temporary fields].
///
/// [temporary fields]: crate::docs::attribute#temp
pub trait BinRead: Sized + 'static {
pub trait BinRead: Sized {
/// The type used for the `args` parameter of [`read_args()`] and
/// [`read_options()`].
///
Expand All @@ -46,7 +46,7 @@ pub trait BinRead: Sized + 'static {
/// [`read()`]: Self::read
/// [`read_args()`]: Self::read_args
/// [`read_options()`]: Self::read_options
type Args: Clone;
type Args<'a>;

/// Read `Self` from the reader using default arguments.
///
Expand All @@ -57,7 +57,7 @@ pub trait BinRead: Sized + 'static {
fn read<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
where
Self: ReadEndian,
Self::Args: Required,
for<'a> Self::Args<'a>: Required,
{
Self::read_args(reader, Self::Args::args())
}
Expand All @@ -71,7 +71,7 @@ pub trait BinRead: Sized + 'static {
#[inline]
fn read_be<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
where
Self::Args: Required,
for<'a> Self::Args<'a>: Required,
{
Self::read_be_args(reader, Self::Args::args())
}
Expand All @@ -85,7 +85,7 @@ pub trait BinRead: Sized + 'static {
#[inline]
fn read_le<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
where
Self::Args: Required,
for<'a> Self::Args<'a>: Required,
{
Self::read_le_args(reader, Self::Args::args())
}
Expand All @@ -98,7 +98,7 @@ pub trait BinRead: Sized + 'static {
#[inline]
fn read_ne<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
where
Self::Args: Required,
for<'a> Self::Args<'a>: Required,
{
Self::read_ne_args(reader, Self::Args::args())
}
Expand All @@ -109,7 +109,7 @@ pub trait BinRead: Sized + 'static {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_args<R: Read + Seek>(reader: &mut R, args: Self::Args) -> BinResult<Self>
fn read_args<R: Read + Seek>(reader: &mut R, args: Self::Args<'_>) -> BinResult<Self>
where
Self: ReadEndian,
{
Expand All @@ -123,7 +123,7 @@ pub trait BinRead: Sized + 'static {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_be_args<R: Read + Seek>(reader: &mut R, args: Self::Args) -> BinResult<Self> {
fn read_be_args<R: Read + Seek>(reader: &mut R, args: Self::Args<'_>) -> BinResult<Self> {
Self::read_options(reader, Endian::Big, args)
}

Expand All @@ -134,7 +134,7 @@ pub trait BinRead: Sized + 'static {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_le_args<R: Read + Seek>(reader: &mut R, args: Self::Args) -> BinResult<Self> {
fn read_le_args<R: Read + Seek>(reader: &mut R, args: Self::Args<'_>) -> BinResult<Self> {
Self::read_options(reader, Endian::Little, args)
}

Expand All @@ -145,7 +145,7 @@ pub trait BinRead: Sized + 'static {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_ne_args<R: Read + Seek>(reader: &mut R, args: Self::Args) -> BinResult<Self> {
fn read_ne_args<R: Read + Seek>(reader: &mut R, args: Self::Args<'_>) -> BinResult<Self> {
Self::read_options(reader, Endian::NATIVE, args)
}

Expand All @@ -158,7 +158,7 @@ pub trait BinRead: Sized + 'static {
fn read_options<R: Read + Seek>(
reader: &mut R,
endian: Endian,
args: Self::Args,
args: Self::Args<'_>,
) -> BinResult<Self>;

/// Runs any post-processing steps required to finalize construction of the
Expand All @@ -172,7 +172,7 @@ pub trait BinRead: Sized + 'static {
&mut self,
_: &mut R,
_: Endian,
_: Self::Args,
_: Self::Args<'_>,
) -> BinResult<()> {
Ok(())
}
Expand All @@ -199,9 +199,10 @@ pub trait BinReaderExt: Read + Seek + Sized {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_type<T: BinRead>(&mut self, endian: Endian) -> BinResult<T>
fn read_type<'a, T>(&mut self, endian: Endian) -> BinResult<T>
where
T::Args: Required,
T: BinRead,
T::Args<'a>: Required + Clone,
{
self.read_type_args(endian, T::Args::args())
}
Expand All @@ -212,9 +213,10 @@ pub trait BinReaderExt: Read + Seek + Sized {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_be<T: BinRead>(&mut self) -> BinResult<T>
fn read_be<'a, T>(&mut self) -> BinResult<T>
where
T::Args: Required,
T: BinRead,
T::Args<'a>: Required + Clone,
{
self.read_type(Endian::Big)
}
Expand All @@ -225,9 +227,10 @@ pub trait BinReaderExt: Read + Seek + Sized {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_le<T: BinRead>(&mut self) -> BinResult<T>
fn read_le<'a, T>(&mut self) -> BinResult<T>
where
T::Args: Required,
T: BinRead,
T::Args<'a>: Required + Clone,
{
self.read_type(Endian::Little)
}
Expand All @@ -238,9 +241,10 @@ pub trait BinReaderExt: Read + Seek + Sized {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_ne<T: BinRead>(&mut self) -> BinResult<T>
fn read_ne<'a, T>(&mut self) -> BinResult<T>
where
T::Args: Required,
T: BinRead,
T::Args<'a>: Required + Clone,
{
self.read_type(Endian::NATIVE)
}
Expand All @@ -250,7 +254,11 @@ pub trait BinReaderExt: Read + Seek + Sized {
/// # Errors
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
fn read_type_args<T: BinRead>(&mut self, endian: Endian, args: T::Args) -> BinResult<T> {
fn read_type_args<'a, T>(&mut self, endian: Endian, args: T::Args<'a>) -> BinResult<T>
where
T: BinRead,
T::Args<'a>: Clone,
{
let mut res = T::read_options(self, endian, args.clone())?;
res.after_parse(self, endian, args)?;

Expand All @@ -264,7 +272,11 @@ pub trait BinReaderExt: Read + Seek + Sized {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_be_args<T: BinRead>(&mut self, args: T::Args) -> BinResult<T> {
fn read_be_args<'a, T>(&mut self, args: T::Args<'a>) -> BinResult<T>
where
T: BinRead,
T::Args<'a>: Clone,
{
self.read_type_args(Endian::Big, args)
}

Expand All @@ -275,7 +287,11 @@ pub trait BinReaderExt: Read + Seek + Sized {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_le_args<T: BinRead>(&mut self, args: T::Args) -> BinResult<T> {
fn read_le_args<'a, T>(&mut self, args: T::Args<'a>) -> BinResult<T>
where
T: BinRead,
T::Args<'a>: Clone,
{
self.read_type_args(Endian::Little, args)
}

Expand All @@ -286,7 +302,11 @@ pub trait BinReaderExt: Read + Seek + Sized {
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
#[inline]
fn read_ne_args<T: BinRead>(&mut self, args: T::Args) -> BinResult<T> {
fn read_ne_args<'a, T>(&mut self, args: T::Args<'a>) -> BinResult<T>
where
T: BinRead,
T::Args<'a>: Clone,
{
self.read_type_args(Endian::NATIVE, args)
}
}
Expand Down
Loading

0 comments on commit 5b7ac71

Please sign in to comment.