Open axelkar opened 10 months ago
As an alternative a directive could be added to pad a whole struct, which in my example is Bar
.
Hi, sorry for the delay. pad_size_to
(or any field directive, really) only applies to a field itself, not to items within a collection. I can see how pad_size_to
on a struct might be useful. In the interim, you should be able to pass arbitrary
as an argument and then pad the last field, something like this (untested) code:
#[derive(BinRead)]
#[br(import(arbitrary: u8), little)]
// Is 7+ bytes but needs to get padded to `arbitrary`
pub struct Bar {
f1: u8,
f2: u16,
len: u32,
#[br(count = len, pad_after = u32::from(arbitrary) - len - 7)]
v: Vec<u8>
}
#[derive(BinRead)]
pub struct Foo {
arbitrary: u8,
len: u8,
#[br(args { count: len.into(), inner: (arbitrary,) })]
pub list: Vec<Bar>
}
I've been using this functionality recently too and I don't believe that it's a viable solution to expect developers to write reliable code by manually computing sizes of fields. My current workaround so far has been to create a padded wrapper:
#[derive(BinRead, Debug)]
struct TestList {
n: u8,
s: u8,
#[br(args { count: n as usize, inner: binrw::args!{ padding: s } })]
elements: Vec<Padded<Element>>,
}
#[derive(BinRead, Debug)]
#[br(little, import {
padding: u8,
})]
struct Padded<T>
where
T: BinRead<Args<'static> = ()> + std::fmt::Debug + Sized + Default,
{
#[br(pad_size_to = padding)]
inner: T,
}
and then add a Deref on top of that. Obviously this is not feature complete with correctly passing args through to inner members.
I spent a couple minutes making a draft of changes, hopefully someone with more insight can polish it up? https://github.com/jam1garner/binrw/compare/master...czaloj:struct_pad_size?expand=1
PTAL https://github.com/jam1garner/binrw/pull/250 @csnover @jam1garner
This doesn't currently work