Conversation
New helper is useful when parsing binary formats where collection size is represented in bytes and we don't know element count.
|
Hi, sorry for the delay in looking at this. This appears to be a redundant implementation of combining |
|
I wasn't aware that it's possible to combine #![allow(dead_code)]
use binrw::{
BinRead, BinReaderExt,
helpers::{count_bytes, until_eof},
io::Cursor,
io::TakeSeekExt,
};
fn main() {
#[derive(BinRead)]
#[br(big)]
pub struct XmrObject {
pub flags: u16,
pub type_: u16,
pub length: u32,
#[br(args { type_, length })]
pub data: XmrObjectInner,
}
#[derive(BinRead)]
#[br(big, import { type_: u16, length: u32 })]
pub enum XmrObjectInner {
#[br(pre_assert(type_ == 1))]
OuterContainer(#[br(args(length))] OuterContainer),
}
#[derive(BinRead)]
#[br(big, import(length: u32))]
pub struct OuterContainer {
// #[br(parse_with = count_bytes(u64::from(length - 8)))]
#[br(map_stream = |s| s.take_seek(u64::from(length - 8)), parse_with = until_eof)]
pub containers: Vec<XmrObject>,
}
let mut x = Cursor::new("");
let _: XmrObject = x.read_be().unwrap();
}Compiler throws: When I comment |
|
The problem here is that the structures in your example are recursive ( This loop can be broken by dynamic dispatch so trait ReadSeek: binrw::io::Read + binrw::io::Seek {}
impl<T> ReadSeek for T where T: binrw::io::Read + binrw::io::Seek {}
/* ... */
#[br(map_stream = |s| Box::new(s.take_seek(u64::from(length - 8))) as Box<dyn ReadSeek>, parse_with = until_eof)]The helper function in this PR avoids the infinite recursion by not changing the stream type. I am not confident on whether or not this is a good enough reason to have two different APIs to do the same thing. |
New helper is useful when parsing binary formats where collection size is represented in bytes and we don't know element count.
I used very similar approach while developing playready-rs.