From def52d8dd454cf72bb022220e966b682f7ed5ffc Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Tue, 6 Sep 2022 23:47:31 -0500 Subject: [PATCH] Replace `ReadOptions`/`WriteOptions` with just `Endian` Assuming jam1garner/binrw#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. --- binrw/doc/attribute.md | 41 ++++----- binrw/src/binread/impls.rs | 64 ++++++------- binrw/src/binread/mod.rs | 22 ++--- binrw/src/binread/options.rs | 42 --------- binrw/src/binwrite/impls.rs | 54 +++++------ binrw/src/binwrite/mod.rs | 53 ++--------- binrw/src/file_ptr.rs | 73 +++++++-------- binrw/src/helpers.rs | 52 +++++------ binrw/src/pos_value.rs | 10 +-- binrw/src/private.rs | 16 ++-- binrw/src/punctuated.rs | 14 +-- binrw/src/strings.rs | 22 ++--- binrw/tests/binwrite_impls.rs | 4 +- binrw/tests/derive/binwrite_temp.rs | 6 +- binrw/tests/derive/struct.rs | 8 +- binrw/tests/derive/write/binread_temp.rs | 4 +- binrw/tests/derive/write/c_enum.rs | 10 +-- binrw/tests/derive/write/calc.rs | 6 +- binrw/tests/derive/write/custom_writer.rs | 6 +- binrw/tests/derive/write/enum.rs | 7 +- binrw/tests/derive/write/if_cond.rs | 8 +- binrw/tests/derive/write/ignore.rs | 4 +- binrw/tests/derive/write/import.rs | 3 +- binrw/tests/derive/write/padding.rs | 7 +- binrw/tests/derive/write/simple.rs | 10 +-- binrw_derive/src/codegen/meta.rs | 8 +- binrw_derive/src/codegen/mod.rs | 31 +++++-- binrw_derive/src/codegen/read_options.rs | 90 ++++--------------- binrw_derive/src/codegen/read_options/enum.rs | 4 +- binrw_derive/src/codegen/read_options/map.rs | 4 +- .../src/codegen/read_options/struct.rs | 69 +++++++------- binrw_derive/src/codegen/sanitization.rs | 4 +- .../src/codegen/write_options/enum.rs | 6 +- .../src/codegen/write_options/prelude.rs | 24 +---- .../src/codegen/write_options/struct_field.rs | 38 +++----- binrw_derive/src/parser/field_level_attrs.rs | 10 +-- 36 files changed, 315 insertions(+), 519 deletions(-) delete mode 100644 binrw/src/binread/options.rs diff --git a/binrw/doc/attribute.md b/binrw/doc/attribute.md index b755efb9..91ad5543 100644 --- a/binrw/doc/attribute.md +++ b/binrw/doc/attribute.md @@ -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. The [`endian`](crate::ReadOptions::endian) property of the - [`ReadOptions`](crate::ReadOptions) object passed to - [`BinRead::read_options`](crate::BinRead::read_options) by the caller - The [`endian`](crate::WriteOptions::endian) property of the - [`WriteOptions`](crate::WriteOptions) object passed to - [`BinWrite::write_options`](crate::BinWrite::write_options) by the caller -5. The host machine’s native byte order +4. The `endian` parameter of the + [`BinRead::read_options`](crate::BinRead::read_options) + [`BinWrite::write_options`](crate::BinWrite::write_options) 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 @@ -658,7 +654,7 @@ object or explicitly called with a different byte order:
``` -# 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 @@ -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) }); ```
``` -# 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 @@ -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"); ``` @@ -706,8 +702,7 @@ object.write_options(&mut output, &options, ()) When manually implementing [`BinRead::read_options`](crate::BinRead::read_options)[`BinWrite::write_options`](crate::BinWrite::write_options) or a [custom parserwriter function](#custom-parserswriters), -the byte order is accessible from -[`ReadOptions::endian`](crate::ReadOptions::endian)[`WriteOptions::endian`](crate::WriteOptions::endian). +the byte order is accessible from the `endian` parameter. ## Examples @@ -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(reader: &mut R, ro: &ReadOptions, _: ()) +fn custom_parser(reader: &mut R, endian: Endian, _: ()) -> BinResult> { 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) } @@ -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( map: &BTreeMap, 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(()) } diff --git a/binrw/src/binread/impls.rs b/binrw/src/binread/impls.rs index d5c9e4d4..45764f06 100644 --- a/binrw/src/binread/impls.rs +++ b/binrw/src/binread/impls.rs @@ -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::{ @@ -14,7 +14,7 @@ macro_rules! binread_impl { impl BinRead for $type_name { type Args = (); - fn read_options(reader: &mut R, options: &ReadOptions, _: Self::Args) -> BinResult { + fn read_options(reader: &mut R, endian: Endian, _: Self::Args) -> BinResult { let mut val = [0; core::mem::size_of::<$type_name>()]; let pos = reader.stream_position()?; @@ -22,7 +22,7 @@ macro_rules! binread_impl { reader.seek(SeekFrom::Start(pos))?; Err(e) })?; - Ok(match options.endian() { + Ok(match endian { Endian::Big => { <$type_name>::from_be_bytes(val) } @@ -53,10 +53,10 @@ macro_rules! binread_nonzero_impl { fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, _: Self::Args, ) -> BinResult { - 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()), } @@ -138,23 +138,18 @@ impl BinRead for Vec { fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: Self::Args, ) -> BinResult { - 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( - &mut self, - reader: &mut R, - ro: &ReadOptions, - args: Self::Args, - ) -> BinResult<()> + fn after_parse(&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(()) @@ -166,18 +161,18 @@ impl BinRead for [B; N] { fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: Self::Args, ) -> BinResult { - 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(&mut self, reader: &mut R, ro: &ReadOptions, args: B::Args) -> BinResult<()> + fn after_parse(&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(()) @@ -190,23 +185,23 @@ macro_rules! binread_tuple_impl { impl, $($types: BinRead),*> BinRead for ($type1, $($types),*) { type Args = Args; - fn read_options(reader: &mut R, options: &ReadOptions, args: Self::Args) -> BinResult { + fn read_options(reader: &mut R, endian: Endian, args: Self::Args) -> BinResult { 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(&mut self, reader: &mut R, options: &ReadOptions, args: Self::Args) -> BinResult<()> { + fn after_parse(&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(()) @@ -227,7 +222,7 @@ binread_tuple_impl!( impl BinRead for () { type Args = (); - fn read_options(_: &mut R, _: &ReadOptions, _: Self::Args) -> BinResult { + fn read_options(_: &mut R, _: Endian, _: Self::Args) -> BinResult { Ok(()) } } @@ -237,10 +232,10 @@ impl BinRead for Box { fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: Self::Args, ) -> BinResult { - Ok(Box::new(T::read_options(reader, options, args)?)) + Ok(Box::new(T::read_options(reader, endian, args)?)) } } @@ -249,23 +244,18 @@ impl BinRead for Option { fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: Self::Args, ) -> BinResult { - Ok(Some(T::read_options(reader, options, args)?)) + Ok(Some(T::read_options(reader, endian, args)?)) } - fn after_parse( - &mut self, - reader: &mut R, - ro: &ReadOptions, - args: Self::Args, - ) -> BinResult<()> + fn after_parse(&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(()), } } @@ -274,7 +264,7 @@ impl BinRead for Option { impl BinRead for core::marker::PhantomData { type Args = (); - fn read_options(_: &mut R, _: &ReadOptions, _: Self::Args) -> BinResult { + fn read_options(_: &mut R, _: Endian, _: Self::Args) -> BinResult { Ok(core::marker::PhantomData) } } diff --git a/binrw/src/binread/mod.rs b/binrw/src/binread/mod.rs index 17c534b2..b7c854eb 100644 --- a/binrw/src/binread/mod.rs +++ b/binrw/src/binread/mod.rs @@ -1,5 +1,4 @@ mod impls; -mod options; use crate::{ io::{Read, Seek}, @@ -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. /// @@ -115,7 +113,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 @@ -126,7 +124,7 @@ pub trait BinRead: Sized + 'static { /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] fn read_be_args(reader: &mut R, args: Self::Args) -> BinResult { - 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 @@ -137,7 +135,7 @@ pub trait BinRead: Sized + 'static { /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] fn read_le_args(reader: &mut R, args: Self::Args) -> BinResult { - 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 @@ -148,10 +146,10 @@ pub trait BinRead: Sized + 'static { /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] fn read_ne_args(reader: &mut R, args: Self::Args) -> BinResult { - 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 @@ -159,7 +157,7 @@ pub trait BinRead: Sized + 'static { /// If reading fails, an [`Error`](crate::Error) variant will be returned. fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: Self::Args, ) -> BinResult; @@ -173,7 +171,7 @@ pub trait BinRead: Sized + 'static { fn after_parse( &mut self, _: &mut R, - _: &ReadOptions, + _: Endian, _: Self::Args, ) -> BinResult<()> { Ok(()) @@ -253,10 +251,8 @@ pub trait BinReaderExt: Read + Seek + Sized { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. fn read_type_args(&mut self, endian: Endian, args: T::Args) -> BinResult { - 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) } diff --git a/binrw/src/binread/options.rs b/binrw/src/binread/options.rs deleted file mode 100644 index 9e896c21..00000000 --- a/binrw/src/binread/options.rs +++ /dev/null @@ -1,42 +0,0 @@ -use super::Endian; -#[cfg(all(doc, not(feature = "std")))] -use alloc::vec::Vec; - -/// Runtime options for -/// [`BinRead::read_options()`](crate::BinRead::read_options). -#[derive(Clone, Copy)] -pub struct ReadOptions { - /// The [byte order](crate::Endian) to use when reading data. - /// - /// Note that if a derived type uses one of the - /// [byte order directives](crate::docs::attribute#byte-order), this option - /// will be overridden by the directive. - endian: Endian, -} - -impl ReadOptions { - /// Creates a new `ReadOptions` with the given [endianness](crate::Endian). - #[must_use] - pub fn new(endian: Endian) -> Self { - Self { endian } - } - - /// The [byte order](crate::Endian) to use when reading data. - /// - /// Note that if a derived type uses one of the - /// [byte order directives](crate::docs::attribute#byte-order), this option - /// will be overridden by the directive. - #[must_use] - pub fn endian(&self) -> Endian { - self.endian - } - - /// Creates a copy of this `ReadOptions` using the given - /// [endianness](crate::Endian). - #[must_use] - // Lint: API compatibility. - #[allow(clippy::unused_self)] - pub fn with_endian(self, endian: Endian) -> Self { - Self { endian } - } -} diff --git a/binrw/src/binwrite/impls.rs b/binrw/src/binwrite/impls.rs index 3b755159..db538c58 100644 --- a/binrw/src/binwrite/impls.rs +++ b/binrw/src/binwrite/impls.rs @@ -1,6 +1,6 @@ use crate::{ io::{Seek, Write}, - BinResult, BinWrite, Endian, WriteOptions, + BinResult, BinWrite, Endian, }; use alloc::{boxed::Box, vec::Vec}; use core::{ @@ -21,10 +21,10 @@ macro_rules! binwrite_num_impl { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, _: Self::Args, ) -> BinResult<()> { - writer.write_all(&match options.endian() { + writer.write_all(&match endian { Endian::Big => self.to_be_bytes(), Endian::Little => self.to_le_bytes(), }).map_err(Into::into) @@ -45,12 +45,12 @@ macro_rules! binwrite_nonzero_num_impl { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, _: Self::Args, ) -> BinResult<()> { let num = <$type_name>::from(*self); - writer.write_all(&match options.endian() { + writer.write_all(&match endian { Endian::Big => num.to_be_bytes(), Endian::Little => num.to_le_bytes(), }).map_err(Into::into) @@ -79,14 +79,14 @@ impl BinWrite for [T; N] { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { if let Some(this) = ::downcast_ref::<[u8; N]>(self) { writer.write_all(&this[..])?; } else { for item in self { - T::write_options(item, writer, options, args.clone())?; + T::write_options(item, writer, endian, args.clone())?; } } @@ -100,11 +100,11 @@ impl BinWrite for [T] { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { for item in self { - T::write_options(item, writer, options, args.clone())?; + T::write_options(item, writer, endian, args.clone())?; } Ok(()) @@ -117,7 +117,7 @@ impl BinWrite for Vec { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { if let Some(this) = ::downcast_ref::>(self) { @@ -126,7 +126,7 @@ impl BinWrite for Vec { writer.write_all(bytemuck::cast_slice(this.as_slice()))?; } else { for item in self { - T::write_options(item, writer, options, args.clone())?; + T::write_options(item, writer, endian, args.clone())?; } } @@ -140,10 +140,10 @@ impl BinWrite for &T { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { - (**self).write_options(writer, options, args) + (**self).write_options(writer, endian, args) } } @@ -153,13 +153,13 @@ impl BinWrite for Box { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { if let Some(this) = ::downcast_ref::>(self) { writer.write_all(this)?; } else { - (**self).write_options(writer, options, args)?; + (**self).write_options(writer, endian, args)?; } Ok(()) @@ -172,11 +172,11 @@ impl BinWrite for Option { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { match self { - Some(inner) => inner.write_options(writer, options, args), + Some(inner) => inner.write_options(writer, endian, args), None => Ok(()), } } @@ -185,12 +185,7 @@ impl BinWrite for Option { impl BinWrite for PhantomData { type Args = T::Args; - fn write_options( - &self, - _: &mut W, - _: &WriteOptions, - _: Self::Args, - ) -> BinResult<()> { + fn write_options(&self, _: &mut W, _: Endian, _: Self::Args) -> BinResult<()> { Ok(()) } } @@ -198,12 +193,7 @@ impl BinWrite for PhantomData { impl BinWrite for () { type Args = (); - fn write_options( - &self, - _: &mut W, - _: &WriteOptions, - _: Self::Args, - ) -> BinResult<()> { + fn write_options(&self, _: &mut W, _: Endian, _: Self::Args) -> BinResult<()> { Ok(()) } } @@ -219,16 +209,16 @@ macro_rules! binwrite_tuple_impl { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { let ($type1, $( $types ),*) = self; - $type1.write_options(writer, options, args.clone())?; + $type1.write_options(writer, endian, args.clone())?; $( - $types.write_options(writer, options, args.clone())?; + $types.write_options(writer, endian, args.clone())?; )* Ok(()) diff --git a/binrw/src/binwrite/mod.rs b/binrw/src/binwrite/mod.rs index 8ebcb3c6..e8f3704d 100644 --- a/binrw/src/binwrite/mod.rs +++ b/binrw/src/binwrite/mod.rs @@ -96,7 +96,7 @@ pub trait BinWrite { where Self: crate::meta::WriteEndian, { - self.write_options(writer, &WriteOptions::new(Endian::Little), args) + self.write_options(writer, Endian::Little, args) } /// Write `Self` to the writer, assuming big-endian byte order, using the @@ -107,7 +107,7 @@ pub trait BinWrite { /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] fn write_be_args(&self, writer: &mut W, args: Self::Args) -> BinResult<()> { - self.write_options(writer, &WriteOptions::new(Endian::Big), args) + self.write_options(writer, Endian::Big, args) } /// Write `Self` to the writer, assuming little-endian byte order, using the @@ -118,10 +118,10 @@ pub trait BinWrite { /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] fn write_le_args(&self, writer: &mut W, args: Self::Args) -> BinResult<()> { - self.write_options(writer, &WriteOptions::new(Endian::Little), args) + self.write_options(writer, Endian::Little, args) } - /// Write `Self` to the writer using the given [`WriteOptions`] and + /// Write `Self` to the writer using the given [`Endian`] and /// arguments. /// /// # Errors @@ -130,50 +130,11 @@ pub trait BinWrite { fn write_options( &self, writer: &mut W, - options: &WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()>; } -/// Runtime options for -/// [`BinWrite::write_options()`](crate::BinWrite::write_options). -#[derive(Clone, Copy)] -pub struct WriteOptions { - /// The [byte order](crate::Endian) to use when writing data. - /// - /// Note that if a derived type uses one of the - /// [byte order directives](crate::docs::attribute#byte-order), this option - /// will be overridden by the directive. - endian: Endian, -} - -impl WriteOptions { - /// Creates a new `WriteOptions` with the given [endianness](crate::Endian). - #[must_use] - pub fn new(endian: Endian) -> Self { - Self { endian } - } - - /// The [byte order](crate::Endian) to use when writing data. - /// - /// Note that if a derived type uses one of the - /// [byte order directives](crate::docs::attribute#byte-order), this option - /// will be overridden by the directive. - #[must_use] - pub fn endian(&self) -> Endian { - self.endian - } - - /// Creates a copy of this `WriteOptions` using the given - /// [endianness](crate::Endian). - #[must_use] - // Lint: For symmetry with `ReadOptions`. - #[allow(clippy::unused_self)] - pub fn with_endian(self, endian: Endian) -> Self { - Self { endian } - } -} - /// Extension methods for writing [`BinWrite`] objects directly to a writer. /// /// # Examples @@ -250,9 +211,7 @@ pub trait BinWriterExt: Write + Seek + Sized { endian: Endian, args: T::Args, ) -> BinResult<()> { - let options = WriteOptions::new(endian); - - T::write_options(value, self, &options, args)?; + T::write_options(value, self, endian, args)?; Ok(()) } diff --git a/binrw/src/file_ptr.rs b/binrw/src/file_ptr.rs index 39aea459..b8fcbb15 100644 --- a/binrw/src/file_ptr.rs +++ b/binrw/src/file_ptr.rs @@ -1,6 +1,11 @@ //! Type definitions for wrappers which represent a layer of indirection within //! a file. +use crate::NamedArgs; +use crate::{ + io::{Read, Seek, SeekFrom}, + BinRead, BinResult, Endian, +}; use core::fmt; use core::num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16, @@ -8,12 +13,6 @@ use core::num::{ }; use core::ops::{Deref, DerefMut}; -use crate::NamedArgs; -use crate::{ - io::{Read, Seek, SeekFrom}, - BinRead, BinResult, ReadOptions, -}; - /// A type alias for [`FilePtr`] with 8-bit offsets. pub type FilePtr8 = FilePtr; /// A type alias for [`FilePtr`] with 16-bit offsets. @@ -87,11 +86,11 @@ impl + IntoSeekFrom, Value: BinRead> BinRead for FilePtr /// [`after_parse()`](Self::after_parse) is called. fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, _: Self::Args, ) -> BinResult { Ok(FilePtr { - ptr: Ptr::read_options(reader, options, ())?, + ptr: Ptr::read_options(reader, endian, ())?, value: None, }) } @@ -100,64 +99,66 @@ impl + IntoSeekFrom, Value: BinRead> BinRead for FilePtr fn after_parse( &mut self, reader: &mut R, - ro: &ReadOptions, + endian: Endian, args: FilePtrArgs, ) -> BinResult<()> where R: Read + Seek, { - self.after_parse_with_parser(Value::read_options, Value::after_parse, reader, ro, args) + self.after_parse_with_parser( + Value::read_options, + Value::after_parse, + reader, + endian, + args, + ) } } impl + IntoSeekFrom, Value> FilePtr { - // Lint: Non-consumed argument is required to match the API. - #[allow(clippy::trivially_copy_pass_by_ref)] fn read_with_parser( parser: Parser, after_parse: AfterParse, reader: &mut R, - options: &ReadOptions, + endian: Endian, args: FilePtrArgs, ) -> BinResult where R: Read + Seek, Args: Clone, - Parser: Fn(&mut R, &ReadOptions, Args) -> BinResult, - AfterParse: Fn(&mut Value, &mut R, &ReadOptions, Args) -> BinResult<()>, + Parser: Fn(&mut R, Endian, Args) -> BinResult, + AfterParse: Fn(&mut Value, &mut R, Endian, Args) -> BinResult<()>, { let mut file_ptr = Self { - ptr: Ptr::read_options(reader, options, ())?, + ptr: Ptr::read_options(reader, endian, ())?, value: None, }; - file_ptr.after_parse_with_parser(parser, after_parse, reader, options, args)?; + file_ptr.after_parse_with_parser(parser, after_parse, reader, endian, args)?; Ok(file_ptr) } - // Lint: Non-consumed argument is required to match the API. - #[allow(clippy::trivially_copy_pass_by_ref)] fn after_parse_with_parser( &mut self, parser: Parser, after_parse: AfterParse, reader: &mut R, - options: &ReadOptions, + endian: Endian, args: FilePtrArgs, ) -> BinResult<()> where R: Read + Seek, Args: Clone, - Parser: Fn(&mut R, &ReadOptions, Args) -> BinResult, - AfterParse: Fn(&mut Value, &mut R, &ReadOptions, Args) -> BinResult<()>, + Parser: Fn(&mut R, Endian, Args) -> BinResult, + AfterParse: Fn(&mut Value, &mut R, Endian, Args) -> BinResult<()>, { let relative_to = args.offset; let before = reader.stream_position()?; reader.seek(SeekFrom::Start(relative_to))?; reader.seek(self.ptr.into_seek_from())?; - let mut inner: Value = parser(reader, options, args.inner.clone())?; + let mut inner: Value = parser(reader, endian, args.inner.clone())?; - after_parse(&mut inner, reader, options, args.inner)?; + after_parse(&mut inner, reader, endian, args.inner)?; reader.seek(SeekFrom::Start(before))?; self.value = Some(inner); @@ -174,7 +175,7 @@ impl + IntoSeekFrom, Value> FilePtr { /// If reading fails, an [`Error`](crate::Error) variant will be returned. pub fn parse( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: FilePtrArgs, ) -> BinResult where @@ -186,7 +187,7 @@ impl + IntoSeekFrom, Value> FilePtr { Value::read_options, Value::after_parse, reader, - options, + endian, args, )? .into_inner()) @@ -202,15 +203,15 @@ impl + IntoSeekFrom, Value> FilePtr { /// If reading fails, an [`Error`](crate::Error) variant will be returned. pub fn parse_with( parser: F, - ) -> impl Fn(&mut R, &ReadOptions, FilePtrArgs) -> BinResult + ) -> impl Fn(&mut R, Endian, FilePtrArgs) -> BinResult where R: Read + Seek, Args: Clone, - F: Fn(&mut R, &ReadOptions, Args) -> BinResult, + F: Fn(&mut R, Endian, Args) -> BinResult, { - move |reader, ro, args| { - let after_parse = |_: &mut Value, _: &mut R, _: &ReadOptions, _: Args| Ok(()); - Ok(Self::read_with_parser(&parser, after_parse, reader, ro, args)?.into_inner()) + move |reader, endian, args| { + let after_parse = |_: &mut Value, _: &mut R, _: Endian, _: Args| Ok(()); + Ok(Self::read_with_parser(&parser, after_parse, reader, endian, args)?.into_inner()) } } @@ -224,15 +225,15 @@ impl + IntoSeekFrom, Value> FilePtr { /// If reading fails, an [`Error`](crate::Error) variant will be returned. pub fn with( parser: F, - ) -> impl Fn(&mut R, &ReadOptions, FilePtrArgs) -> BinResult + ) -> impl Fn(&mut R, Endian, FilePtrArgs) -> BinResult where R: Read + Seek, Args: Clone, - F: Fn(&mut R, &ReadOptions, Args) -> BinResult, + F: Fn(&mut R, Endian, Args) -> BinResult, { - move |reader, ro, args| { - let after_parse = |_: &mut Value, _: &mut R, _: &ReadOptions, _: Args| Ok(()); - Self::read_with_parser(&parser, after_parse, reader, ro, args) + move |reader, endian, args| { + let after_parse = |_: &mut Value, _: &mut R, _: Endian, _: Args| Ok(()); + Self::read_with_parser(&parser, after_parse, reader, endian, args) } } diff --git a/binrw/src/helpers.rs b/binrw/src/helpers.rs index e98262ae..176bf44b 100644 --- a/binrw/src/helpers.rs +++ b/binrw/src/helpers.rs @@ -2,7 +2,7 @@ use crate::{ io::{self, Read, Seek}, - BinRead, BinResult, Error, ReadOptions, + BinRead, BinResult, Endian, Error, }; use alloc::vec::Vec; use core::iter::from_fn; @@ -29,7 +29,7 @@ use core::iter::from_fn; /// ``` pub fn until( cond: CondFn, -) -> impl Fn(&mut Reader, &ReadOptions, Arg) -> BinResult +) -> impl Fn(&mut Reader, Endian, Arg) -> BinResult where T: BinRead, Reader: Read + Seek, @@ -69,21 +69,21 @@ where pub fn until_with( cond: CondFn, read: ReadFn, -) -> impl Fn(&mut Reader, &ReadOptions, Arg) -> BinResult +) -> impl Fn(&mut Reader, Endian, Arg) -> BinResult where Reader: Read + Seek, CondFn: Fn(&T) -> bool, Arg: Clone, - ReadFn: Fn(&mut Reader, &ReadOptions, Arg) -> BinResult, + ReadFn: Fn(&mut Reader, Endian, Arg) -> BinResult, Ret: FromIterator, { - move |reader, ro, args| { + move |reader, endian, args| { let mut last = false; from_fn(|| { if last { None } else { - match read(reader, ro, args.clone()) { + match read(reader, endian, args.clone()) { Ok(value) => { if cond(&value) { last = true; @@ -121,7 +121,7 @@ where /// ``` pub fn until_exclusive( cond: CondFn, -) -> impl Fn(&mut Reader, &ReadOptions, Arg) -> BinResult +) -> impl Fn(&mut Reader, Endian, Arg) -> BinResult where T: BinRead, Reader: Read + Seek, @@ -161,16 +161,16 @@ where pub fn until_exclusive_with( cond: CondFn, read: ReadFn, -) -> impl Fn(&mut Reader, &ReadOptions, Arg) -> BinResult +) -> impl Fn(&mut Reader, Endian, Arg) -> BinResult where Reader: Read + Seek, CondFn: Fn(&T) -> bool, Arg: Clone, - ReadFn: Fn(&mut Reader, &ReadOptions, Arg) -> BinResult, + ReadFn: Fn(&mut Reader, Endian, Arg) -> BinResult, Ret: FromIterator, { - move |reader, ro, args| { - from_fn(|| match read(reader, ro, args.clone()) { + move |reader, endian, args| { + from_fn(|| match read(reader, endian, args.clone()) { Ok(value) => { if cond(&value) { None @@ -212,7 +212,7 @@ where /// ``` pub fn until_eof( reader: &mut Reader, - ro: &ReadOptions, + endian: Endian, args: Arg, ) -> BinResult where @@ -221,7 +221,7 @@ where Arg: Clone, Ret: FromIterator, { - until_eof_with(default_reader)(reader, ro, args) + until_eof_with(default_reader)(reader, endian, args) } /// Creates a parser that uses a given function to read items into a collection @@ -257,15 +257,15 @@ where /// ``` pub fn until_eof_with( read: ReadFn, -) -> impl Fn(&mut Reader, &ReadOptions, Arg) -> BinResult +) -> impl Fn(&mut Reader, Endian, Arg) -> BinResult where Reader: Read + Seek, Arg: Clone, - ReadFn: Fn(&mut Reader, &ReadOptions, Arg) -> BinResult, + ReadFn: Fn(&mut Reader, Endian, Arg) -> BinResult, Ret: FromIterator, { - move |reader, ro, args| { - from_fn(|| match read(reader, ro, args.clone()) { + move |reader, endian, args| { + from_fn(|| match read(reader, endian, args.clone()) { ok @ Ok(_) => Some(ok), Err(err) if err.is_eof() => None, err => Some(err), @@ -298,7 +298,7 @@ where /// # let x: CountBytes = x.read_be().unwrap(); /// # assert_eq!(x.data, &[1, 2, 3]); /// ``` -pub fn count(n: usize) -> impl Fn(&mut R, &ReadOptions, Arg) -> BinResult +pub fn count(n: usize) -> impl Fn(&mut R, Endian, Arg) -> BinResult where T: BinRead, R: Read + Seek, @@ -339,17 +339,17 @@ where pub fn count_with( n: usize, read: ReadFn, -) -> impl Fn(&mut R, &ReadOptions, Arg) -> BinResult +) -> impl Fn(&mut R, Endian, Arg) -> BinResult where R: Read + Seek, Arg: Clone, - ReadFn: Fn(&mut R, &ReadOptions, Arg) -> BinResult, + ReadFn: Fn(&mut R, Endian, Arg) -> BinResult, Ret: FromIterator + 'static, { - move |reader, ro, args| { + move |reader, endian, args| { let mut container = core::iter::empty::().collect::(); - vec_fast_int!(try (i8 i16 u16 i32 u32 i64 u64 i128 u128) using (container, reader, ro.endian(), n) else { + vec_fast_int!(try (i8 i16 u16 i32 u32 i64 u64 i128 u128) using (container, reader, endian, n) else { // This extra branch for `Vec` makes it faster than // `vec_fast_int`, but *only* because `vec_fast_int` is not allowed // to use unsafe code to eliminate the unnecessary zero-fill. @@ -367,7 +367,7 @@ where Err(not_enough_bytes(())) } } else { - core::iter::repeat_with(|| read(reader, ro, args.clone())) + core::iter::repeat_with(|| read(reader, endian, args.clone())) .take(n) .collect() } @@ -379,11 +379,11 @@ where #[allow(clippy::trivially_copy_pass_by_ref)] fn default_reader>( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: T::Args, ) -> BinResult { - let mut value = T::read_options(reader, options, args.clone())?; - value.after_parse(reader, options, args)?; + let mut value = T::read_options(reader, endian, args.clone())?; + value.after_parse(reader, endian, args)?; Ok(value) } diff --git a/binrw/src/pos_value.rs b/binrw/src/pos_value.rs index 5780f0fc..1ed9b2fd 100644 --- a/binrw/src/pos_value.rs +++ b/binrw/src/pos_value.rs @@ -1,6 +1,6 @@ use crate::{ io::{Read, Seek}, - BinRead, BinResult, ReadOptions, + BinRead, BinResult, Endian, }; use core::fmt; @@ -34,24 +34,24 @@ impl BinRead for PosValue { fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: T::Args, ) -> BinResult { let pos = reader.stream_position()?; Ok(PosValue { pos, - val: T::read_options(reader, options, args)?, + val: T::read_options(reader, endian, args)?, }) } fn after_parse( &mut self, reader: &mut R, - options: &ReadOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { - self.val.after_parse(reader, options, args) + self.val.after_parse(reader, endian, args) } } diff --git a/binrw/src/private.rs b/binrw/src/private.rs index 15eba009..3e1b971e 100644 --- a/binrw/src/private.rs +++ b/binrw/src/private.rs @@ -1,7 +1,7 @@ use crate::{ error::CustomError, io::{self, Seek, Write}, - BinRead, BinResult, Error, ReadOptions, WriteOptions, + BinRead, BinResult, Endian, Error, }; use alloc::{boxed::Box, string::String}; @@ -72,13 +72,13 @@ where f } -pub fn magic(reader: &mut R, expected: B, options: &ReadOptions) -> BinResult<()> +pub fn magic(reader: &mut R, expected: B, endian: Endian) -> BinResult<()> where B: BinRead + core::fmt::Debug + PartialEq + Sync + Send + Clone + Copy + 'static, R: io::Read + io::Seek, { let pos = reader.stream_position()?; - let val = B::read_options(reader, options, ())?; + let val = B::read_options(reader, endian, ())?; if val == expected { Ok(()) } else { @@ -92,7 +92,7 @@ where pub fn parse_function_args_type_hint(_: F, a: Args) -> Args where R: crate::io::Read + Seek, - F: FnOnce(&mut R, &crate::ReadOptions, Args) -> crate::BinResult, + F: FnOnce(&mut R, Endian, Args) -> crate::BinResult, { a } @@ -100,7 +100,7 @@ where pub fn write_function_args_type_hint(_: F, a: Args) -> Args where W: Write + Seek, - F: FnOnce(&T, &mut W, &crate::WriteOptions, Args) -> crate::BinResult<()>, + F: FnOnce(&T, &mut W, Endian, Args) -> crate::BinResult<()>, { a } @@ -117,7 +117,7 @@ pub fn write_fn_type_hint(x: WriterFn) -> WriterFn where Args: Clone, Writer: Write + Seek, - WriterFn: Fn(&T, &mut Writer, &WriteOptions, Args) -> BinResult<()>, + WriterFn: Fn(&T, &mut Writer, Endian, Args) -> BinResult<()>, { x } @@ -157,7 +157,7 @@ where MapFn: FnOnce(Input) -> Output, Args: Clone, Writer: Write + Seek, - WriteFn: Fn(&Output, &mut Writer, &WriteOptions, Args) -> BinResult<()>, + WriteFn: Fn(&Output, &mut Writer, Endian, Args) -> BinResult<()>, { func } @@ -171,7 +171,7 @@ where MapFn: FnOnce(Input) -> Result, Args: Clone, Writer: Write + Seek, - WriteFn: Fn(&Output, &mut Writer, &WriteOptions, Args) -> BinResult<()>, + WriteFn: Fn(&Output, &mut Writer, Endian, Args) -> BinResult<()>, { func } diff --git a/binrw/src/punctuated.rs b/binrw/src/punctuated.rs index 84ca249d..cf939729 100644 --- a/binrw/src/punctuated.rs +++ b/binrw/src/punctuated.rs @@ -2,7 +2,7 @@ use crate::{ io::{Read, Seek}, - BinRead, BinResult, ReadOptions, VecArgs, + BinRead, BinResult, Endian, VecArgs, }; use alloc::vec::Vec; use core::fmt; @@ -78,16 +78,16 @@ impl> Punctuated { #[allow(clippy::needless_pass_by_value)] pub fn separated( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: VecArgs, ) -> BinResult { let mut data = Vec::with_capacity(args.count); let mut separators = Vec::with_capacity(args.count.max(1) - 1); for i in 0..args.count { - data.push(T::read_options(reader, options, args.inner.clone())?); + data.push(T::read_options(reader, endian, args.inner.clone())?); if i + 1 != args.count { - separators.push(P::read_options(reader, options, ())?); + separators.push(P::read_options(reader, endian, ())?); } } @@ -106,15 +106,15 @@ impl> Punctuated { #[allow(clippy::needless_pass_by_value)] pub fn separated_trailing( reader: &mut R, - options: &ReadOptions, + endian: Endian, args: VecArgs, ) -> BinResult { let mut data = Vec::with_capacity(args.count); let mut separators = Vec::with_capacity(args.count); for _ in 0..args.count { - data.push(T::read_options(reader, options, args.inner.clone())?); - separators.push(P::read_options(reader, options, ())?); + data.push(T::read_options(reader, endian, args.inner.clone())?); + separators.push(P::read_options(reader, endian, ())?); } Ok(Self { data, separators }) diff --git a/binrw/src/strings.rs b/binrw/src/strings.rs index 32f7eb33..02e6232a 100644 --- a/binrw/src/strings.rs +++ b/binrw/src/strings.rs @@ -3,7 +3,7 @@ use crate::{ alloc::string::{FromUtf16Error, FromUtf8Error}, io::{Read, Seek, Write}, - BinRead, BinResult, BinWrite, ReadOptions, + BinRead, BinResult, BinWrite, Endian, }; use alloc::{string::String, vec, vec::Vec}; use core::fmt::{self, Write as _}; @@ -38,13 +38,13 @@ impl BinRead for NullString { fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, _: Self::Args, ) -> BinResult { let mut values = vec![]; loop { - let val = ::read_options(reader, options, ())?; + let val = ::read_options(reader, endian, ())?; if val == 0 { return Ok(Self(values)); } @@ -59,11 +59,11 @@ impl BinWrite for NullString { fn write_options( &self, writer: &mut W, - options: &crate::WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { - self.0.write_options(writer, options, args)?; - 0u8.write_options(writer, options, args)?; + self.0.write_options(writer, endian, args)?; + 0u8.write_options(writer, endian, args)?; Ok(()) } @@ -160,13 +160,13 @@ impl BinRead for NullWideString { fn read_options( reader: &mut R, - options: &ReadOptions, + endian: Endian, _: Self::Args, ) -> BinResult { let mut values = vec![]; loop { - let val = ::read_options(reader, options, ())?; + let val = ::read_options(reader, endian, ())?; if val == 0 { return Ok(Self(values)); } @@ -181,11 +181,11 @@ impl BinWrite for NullWideString { fn write_options( &self, writer: &mut W, - options: &crate::WriteOptions, + endian: Endian, args: Self::Args, ) -> BinResult<()> { - self.0.write_options(writer, options, args)?; - 0u16.write_options(writer, options, args)?; + self.0.write_options(writer, endian, args)?; + 0u16.write_options(writer, endian, args)?; Ok(()) } diff --git a/binrw/tests/binwrite_impls.rs b/binrw/tests/binwrite_impls.rs index d9bb2eee..8da25c36 100644 --- a/binrw/tests/binwrite_impls.rs +++ b/binrw/tests/binwrite_impls.rs @@ -3,9 +3,7 @@ use binrw::{BinWrite, Endian}; macro_rules! compare { ($input:expr, $endian:expr, $output:expr) => { let mut output = binrw::io::Cursor::new(vec![]); - $input - .write_options(&mut output, &binrw::WriteOptions::new($endian), ()) - .unwrap(); + $input.write_options(&mut output, $endian, ()).unwrap(); assert_eq!(output.into_inner(), $output); }; diff --git a/binrw/tests/derive/binwrite_temp.rs b/binrw/tests/derive/binwrite_temp.rs index fa508a1d..c7e7bd4c 100644 --- a/binrw/tests/derive/binwrite_temp.rs +++ b/binrw/tests/derive/binwrite_temp.rs @@ -1,4 +1,4 @@ -use binrw::{binrw, io::Cursor, BinRead, BinWrite, Endian, WriteOptions}; +use binrw::{binrw, io::Cursor, BinRead, BinWrite, Endian}; #[test] fn binwrite_temp_applies() { @@ -48,9 +48,7 @@ fn binwrite_temp_with_ignore() { let mut x = Cursor::new(Vec::new()); - result - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) - .unwrap(); + result.write_options(&mut x, Endian::Big, ()).unwrap(); // Since it's bw(ignore), the length isn't written here assert_eq!(x.into_inner(), b"ABCDE"); diff --git a/binrw/tests/derive/struct.rs b/binrw/tests/derive/struct.rs index 3ac53680..489ea7ff 100644 --- a/binrw/tests/derive/struct.rs +++ b/binrw/tests/derive/struct.rs @@ -1,7 +1,7 @@ use binrw::{ args, binread, io::{Cursor, Read, Seek, SeekFrom}, - BinRead, BinResult, FilePtr, NullString, ReadOptions, + BinRead, BinResult, Endian, FilePtr, NullString, }; #[test] @@ -28,12 +28,12 @@ fn all_the_things() { fn read_offsets( reader: &mut R, - ro: &ReadOptions, + endian: Endian, _: (), ) -> BinResult<(u16, u16)> { Ok(( - u16::read_options(reader, ro, ())?, - u16::read_options(reader, ro, ())?, + u16::read_options(reader, endian, ())?, + u16::read_options(reader, endian, ())?, )) } diff --git a/binrw/tests/derive/write/binread_temp.rs b/binrw/tests/derive/write/binread_temp.rs index d6239927..0190131b 100644 --- a/binrw/tests/derive/write/binread_temp.rs +++ b/binrw/tests/derive/write/binread_temp.rs @@ -1,4 +1,4 @@ -use binrw::{binrw, io::Cursor, BinWrite, Endian, WriteOptions}; +use binrw::{binrw, io::Cursor, BinWrite, Endian}; #[test] fn binread_temp_applies() { @@ -22,7 +22,7 @@ fn binread_temp_applies() { Test { inner: TestInner {}, } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!(x.into_inner(), [0, 0, 0, 1]); diff --git a/binrw/tests/derive/write/c_enum.rs b/binrw/tests/derive/write/c_enum.rs index abb0501b..9ad8b544 100644 --- a/binrw/tests/derive/write/c_enum.rs +++ b/binrw/tests/derive/write/c_enum.rs @@ -1,5 +1,5 @@ use binrw::io::Cursor; -use binrw::{BinRead, BinReaderExt, BinWrite, Endian, WriteOptions}; +use binrw::{BinRead, BinReaderExt, BinWrite, Endian}; #[test] fn write_enum() { @@ -15,7 +15,7 @@ fn write_enum() { let mut x = Cursor::new(Vec::new()); vec![Test::A, Test::B, Test::C, Test::D] - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!( @@ -42,8 +42,7 @@ fn round_trip_unit_enum() { let mut x = Cursor::new(Vec::new()); - test.write_options(&mut x, &WriteOptions::new(Endian::Big), ()) - .unwrap(); + test.write_options(&mut x, Endian::Big, ()).unwrap(); assert_eq!(x.into_inner(), data); } @@ -70,8 +69,7 @@ fn magic_enum_round_trip() { let mut x = Cursor::new(Vec::new()); - test.write_options(&mut x, &WriteOptions::new(Endian::Big), ()) - .unwrap(); + test.write_options(&mut x, Endian::Big, ()).unwrap(); assert_eq!(x.into_inner(), data); } diff --git a/binrw/tests/derive/write/calc.rs b/binrw/tests/derive/write/calc.rs index e7dd571a..4b817eb7 100644 --- a/binrw/tests/derive/write/calc.rs +++ b/binrw/tests/derive/write/calc.rs @@ -1,4 +1,4 @@ -use binrw::{binwrite, io::Cursor, BinWrite, Endian, WriteOptions}; +use binrw::{binwrite, io::Cursor, BinWrite, Endian}; #[test] fn calc_simple_write() { @@ -16,7 +16,7 @@ fn calc_simple_write() { let mut x = Cursor::new(Vec::new()); Test { x: 1 } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!(x.into_inner(), [1, 0, 2, 0, 0, 0, 3]); @@ -39,7 +39,7 @@ fn calc_visibility() { let mut x = Cursor::new(Vec::new()); Test { x: 1 } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!(x.into_inner(), [1, 0, 2, 0, 3]); diff --git a/binrw/tests/derive/write/custom_writer.rs b/binrw/tests/derive/write/custom_writer.rs index b17f511d..092eae93 100644 --- a/binrw/tests/derive/write/custom_writer.rs +++ b/binrw/tests/derive/write/custom_writer.rs @@ -1,4 +1,4 @@ -use binrw::{io::Cursor, BinWrite, Endian, WriteOptions}; +use binrw::{io::Cursor, BinWrite, Endian}; #[test] fn custom_writer() { @@ -13,7 +13,7 @@ fn custom_writer() { fn custom_writer( _this: &u16, writer: &mut W, - _opts: &WriteOptions, + _: Endian, _: (), ) -> binrw::BinResult<()> { writer.write_all(b"abcd")?; @@ -23,7 +23,7 @@ fn custom_writer() { let mut x = Cursor::new(Vec::new()); Test { x: 1, y: 2 } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!(x.into_inner(), b"\x01abcd"); diff --git a/binrw/tests/derive/write/enum.rs b/binrw/tests/derive/write/enum.rs index 642fdd0c..6f6c69d5 100644 --- a/binrw/tests/derive/write/enum.rs +++ b/binrw/tests/derive/write/enum.rs @@ -1,5 +1,5 @@ use binrw::io::Cursor; -use binrw::{BinRead, BinReaderExt, BinWrite, Endian, WriteOptions}; +use binrw::{BinRead, BinReaderExt, BinWrite, Endian}; #[test] fn enum_round_trip() { @@ -30,8 +30,7 @@ fn enum_round_trip() { let mut x = Cursor::new(Vec::new()); - test.write_options(&mut x, &WriteOptions::new(Endian::Big), ()) - .unwrap(); + test.write_options(&mut x, Endian::Big, ()).unwrap(); assert_eq!(x.into_inner(), data); } @@ -65,7 +64,7 @@ fn enum_one_way() { y: 0xFF, }, ] - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!( diff --git a/binrw/tests/derive/write/if_cond.rs b/binrw/tests/derive/write/if_cond.rs index eb0bd995..04735245 100644 --- a/binrw/tests/derive/write/if_cond.rs +++ b/binrw/tests/derive/write/if_cond.rs @@ -1,5 +1,5 @@ use binrw::BinWrite; -use binrw::{io::Cursor, Endian, WriteOptions}; +use binrw::{io::Cursor, Endian}; #[derive(BinWrite)] struct Test { @@ -15,7 +15,7 @@ fn if_cond() { let mut x = Cursor::new(Vec::new()); Test { x: 1, y: 2, z: 3 } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!(&x.into_inner(), &[1, 0, 10]); @@ -23,7 +23,7 @@ fn if_cond() { let mut x = Cursor::new(Vec::new()); Test { x: 2, y: 3, z: 4 } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!(&x.into_inner(), &[2, 0, 3]); @@ -31,7 +31,7 @@ fn if_cond() { let mut x = Cursor::new(Vec::new()); Test { x: 3, y: 4, z: 5 } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!(&x.into_inner(), &[3, 0, 4, 0, 0, 0, 5]); diff --git a/binrw/tests/derive/write/ignore.rs b/binrw/tests/derive/write/ignore.rs index 128b6fe9..7d240f7c 100644 --- a/binrw/tests/derive/write/ignore.rs +++ b/binrw/tests/derive/write/ignore.rs @@ -1,4 +1,4 @@ -use binrw::{binwrite, io::Cursor, BinWrite, Endian, WriteOptions}; +use binrw::{binwrite, io::Cursor, BinWrite, Endian}; #[test] fn ignore_is_not_written() { @@ -11,7 +11,7 @@ fn ignore_is_not_written() { let mut x = Cursor::new(Vec::new()); Test { x: 1 } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); // Since it's bw(ignore), nothing is written here. diff --git a/binrw/tests/derive/write/import.rs b/binrw/tests/derive/write/import.rs index 2b4efc68..88945dc9 100644 --- a/binrw/tests/derive/write/import.rs +++ b/binrw/tests/derive/write/import.rs @@ -1,5 +1,4 @@ -use binrw::binrw; -use binrw::BinWrite; +use binrw::{binrw, BinWrite}; #[test] fn correct_args_type_set() { diff --git a/binrw/tests/derive/write/padding.rs b/binrw/tests/derive/write/padding.rs index 9a1fc101..106e3ce6 100644 --- a/binrw/tests/derive/write/padding.rs +++ b/binrw/tests/derive/write/padding.rs @@ -1,5 +1,5 @@ use binrw::io::Cursor; -use binrw::{BinRead, BinReaderExt, BinWrite, Endian, WriteOptions}; +use binrw::{BinRead, BinReaderExt, BinWrite, Endian}; #[test] fn padding_big() { @@ -37,8 +37,7 @@ fn padding_round_trip() { let mut x = Cursor::new(Vec::new()); - test.write_options(&mut x, &WriteOptions::new(Endian::Big), ()) - .unwrap(); + test.write_options(&mut x, Endian::Big, ()).unwrap(); assert_eq!(x.into_inner(), data); } @@ -70,7 +69,7 @@ fn padding_one_way() { y: 2, z: 0xabcdef, } - .write_options(&mut x, &WriteOptions::new(Endian::Little), ()) + .write_options(&mut x, Endian::Little, ()) .unwrap(); assert_eq!(x.into_inner(), data); diff --git a/binrw/tests/derive/write/simple.rs b/binrw/tests/derive/write/simple.rs index 2ce0cc1e..5ac46262 100644 --- a/binrw/tests/derive/write/simple.rs +++ b/binrw/tests/derive/write/simple.rs @@ -1,4 +1,4 @@ -use binrw::{io::Cursor, Endian, WriteOptions}; +use binrw::{io::Cursor, Endian}; use binrw::{BinRead, BinWrite, BinWriterExt}; #[derive(BinWrite)] @@ -13,7 +13,7 @@ fn simple_write() { let mut x = Cursor::new(Vec::new()); Test { x: 1, y: 2, z: 3 } - .write_options(&mut x, &WriteOptions::new(Endian::Big), ()) + .write_options(&mut x, Endian::Big, ()) .unwrap(); assert_eq!(x.into_inner(), [1, 0, 2, 0, 0, 0, 3]); @@ -79,10 +79,8 @@ fn round_trip_2() { let mut x = Cursor::new(Vec::new()); let mut y = Cursor::new(Vec::new()); - test.write_options(&mut x, &WriteOptions::new(Endian::Big), ()) - .unwrap(); - conj.write_options(&mut y, &WriteOptions::new(Endian::Big), ()) - .unwrap(); + test.write_options(&mut x, Endian::Big, ()).unwrap(); + conj.write_options(&mut y, Endian::Big, ()).unwrap(); assert_eq!(x.into_inner() == bytes, y.into_inner() == bytes_conj); } diff --git a/binrw_derive/src/codegen/meta.rs b/binrw_derive/src/codegen/meta.rs index 6382bfec..e254e9c0 100644 --- a/binrw_derive/src/codegen/meta.rs +++ b/binrw_derive/src/codegen/meta.rs @@ -1,7 +1,7 @@ use super::sanitization::{READ_ENDIAN, READ_MAGIC, WRITE_ENDIAN, WRITE_MAGIC}; use crate::{ codegen::sanitization::META_ENDIAN_KIND, - parser::{Input, Map}, + parser::{CondEndian, Input, Map}, }; use proc_macro2::TokenStream; use quote::quote; @@ -28,7 +28,7 @@ pub(crate) fn generate( let endian_meta = if WRITE { WRITE_ENDIAN } else { READ_ENDIAN }; let endian = match input.endian() { - crate::parser::CondEndian::Inherited => match input.map() { + CondEndian::Inherited => match input.map() { Map::None => input.is_empty().then(|| { quote! { #META_ENDIAN_KIND::None @@ -41,10 +41,10 @@ pub(crate) fn generate( quote! { <(#repr) as #endian_meta>::ENDIAN } }), }, - crate::parser::CondEndian::Fixed(endian) => Some(quote! { + CondEndian::Fixed(endian) => Some(quote! { #META_ENDIAN_KIND::Endian(#endian) }), - crate::parser::CondEndian::Cond(..) => Some(quote! { + CondEndian::Cond(..) => Some(quote! { #META_ENDIAN_KIND::Runtime }), } diff --git a/binrw_derive/src/codegen/mod.rs b/binrw_derive/src/codegen/mod.rs index ae690ef8..af0e1955 100644 --- a/binrw_derive/src/codegen/mod.rs +++ b/binrw_derive/src/codegen/mod.rs @@ -4,15 +4,17 @@ pub(crate) mod sanitization; mod write_options; use crate::{ - codegen::sanitization::{ARGS_MACRO, ASSERT, ASSERT_ERROR_FN, POS}, + codegen::sanitization::{ARGS_MACRO, ASSERT, ASSERT_ERROR_FN, ENDIAN_ENUM, POS}, named_args::{arg_type_name, derive_from_imports}, - parser::{Assert, AssertionError, Imports, Input, ParseResult, PassedArgs, StructField}, + parser::{ + Assert, AssertionError, CondEndian, Imports, Input, ParseResult, PassedArgs, StructField, + }, }; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; use sanitization::{ - ARGS, BINREAD_TRAIT, BINWRITE_TRAIT, BIN_RESULT, OPT, READER, READ_OPTIONS, READ_TRAIT, - SEEK_TRAIT, WRITER, WRITE_OPTIONS, WRITE_TRAIT, + ARGS, BINREAD_TRAIT, BINWRITE_TRAIT, BIN_RESULT, OPT, READER, READ_TRAIT, SEEK_TRAIT, WRITER, + WRITE_TRAIT, }; use syn::{spanned::Spanned, DeriveInput, Ident}; @@ -76,7 +78,7 @@ fn generate_trait_impl( fn write_options( &self, #WRITER: &mut W, - #OPT: &#WRITE_OPTIONS, + #OPT: #ENDIAN_ENUM, #ARGS: Self::Args ) -> #BIN_RESULT<()> }, @@ -86,7 +88,7 @@ fn generate_trait_impl( BINREAD_TRAIT, quote! { fn read_options - (#READER: &mut R, #OPT: &#READ_OPTIONS, #ARGS: Self::Args) + (#READER: &mut R, #OPT: #ENDIAN_ENUM, #ARGS: Self::Args) -> #BIN_RESULT }, ) @@ -180,6 +182,23 @@ fn get_destructured_imports( } } +fn get_endian(endian: &CondEndian) -> TokenStream { + match endian { + CondEndian::Inherited => OPT.to_token_stream(), + CondEndian::Fixed(endian) => endian.to_token_stream(), + CondEndian::Cond(endian, condition) => { + let (true_cond, false_cond) = (endian, endian.flipped()); + quote! { + if (#condition) { + #true_cond + } else { + #false_cond + } + } + } + } +} + fn get_passed_args(field: &StructField) -> Option { let args = &field.args; match args { diff --git a/binrw_derive/src/codegen/read_options.rs b/binrw_derive/src/codegen/read_options.rs index fabf95c6..db4500ca 100644 --- a/binrw_derive/src/codegen/read_options.rs +++ b/binrw_derive/src/codegen/read_options.rs @@ -4,10 +4,13 @@ mod r#struct; use super::{get_assertions, get_destructured_imports}; use crate::{ - codegen::sanitization::{ - IdentStr, ARGS, ASSERT_MAGIC, BIN_ERROR, OPT, POS, READER, SEEK_FROM, SEEK_TRAIT, TEMP, + codegen::{ + get_endian, + sanitization::{ + IdentStr, ARGS, ASSERT_MAGIC, BIN_ERROR, OPT, POS, READER, SEEK_FROM, SEEK_TRAIT, + }, }, - parser::{CondEndian, Input, Magic, Map}, + parser::{Input, Magic, Map}, }; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; @@ -76,19 +79,13 @@ impl<'input> PreludeGenerator<'input> { self } - fn add_options(mut self) -> Self { - let options = ReadOptionsGenerator::new(OPT) - .endian(self.input.endian()) - .finish(); - - if !options.is_empty() { - let head = self.out; - self.out = quote! { - #head - #options - }; - } - + fn add_endian(mut self) -> Self { + let endian = get_endian(self.input.endian()); + let head = self.out; + self.out = quote! { + #head + let #OPT = #endian; + }; self } @@ -118,11 +115,11 @@ impl<'input> PreludeGenerator<'input> { } } -fn get_magic(magic: &Magic, options_var: &impl ToTokens) -> Option { +fn get_magic(magic: &Magic, endian_var: impl ToTokens) -> Option { magic.as_ref().map(|magic| { let magic = magic.deref_value(); quote! { - #ASSERT_MAGIC(#READER, #magic, #options_var)?; + #ASSERT_MAGIC(#READER, #magic, #endian_var)?; } }) } @@ -137,60 +134,3 @@ fn get_map_err(pos: IdentStr) -> TokenStream { }) } } - -struct ReadOptionsGenerator { - out: TokenStream, - options_var: TokenStream, -} - -impl ReadOptionsGenerator { - fn new(options_var: impl quote::ToTokens) -> Self { - Self { - out: TokenStream::new(), - options_var: options_var.into_token_stream(), - } - } - - fn endian(mut self, endian: &CondEndian) -> Self { - let endian = match endian { - CondEndian::Inherited => return self, - CondEndian::Fixed(endian) => endian.to_token_stream(), - CondEndian::Cond(endian, condition) => { - let (true_cond, false_cond) = (endian, endian.flipped()); - quote! { - if (#condition) { - #true_cond - } else { - #false_cond - } - } - } - }; - - let head = self.out; - self.out = quote! { - #head - let #TEMP = #TEMP.with_endian(#endian); - }; - - self - } - - fn finish(self) -> TokenStream { - let options_var = self.options_var; - if self.out.is_empty() { - quote! { - let #options_var = #OPT; - } - } else { - let setters = self.out; - quote! { - let #options_var = &{ - let mut #TEMP = *#OPT; - #setters - #TEMP - }; - } - } - } -} diff --git a/binrw_derive/src/codegen/read_options/enum.rs b/binrw_derive/src/codegen/read_options/enum.rs index 30879bc3..e97a7e98 100644 --- a/binrw_derive/src/codegen/read_options/enum.rs +++ b/binrw_derive/src/codegen/read_options/enum.rs @@ -25,7 +25,7 @@ pub(super) fn generate_unit_enum( ) -> TokenStream { let prelude = PreludeGenerator::new(input) .add_imports(name) - .add_options() + .add_endian() .add_magic_pre_assertion() .finish(); @@ -177,7 +177,7 @@ pub(super) fn generate_data_enum(input: &Input, name: Option<&Ident>, en: &Enum) let prelude = PreludeGenerator::new(input) .add_imports(name) - .add_options() + .add_endian() .add_magic_pre_assertion() .reset_position_after_magic() .finish(); diff --git a/binrw_derive/src/codegen/read_options/map.rs b/binrw_derive/src/codegen/read_options/map.rs index 50ded844..45e2004e 100644 --- a/binrw_derive/src/codegen/read_options/map.rs +++ b/binrw_derive/src/codegen/read_options/map.rs @@ -13,7 +13,7 @@ use syn::Ident; pub(crate) fn generate_map(input: &Input, name: Option<&Ident>, map: &TokenStream) -> TokenStream { let prelude = PreludeGenerator::new(input) .add_imports(name) - .add_options() + .add_endian() .add_magic_pre_assertion() .finish(); @@ -49,7 +49,7 @@ pub(crate) fn generate_try_map( let map_err = get_map_err(POS); let prelude = PreludeGenerator::new(input) .add_imports(name) - .add_options() + .add_endian() .add_magic_pre_assertion() .finish(); diff --git a/binrw_derive/src/codegen/read_options/struct.rs b/binrw_derive/src/codegen/read_options/struct.rs index c758bce4..cc2e8298 100644 --- a/binrw_derive/src/codegen/read_options/struct.rs +++ b/binrw_derive/src/codegen/read_options/struct.rs @@ -1,13 +1,14 @@ -use super::{get_magic, PreludeGenerator, ReadOptionsGenerator}; +use super::{get_magic, PreludeGenerator}; #[cfg(feature = "verbose-backtrace")] use crate::backtrace::BacktraceFrame; use crate::{ codegen::{ - get_assertions, get_passed_args, + get_assertions, get_endian, get_passed_args, sanitization::{ make_ident, IdentStr, AFTER_PARSE, ARGS_MACRO, ARGS_TYPE_HINT, BACKTRACE_FRAME, - BINREAD_TRAIT, COERCE_FN, MAP_ARGS_TYPE_HINT, POS, READER, READ_FUNCTION, READ_METHOD, - REQUIRED_ARG_TRAIT, SAVED_POSITION, SEEK_FROM, SEEK_TRAIT, TEMP, WITH_CONTEXT, + BINREAD_TRAIT, COERCE_FN, MAP_ARGS_TYPE_HINT, OPT, POS, READER, READ_FUNCTION, + READ_METHOD, REQUIRED_ARG_TRAIT, SAVED_POSITION, SEEK_FROM, SEEK_TRAIT, TEMP, + WITH_CONTEXT, }, }, parser::{ErrContext, FieldMode, Input, Map, Struct, StructField}, @@ -113,10 +114,10 @@ impl<'input> StructGenerator<'input> { fn generate_after_parse(field: &StructField) -> Option { if field.deref_now.is_none() { get_after_parse_handler(field).map(|after_parse_fn| { - let (args_var, options_var) = make_field_vars(field); + let (args_var, endian_var) = make_field_vars(field); AfterParseCallGenerator::new(field) .get_value_from_ident() - .call_after_parse(after_parse_fn, &options_var, &args_var) + .call_after_parse(after_parse_fn, &endian_var, &args_var) .finish() }) } else { @@ -167,14 +168,10 @@ impl<'field> AfterParseCallGenerator<'field> { fn call_after_parse( mut self, after_parse_fn: IdentStr, - options_var: &Option, + endian_var: &TokenStream, args_var: &Option, ) -> Self { let value = self.out; - let options_var = options_var.as_ref().expect( - "called `AfterParseCallGenerator::call_after_parse` but no `options_var` was generated", - ); - let args_arg = if let Some(offset) = &self.field.offset_after { let offset = offset.as_ref(); if let Some(args_var) = args_var { @@ -193,7 +190,7 @@ impl<'field> AfterParseCallGenerator<'field> { }; self.out = quote! { - #after_parse_fn(#value, #READER, #options_var, #args_arg)?; + #after_parse_fn(#value, #READER, #endian_var, #args_arg)?; }; self @@ -221,18 +218,18 @@ struct FieldGenerator<'field> { field: &'field StructField, out: TokenStream, args_var: Option, - options_var: Option, + endian_var: TokenStream, } impl<'field> FieldGenerator<'field> { fn new(field: &'field StructField) -> Self { - let (args_var, options_var) = make_field_vars(field); + let (args_var, endian_var) = make_field_vars(field); Self { field, out: TokenStream::new(), args_var, - options_var, + endian_var, } } @@ -264,7 +261,7 @@ impl<'field> FieldGenerator<'field> { if let Some(after_parse) = get_after_parse_handler(self.field) { let after_parse = AfterParseCallGenerator::new(self.field) .get_value_from_temp() - .call_after_parse(after_parse, &self.options_var, &self.args_var) + .call_after_parse(after_parse, &self.endian_var, &self.args_var) .finish(); let value = self.out; @@ -384,17 +381,17 @@ impl<'field> FieldGenerator<'field> { } }); - let options = self.options_var.as_ref().map(|options_var| { - ReadOptionsGenerator::new(options_var) - .endian(&self.field.endian) - .finish() + let endian = self.field.needs_endian().then(|| { + let var = &self.endian_var; + let endian = get_endian(&self.field.endian); + quote! { let #var = #endian; } }); let tail = self.out; self.out = quote! { #args - #options + #endian #tail }; @@ -402,14 +399,12 @@ impl<'field> FieldGenerator<'field> { } fn prefix_magic(mut self) -> Self { - if let Some(options_var) = &self.options_var { - if let Some(magic) = get_magic(&self.field.magic, options_var) { - let tail = self.out; - self.out = quote! { - #magic - #tail - }; - } + if let Some(magic) = get_magic(&self.field.magic, &self.endian_var) { + let tail = self.out; + self.out = quote! { + #magic + #tail + }; } self @@ -421,10 +416,10 @@ impl<'field> FieldGenerator<'field> { FieldMode::Calc(calc) => quote! { #calc }, FieldMode::Normal | FieldMode::Function(_) => { let args_arg = get_args_argument(self.field, &self.args_var); - let options_var = &self.options_var; + let endian_var = &self.endian_var; quote! { - #READ_FUNCTION(#READER, #options_var, #args_arg) + #READ_FUNCTION(#READER, #endian_var, #args_arg) } } }; @@ -558,7 +553,7 @@ fn get_err_context( fn get_prelude(input: &Input, name: Option<&Ident>) -> TokenStream { PreludeGenerator::new(input) .add_imports(name) - .add_options() + .add_endian() .add_magic_pre_assertion() .finish() } @@ -613,20 +608,20 @@ fn get_return_type(variant_ident: Option<&Ident>) -> TokenStream { variant_ident.map_or_else(|| quote! { Self }, |ident| quote! { Self::#ident }) } -fn make_field_vars(field: &StructField) -> (Option, Option) { +fn make_field_vars(field: &StructField) -> (Option, TokenStream) { let args_var = if field.needs_args() { Some(make_ident(&field.ident, "args")) } else { None }; - let options_var = if field.needs_options() { - Some(make_ident(&field.ident, "options")) + let endian_var = if field.needs_endian() { + make_ident(&field.ident, "endian").into_token_stream() } else { - None + OPT.to_token_stream() }; - (args_var, options_var) + (args_var, endian_var) } fn map_align(align: &TokenStream) -> TokenStream { diff --git a/binrw_derive/src/codegen/sanitization.rs b/binrw_derive/src/codegen/sanitization.rs index 650708bb..21484e16 100644 --- a/binrw_derive/src/codegen/sanitization.rs +++ b/binrw_derive/src/codegen/sanitization.rs @@ -43,8 +43,6 @@ ident_str! { pub(crate) BINREAD_TRAIT = from_read_trait!(); pub(crate) BINWRITE_TRAIT = from_write_trait!(); pub(crate) BIN_ERROR = from_crate!(Error); - pub(crate) READ_OPTIONS = from_crate!(ReadOptions); - pub(crate) WRITE_OPTIONS = from_crate!(WriteOptions); pub(crate) READ_TRAIT = from_crate!(io::Read); pub(crate) WRITE_TRAIT = from_crate!(io::Write); pub(crate) SEEK_TRAIT = from_crate!(io::Seek); @@ -56,7 +54,7 @@ ident_str! { pub(crate) WRITE_METHOD = from_write_trait!(write_options); pub(crate) READER = "__binrw_generated_var_reader"; pub(crate) WRITER = "__binrw_generated_var_writer"; - pub(crate) OPT = "__binrw_generated_var_options"; + pub(crate) OPT = "__binrw_generated_var_endian"; pub(crate) ARGS = "__binrw_generated_var_arguments"; pub(crate) SAVED_POSITION = "__binrw_generated_saved_position"; pub(crate) ASSERT_MAGIC = from_crate!(__private::magic); diff --git a/binrw_derive/src/codegen/write_options/enum.rs b/binrw_derive/src/codegen/write_options/enum.rs index fded37fa..26ecdde1 100644 --- a/binrw_derive/src/codegen/write_options/enum.rs +++ b/binrw_derive/src/codegen/write_options/enum.rs @@ -69,7 +69,7 @@ impl<'a> EnumGenerator<'a> { #WRITE_METHOD ( &#magic, #WRITER, - &#OPT, + #OPT, () )?; } @@ -124,7 +124,7 @@ fn generate_unit_enum_repr(repr: &TokenStream, variants: &[UnitEnumField]) -> To #(#branches),* } as #repr), #WRITER, - &#OPT, + #OPT, (), )?; } @@ -140,7 +140,7 @@ fn generate_unit_enum_magic(variants: &[UnitEnumField]) -> TokenStream { #WRITE_METHOD ( &#magic, #WRITER, - &#OPT, + #OPT, (), )?; } diff --git a/binrw_derive/src/codegen/write_options/prelude.rs b/binrw_derive/src/codegen/write_options/prelude.rs index 96386baa..549beaa0 100644 --- a/binrw_derive/src/codegen/write_options/prelude.rs +++ b/binrw_derive/src/codegen/write_options/prelude.rs @@ -1,6 +1,6 @@ use crate::{ codegen::{ - get_destructured_imports, + get_destructured_imports, get_endian, sanitization::{ARGS, OPT, WRITER, WRITE_METHOD}, }, parser::{CondEndian, Input, Magic}, @@ -42,7 +42,7 @@ impl<'a> PreludeGenerator<'a> { #WRITE_METHOD ( &#magic, #WRITER, - &#OPT, + #OPT, () )?; @@ -54,26 +54,10 @@ impl<'a> PreludeGenerator<'a> { } pub(crate) fn prefix_endian(mut self, endian: &CondEndian) -> Self { + let endian = get_endian(endian); let out = self.out; - let set_endian = match endian { - CondEndian::Inherited => None, - CondEndian::Fixed(endian) => Some({ - quote! { - let #OPT = #OPT.clone().with_endian(#endian); - let #OPT = &#OPT; - } - }), - CondEndian::Cond(endian, cond) => Some({ - let else_endian = endian.flipped(); - quote! { - let #OPT = #OPT.clone().with_endian(if #cond { #endian } else { #else_endian }); - let #OPT = &#OPT; - } - }), - }; - self.out = quote! { - #set_endian + let #OPT = #endian; #out }; diff --git a/binrw_derive/src/codegen/write_options/struct_field.rs b/binrw_derive/src/codegen/write_options/struct_field.rs index 4ca7c9d7..f93010ea 100644 --- a/binrw_derive/src/codegen/write_options/struct_field.rs +++ b/binrw_derive/src/codegen/write_options/struct_field.rs @@ -1,15 +1,14 @@ use crate::{ codegen::{ - get_assertions, get_passed_args, + get_assertions, get_endian, get_passed_args, sanitization::{ - make_ident, BEFORE_POS, BINWRITE_TRAIT, OPT, SAVED_POSITION, SEEK_FROM, SEEK_TRAIT, - WRITER, WRITE_ARGS_TYPE_HINT, WRITE_FN_MAP_OUTPUT_TYPE_HINT, - WRITE_FN_TRY_MAP_OUTPUT_TYPE_HINT, WRITE_FN_TYPE_HINT, WRITE_FUNCTION, - WRITE_MAP_ARGS_TYPE_HINT, WRITE_MAP_INPUT_TYPE_HINT, WRITE_METHOD, - WRITE_TRY_MAP_ARGS_TYPE_HINT, WRITE_ZEROES, + make_ident, BEFORE_POS, BINWRITE_TRAIT, SAVED_POSITION, SEEK_FROM, SEEK_TRAIT, WRITER, + WRITE_ARGS_TYPE_HINT, WRITE_FN_MAP_OUTPUT_TYPE_HINT, WRITE_FN_TRY_MAP_OUTPUT_TYPE_HINT, + WRITE_FN_TYPE_HINT, WRITE_FUNCTION, WRITE_MAP_ARGS_TYPE_HINT, + WRITE_MAP_INPUT_TYPE_HINT, WRITE_METHOD, WRITE_TRY_MAP_ARGS_TYPE_HINT, WRITE_ZEROES, }, }, - parser::{CondEndian, FieldMode, Map, StructField}, + parser::{FieldMode, Map, StructField}, }; use core::ops::Not; use proc_macro2::TokenStream; @@ -108,7 +107,7 @@ impl<'a> StructFieldGenerator<'a> { fn write_field(mut self) -> Self { let name = &self.field.ident; let args = args_ident(name); - let options = specify_endian(&self.field.endian); + let endian = get_endian(&self.field.endian); let initialize = match &self.field.read_mode { FieldMode::Calc(expr) => Some({ @@ -156,7 +155,7 @@ impl<'a> StructFieldGenerator<'a> { #WRITE_FUNCTION ( { #store_position &(#map_fn (#name) #map_try) }, #WRITER, - &#OPT #options, + #endian, #args )?; }; @@ -249,13 +248,13 @@ impl<'a> StructFieldGenerator<'a> { fn prefix_magic(mut self) -> Self { if let Some(magic) = &self.field.magic { let magic = magic.match_value(); - let specify_endian = specify_endian(&self.field.endian); + let endian = get_endian(&self.field.endian); let out = self.out; self.out = quote! { #WRITE_METHOD ( &#magic, #WRITER, - &#OPT #specify_endian, + #endian, () )?; @@ -371,20 +370,3 @@ fn pad_before(field: &StructField) -> TokenStream { #pad_size_to_before } } - -fn specify_endian(endian: &CondEndian) -> Option { - match endian { - CondEndian::Inherited => None, - CondEndian::Fixed(endian) => Some({ - quote! { - .clone().with_endian(#endian) - } - }), - CondEndian::Cond(endian, cond) => Some({ - let else_endian = endian.flipped(); - quote! { - .clone().with_endian(if #cond { #endian } else { #else_endian }) - } - }), - } -} diff --git a/binrw_derive/src/parser/field_level_attrs.rs b/binrw_derive/src/parser/field_level_attrs.rs index 7c21c2ea..145e3733 100644 --- a/binrw_derive/src/parser/field_level_attrs.rs +++ b/binrw_derive/src/parser/field_level_attrs.rs @@ -91,16 +91,16 @@ impl StructField { !matches!(self.read_mode, FieldMode::Default) } - /// Returns true if the field needs `ReadOptions` to be parsed. - pub(crate) fn needs_options(&self) -> bool { - !self.generated_value() || self.magic.is_some() - } - /// Returns true if the field requires arguments. pub(crate) fn needs_args(&self) -> bool { self.args.is_some() || self.count.is_some() || self.offset.is_some() } + /// Returns true if the field overrides endianness. + pub(crate) fn needs_endian(&self) -> bool { + !matches!(self.endian, CondEndian::Inherited) + } + /// Returns true if the field is using shorthand directives that are /// converted into named arguments. pub(crate) fn has_named_arg_directives(&self) -> bool {