Skip to content

Commit

Permalink
Replace ReadOptions/WriteOptions with just Endian
Browse files Browse the repository at this point in the history
Assuming jam1garner#24 will not be implemented any time soon,
since there is no longer any need to pass through anything except
endianness, remove the overhead of having an extra object that only
carries endianness.
  • Loading branch information
csnover committed Sep 12, 2022
1 parent bd7d8ea commit 1e5360c
Show file tree
Hide file tree
Showing 36 changed files with 315 additions and 519 deletions.
41 changes: 18 additions & 23 deletions binrw/doc/attribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,13 +643,9 @@ within an object is:
1. A directive on a field
2. A directive on an enum variant
3. A directive on the struct or enum
4. <span class="br">The [`endian`](crate::ReadOptions::endian) property of the
[`ReadOptions`](crate::ReadOptions) object passed to
[`BinRead::read_options`](crate::BinRead::read_options) by the caller</span>
<span class="bw">The [`endian`](crate::WriteOptions::endian) property of the
[`WriteOptions`](crate::WriteOptions) object passed to
[`BinWrite::write_options`](crate::BinWrite::write_options) by the caller</span>
5. The host machine’s native byte order
4. The `endian` parameter of the <span class="br">
[`BinRead::read_options`](crate::BinRead::read_options)</span><span class="bw">
[`BinWrite::write_options`](crate::BinWrite::write_options)</span> call

However, if a byte order directive is added to a struct or enum, that byte
order will *always* be used, even if the object is embedded in another
Expand All @@ -658,7 +654,7 @@ object or explicitly called with a different byte order:
<div class="br">

```
# use binrw::{Endian, ReadOptions, prelude::*, io::Cursor};
# use binrw::{Endian, prelude::*, io::Cursor};
#[derive(BinRead)]
# #[derive(Debug, PartialEq)]
#[br(little)] // ← this *forces* the struct to be little-endian
Expand All @@ -671,16 +667,16 @@ struct Parent {
child: Child,
};
let mut options = ReadOptions::new(Endian::Big /* ← this will be ignored */);
let endian = Endian::Big; /* ← this will be ignored */
# assert_eq!(
Parent::read_options(&mut Cursor::new(b"\x01\0\0\0"), &options, ())
Parent::read_options(&mut Cursor::new(b"\x01\0\0\0"), endian, ())
# .unwrap(), Parent { child: Child(1) });
```
</div>
<div class="bw">

```
# use binrw::{Endian, WriteOptions, prelude::*, io::Cursor};
# use binrw::{Endian, prelude::*, io::Cursor};
#[derive(BinWrite)]
# #[derive(Debug, PartialEq)]
#[bw(little)] // ← this *forces* the struct to be little-endian
Expand All @@ -695,9 +691,9 @@ struct Parent {
let object = Parent { child: Child(1) };
let mut options = WriteOptions::new(Endian::Big /* ← this will be ignored */);
let endian = Endian::Big; /* ← this will be ignored */
let mut output = Cursor::new(vec![]);
object.write_options(&mut output, &options, ())
object.write_options(&mut output, endian, ())
# .unwrap();
# assert_eq!(output.into_inner(), b"\x01\0\0\0");
```
Expand All @@ -706,8 +702,7 @@ object.write_options(&mut output, &options, ())
When manually implementing
<span class="br">[`BinRead::read_options`](crate::BinRead::read_options)</span><span class="bw">[`BinWrite::write_options`](crate::BinWrite::write_options)</span> or a
[custom <span class="br">parser</span><span class="bw">writer</span> function](#custom-parserswriters),
the byte order is accessible from
<span class="br">[`ReadOptions::endian`](crate::ReadOptions::endian)</span><span class="bw">[`WriteOptions::endian`](crate::WriteOptions::endian)</span>.
the byte order is accessible from the `endian` parameter.

## Examples

Expand Down Expand Up @@ -1098,15 +1093,15 @@ calling a function generator).
### Using a custom parser to generate a [`HashMap`](std::collections::HashMap)

