use crate::{
io::{ErrorKind::UnexpectedEof, Read, Seek},
BinRead, BinReaderExt, BinResult, ReadOptions,
};
#[cfg(not(feature = "std"))]
use alloc::{vec, vec::Vec};
pub fn read_bytes<R: Read + Seek>(
reader: &mut R,
options: &ReadOptions,
_: (),
) -> BinResult<Vec<u8>> {
let count = match options.count {
Some(x) => x,
None => panic!("Missing count for read_bytes"),
};
let mut buf = vec![0; count];
reader.read_exact(&mut buf)?;
Ok(buf)
}
pub fn until<Reader, T, CondFn, Arg, Ret>(
cond: CondFn,
) -> impl Fn(&mut Reader, &ReadOptions, Arg) -> BinResult<Ret>
where
T: BinRead<Args = Arg>,
Reader: Read + Seek,
CondFn: Fn(&T) -> bool,
Arg: Clone,
Ret: core::iter::FromIterator<T>,
{
move |reader, ro, args| {
let mut result = Vec::new();
let mut last = reader.read_type_args(ro.endian, args.clone())?;
while !cond(&last) {
result.push(last);
last = reader.read_type_args(ro.endian, args.clone())?;
}
result.push(last);
Ok(result.into_iter().collect())
}
}
pub fn until_exclusive<Reader, T, CondFn, Arg, Ret>(
cond: CondFn,
) -> impl Fn(&mut Reader, &ReadOptions, Arg) -> BinResult<Ret>
where
T: BinRead<Args = Arg>,
Reader: Read + Seek,
CondFn: Fn(&T) -> bool,
Arg: Clone,
Ret: core::iter::FromIterator<T>,
{
move |reader, ro, args| {
let mut result = Vec::new();
let mut last = reader.read_type_args(ro.endian, args.clone())?;
while !cond(&last) {
result.push(last);
last = reader.read_type_args(ro.endian, args.clone())?;
}
Ok(result.into_iter().collect())
}
}
pub fn until_eof<R, T, Arg, Ret>(reader: &mut R, ro: &ReadOptions, args: Arg) -> BinResult<Ret>
where
T: BinRead<Args = Arg>,
R: Read + Seek,
Arg: Clone,
Ret: core::iter::FromIterator<T>,
{
let mut result = Vec::new();
let mut last = reader.read_type_args(ro.endian, args.clone());
while !matches!(&last, Err(crate::Error::Io(err)) if err.kind() == UnexpectedEof) {
last = match last {
Ok(x) => {
result.push(x);
reader.read_type_args(ro.endian, args.clone())
}
Err(err) => return Err(err),
}
}
Ok(result.into_iter().collect())
}
pub fn count<R, T, Arg, Ret>(n: usize) -> impl Fn(&mut R, &ReadOptions, Arg) -> BinResult<Ret>
where
T: BinRead<Args = Arg>,
R: Read + Seek,
Arg: Clone,
Ret: core::iter::FromIterator<T>,
{
move |reader, ro, args| {
(0..n)
.map(|_| reader.read_type_args(ro.endian, args.clone()))
.collect()
}
}