1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
use crate::{
io::{Read, Seek},
BinResult, Endian,
};
mod options;
pub use options::*;
mod impls;
pub use impls::VecArgs;
/// The `BinRead` trait reads data from streams and converts it into objects.
///
/// [`io`]: crate::io
///
/// This trait is usually derived, but can also be manually implemented by
/// writing an appropriate [`Args`] type and [`read_options()`] function.
///
/// [`Args`]: Self::Args
/// [`read_options()`]: Self::read_options
///
/// # Derivable
///
/// This trait can be used with `#[derive]` or `#[derive_binread]`. Each field
/// of a derived type must either implement `BinRead` or be annotated with an
/// attribute containing a [`map`], [`try_map`], or [`parse_with`] directive.
///
/// [`map`]: crate::attribute#map
/// [`parse_with`]: crate::attribute#parse_with
/// [`try_map`]: crate::attribute#map
///
/// Using `#[derive_binread]` instead of `#[derive]` is required when using
/// [temporary fields].
///
/// [temporary fields]: crate::attribute#temp
pub trait BinRead: Sized + 'static {
/// The type used for the `args` parameter of [`read_args()`] and
/// [`read_options()`].
///
/// When the given type implements [`Default`], convenience functions like
/// [`read()`] are enabled. `BinRead` implementations that don’t receive any
/// arguments should use the `()` type.
///
/// When `BinRead` is derived, the [`import`] and [`import_tuple`]
/// directives define this type.
///
/// [`import`]: crate::attribute#arguments
/// [`import_tuple`]: crate::attribute#arguments
/// [`read()`]: Self::read
/// [`read_args()`]: Self::read_args
/// [`read_options()`]: Self::read_options
type Args: Clone;
/// Read `Self` from the reader using default arguments.
fn read<R: Read + Seek>(reader: &mut R) -> BinResult<Self>
where
Self::Args: Default,
{
Self::read_options(reader, &ReadOptions::default(), Self::Args::default())
}
/// Read `Self` from the reader using the given arguments.
fn read_args<R: Read + Seek>(reader: &mut R, args: Self::Args) -> BinResult<Self> {
Self::read_options(reader, &ReadOptions::default(), args)
}
/// Read `Self` from the reader using the given [`ReadOptions`] and
/// arguments.
fn read_options<R: Read + Seek>(
reader: &mut R,
options: &ReadOptions,
args: Self::Args,
) -> BinResult<Self>;
/// Runs any post-processing steps required to finalize construction of the
/// object.
fn after_parse<R: Read + Seek>(
&mut self,
_: &mut R,
_: &ReadOptions,
_: Self::Args,
) -> BinResult<()> {
Ok(())
}
}
/// Extension methods for reading [`BinRead`] objects directly from a reader.
///
/// # Examples
///
/// ```rust
/// use binrw::BinReaderExt;
/// use binrw::endian::LE;
/// use binrw::io::Cursor;
///
/// let mut reader = Cursor::new(b"\x07\0\0\0\xCC\0\0\x05");
/// let x: u32 = reader.read_le().unwrap();
/// let y: u16 = reader.read_type(LE).unwrap();
/// let z = reader.read_be::<u16>().unwrap();
///
/// assert_eq!((x, y, z), (7u32, 0xCCu16, 5u16));
/// ```
pub trait BinReaderExt: Read + Seek + Sized {
/// Read `T` from the reader with the given byte order.
fn read_type<T: BinRead>(&mut self, endian: Endian) -> BinResult<T>
where
T::Args: Default,
{
self.read_type_args(endian, T::Args::default())
}
/// Read `T` from the reader assuming big-endian byte order.
fn read_be<T: BinRead>(&mut self) -> BinResult<T>
where
T::Args: Default,
{
self.read_type(Endian::Big)
}
/// Read `T` from the reader assuming little-endian byte order.
fn read_le<T: BinRead>(&mut self) -> BinResult<T>
where
T::Args: Default,
{
self.read_type(Endian::Little)
}
/// Read `T` from the reader assuming native-endian byte order.
fn read_ne<T: BinRead>(&mut self) -> BinResult<T>
where
T::Args: Default,
{
self.read_type(Endian::Native)
}
/// Read `T` from the reader with the given byte order and arguments.
fn read_type_args<T: BinRead>(&mut self, endian: Endian, args: T::Args) -> BinResult<T> {
let options = ReadOptions::default().with_endian(endian);
let mut res = T::read_options(self, &options, args.clone())?;
res.after_parse(self, &options, args)?;
Ok(res)
}
/// Read `T` from the reader, assuming big-endian byte order, using the
/// given arguments.
fn read_be_args<T: BinRead>(&mut self, args: T::Args) -> BinResult<T> {
self.read_type_args(Endian::Big, args)
}
/// Read `T` from the reader, assuming little-endian byte order, using the
/// given arguments.
fn read_le_args<T: BinRead>(&mut self, args: T::Args) -> BinResult<T> {
self.read_type_args(Endian::Little, args)
}
/// Read `T` from the reader, assuming native-endian byte order, using the
/// given arguments.
fn read_ne_args<T: BinRead>(&mut self, args: T::Args) -> BinResult<T> {
self.read_type_args(Endian::Native, args)
}
}
impl<R: Read + Seek + Sized> BinReaderExt for R {}