```
# use binrw::{prelude::*, io::{prelude::*, Cursor}, ReadOptions};
# use binrw::{prelude::*, io::{prelude::*, Cursor}, Endian};
# use std::collections::HashMap;
fn custom_parser<R: Read + Seek>(reader: &mut R, ro: &ReadOptions, _: ())
fn custom_parser<R: Read + Seek>(reader: &mut R, endian: Endian, _: ())
-> BinResult<HashMap<u16, u16>>
{
let mut map = HashMap::new();
map.insert(
<_>::read_options(reader, ro, ())?,
<_>::read_options(reader, ro, ())?,
<_>::read_options(reader, endian, ())?,
<_>::read_options(reader, endian, ())?,
);
Ok(map)
}
Expand All @@ -1126,17 +1121,17 @@ struct MyType {
### Using a custom serialiser to write a [`BTreeMap`](std::collections::BTreeMap)

```
# use binrw::{prelude::*, io::{prelude::*, Cursor}, WriteOptions};
# use binrw::{prelude::*, io::{prelude::*, Cursor}, Endian};
# use std::collections::BTreeMap;
fn custom_writer<R: Write + Seek>(
map: &BTreeMap<u16, u16>,
writer: &mut R,
wo: &WriteOptions,
endian: Endian,
_: ()
) -> BinResult<()> {
for (key, val) in map.iter() {
key.write_options(writer, wo, ())?;
val.write_options(writer, wo, ())?;
key.write_options(writer, endian, ())?;
val.write_options(writer, endian, ())?;
}
Ok(())
}
Expand Down
64 changes: 27 additions & 37 deletions binrw/src/binread/impls.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
io::{self, Read, Seek, SeekFrom},
BinRead, BinResult, Endian, Error, NamedArgs, ReadOptions,
BinRead, BinResult, Endian, Error, NamedArgs,
};
use alloc::{boxed::Box, vec::Vec};
use core::num::{
Expand All @@ -14,15 +14,15 @@ macro_rules! binread_impl {
impl BinRead for $type_name {
type Args = ();

fn read_options<R: Read + Seek>(reader: &mut R, options: &ReadOptions, _: 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()?;

reader.read_exact(&mut val).or_else(|e| {
reader.seek(SeekFrom::Start(pos))?;
Err(e)
})?;
Ok(match options.endian() {
Ok(match endian {
Endian::Big => {
<$type_name>::from_be_bytes(val)
}
Expand Down Expand Up @@ -53,10 +53,10 @@ macro_rules! binread_nonzero_impl {

fn read_options<R: Read + Seek>(
reader: &mut R,
options: &ReadOptions,
endian: Endian,
_: Self::Args,
) -> BinResult<Self> {
match <$Ty>::new(<$Int>::read_options(reader, options, ())?) {
match <$Ty>::new(<$Int>::read_options(reader, endian, ())?) {
Some(x) => Ok(x),
None => Err(unexpected_zero_num()),
}
Expand Down Expand Up @@ -138,23 +138,18 @@ impl<B: BinRead> BinRead for Vec<B> {

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

fn after_parse<R>(
&mut self,
reader: &mut R,
ro: &ReadOptions,
args: Self::Args,
) -> BinResult<()>
fn after_parse<R>(&mut self, reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<()>
where
R: Read + Seek,
{
for val in self.iter_mut() {
val.after_parse(reader, ro, args.inner.clone())?;
val.after_parse(reader, endian, args.inner.clone())?;
}

Ok(())
Expand All @@ -166,18 +161,18 @@ impl<B: BinRead, const N: usize> BinRead for [B; N] {

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

fn after_parse<R>(&mut self, reader: &mut R, ro: &ReadOptions, args: B::Args) -> BinResult<()>
fn after_parse<R>(&mut self, reader: &mut R, endian: Endian, args: B::Args) -> BinResult<()>
where
R: Read + Seek,
{
for val in self.iter_mut() {
val.after_parse(reader, ro, args.clone())?;
val.after_parse(reader, endian, args.clone())?;
}

Ok(())
Expand All @@ -190,23 +185,23 @@ macro_rules! binread_tuple_impl {
impl<Args: Clone, $type1: BinRead<Args=Args>, $($types: BinRead<Args=Args>),*> BinRead for ($type1, $($types),*) {
type Args = Args;

fn read_options<R: Read + Seek>(reader: &mut R, options: &ReadOptions, 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, options, args.clone())?,
BinRead::read_options(reader, endian, args.clone())?,
$(
<$types>::read_options(reader, options, args.clone())?
<$types>::read_options(reader, endian, args.clone())?
),*
))
}

fn after_parse<R: Read + Seek>(&mut self, reader: &mut R, options: &ReadOptions, 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;

$type1.after_parse(reader, options, args.clone())?;
$type1.after_parse(reader, endian, args.clone())?;
$(
$types.after_parse(reader, options, args.clone())?;
$types.after_parse(reader, endian, args.clone())?;
)*

Ok(())
Expand All @@ -227,7 +222,7 @@ binread_tuple_impl!(
impl BinRead for () {
type Args = ();

fn read_options<R: Read + Seek>(_: &mut R, _: &ReadOptions, _: Self::Args) -> BinResult<Self> {
fn read_options<R: Read + Seek>(_: &mut R, _: Endian, _: Self::Args) -> BinResult<Self> {
Ok(())
}
}
Expand All @@ -237,10 +232,10 @@ impl<T: BinRead> BinRead for Box<T> {

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

Expand All @@ -249,23 +244,18 @@ impl<T: BinRead> BinRead for Option<T> {

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

fn after_parse<R>(
&mut self,
reader: &mut R,
ro: &ReadOptions,
args: Self::Args,
) -> BinResult<()>
fn after_parse<R>(&mut self, reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<()>
where
R: Read + Seek,
{
match self {
Some(val) => val.after_parse(reader, ro, args),
Some(val) => val.after_parse(reader, endian, args),
None => Ok(()),
}
}
Expand All @@ -274,7 +264,7 @@ impl<T: BinRead> BinRead for Option<T> {
impl<T: 'static> BinRead for core::marker::PhantomData<T> {
type Args = ();

fn read_options<R: Read + Seek>(_: &mut R, _: &ReadOptions, _: Self::Args) -> BinResult<Self> {
fn read_options<R: Read + Seek>(_: &mut R, _: Endian, _: Self::Args) -> BinResult<Self> {
Ok(core::marker::PhantomData)
}
}
22 changes: 9 additions & 13 deletions binrw/src/binread/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
mod impls;
mod options;

use crate::{
io::{Read, Seek},
Expand All @@ -8,7 +7,6 @@ use crate::{
meta::ReadEndian,
};
pub use impls::VecArgs;
pub use options::ReadOptions;

/// The `BinRead` trait reads data from streams and converts it into objects.
///
Expand Down Expand Up @@ -118,7 +116,7 @@ pub trait BinRead: Sized + 'static {
where
Self: ReadEndian,
{
Self::read_options(reader, &ReadOptions::new(Endian::Little), args)
Self::read_options(reader, Endian::Little, args)
}

/// Read `Self` from the reader, assuming big-endian byte order, using the
Expand All @@ -129,7 +127,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> {
Self::read_options(reader, &ReadOptions::new(Endian::Big), args)
Self::read_options(reader, Endian::Big, args)
}

/// Read `Self` from the reader, assuming little-endian byte order, using
Expand All @@ -140,7 +138,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> {
Self::read_options(reader, &ReadOptions::new(Endian::Little), args)
Self::read_options(reader, Endian::Little, args)
}

/// Read `T` from the reader, assuming native-endian byte order, using the
Expand All @@ -151,18 +149,18 @@ 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> {
Self::read_options(reader, &ReadOptions::new(Endian::NATIVE), args)
Self::read_options(reader, Endian::NATIVE, args)
}

/// Read `Self` from the reader using the given [`ReadOptions`] and
/// Read `Self` from the reader using the given [`Endian`] and
/// arguments.
///
/// # Errors
///
/// If reading fails, an [`Error`](crate::Error) variant will be returned.
fn read_options<R: Read + Seek>(
reader: &mut R,
options: &ReadOptions,
endian: Endian,
args: Self::Args,
) -> BinResult<Self>;

Expand All @@ -176,7 +174,7 @@ pub trait BinRead: Sized + 'static {
fn after_parse<R: Read + Seek>(
&mut self,
_: &mut R,
_: &ReadOptions,
_: Endian,
_: Self::Args,
) -> BinResult<()> {
Ok(())
Expand Down Expand Up @@ -256,10 +254,8 @@ pub trait BinReaderExt: Read + Seek + Sized {
///
/// 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> {
let options = ReadOptions::new(endian);

let mut res = T::read_options(self, &options, args.clone())?;
res.after_parse(self, &options, args)?;
let mut res = T::read_options(self, endian, args.clone())?;
res.after_parse(self, endian, args)?;

Ok(res)
}
Expand Down
Loading

0 comments on commit 1e5360c

Please sign in to comment.