#![cfg_attr(not(feature = "std"), no_std)]
#![warn(rust_2018_idioms)]
#[cfg(feature = "std")]
use std as alloc;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, string::String, vec::Vec};
#[doc(hidden)]
#[path = "private.rs"]
pub mod __private;
pub mod attribute;
pub mod endian;
pub mod error;
pub mod file_ptr;
pub mod helpers;
pub mod io;
#[doc(hidden)]
pub mod options;
#[doc(hidden)]
pub mod pos_value;
pub mod punctuated;
#[doc(hidden)]
pub mod strings;
#[cfg(feature = "std")]
#[cfg(feature = "debug_template")]
pub mod binary_template;
use core::any::{Any, TypeId};
#[doc(inline)]
pub use {
endian::Endian,
error::Error,
file_ptr::{FilePtr, FilePtr128, FilePtr16, FilePtr32, FilePtr64, FilePtr8},
helpers::{count, until, until_eof, until_exclusive},
options::ReadOptions,
pos_value::PosValue,
strings::{NullString, NullWideString},
};
use io::{Read, Seek, SeekFrom, StreamPosition};
pub use binread_derive::BinRead;
pub use binread_derive::derive_binread;
mod binread_impls;
pub use binread_impls::*;
pub type BinResult<T> = core::result::Result<T, Error>;
pub trait BinRead: Sized {
type Args: Any + Copy;
fn read<R: Read + Seek>(reader: &mut R) -> BinResult<Self> {
let args = match Self::args_default() {
Some(args) => args,
None => panic!("Must pass args, no args_default implemented"),
};
Self::read_options(reader, &ReadOptions::default(), args)
}
fn read_args<R: Read + Seek>(reader: &mut R, args: Self::Args) -> BinResult<Self> {
Self::read_options(reader, &ReadOptions::default(), args)
}
fn read_options<R: Read + Seek>(
reader: &mut R,
options: &ReadOptions,
args: Self::Args,
) -> BinResult<Self>;
fn after_parse<R: Read + Seek>(
&mut self,
_: &mut R,
_: &ReadOptions,
_: Self::Args,
) -> BinResult<()> {
Ok(())
}
fn args_default() -> Option<Self::Args> {
if TypeId::of::<Self::Args>() == TypeId::of::<()>() {
Some(unsafe { core::mem::MaybeUninit::uninit().assume_init() })
} else {
None
}
}
}
pub trait BinReaderExt: Read + Seek + Sized {
fn read_type<T: BinRead>(&mut self, endian: Endian) -> BinResult<T> {
let args = match T::args_default() {
Some(args) => args,
None => panic!("Must pass args, no args_default implemented"),
};
let options = ReadOptions {
endian,
..Default::default()
};
let mut res = T::read_options(self, &options, args)?;
res.after_parse(self, &options, args)?;
Ok(res)
}
fn read_be<T: BinRead>(&mut self) -> BinResult<T> {
self.read_type(Endian::Big)
}
fn read_le<T: BinRead>(&mut self) -> BinResult<T> {
self.read_type(Endian::Little)
}
fn read_ne<T: BinRead>(&mut self) -> BinResult<T> {
self.read_type(Endian::Native)
}
fn read_type_args<T: BinRead>(&mut self, endian: Endian, args: T::Args) -> BinResult<T> {
let options = ReadOptions {
endian,
..Default::default()
};
let mut res = T::read_options(self, &options, args.clone())?;
res.after_parse(self, &options, args)?;
Ok(res)
}
fn read_be_args<T: BinRead>(&mut self, args: T::Args) -> BinResult<T> {
self.read_type_args(Endian::Big, args)
}
fn read_le_args<T: BinRead>(&mut self, args: T::Args) -> BinResult<T> {
self.read_type_args(Endian::Little, args)
}
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 {}
pub mod prelude {
pub use crate::BinRead;
pub use crate::BinReaderExt;
pub use crate::BinResult;
}