jam1garner / jam1garner/binread
Terminate/TakeUntil attribute for dynamically sized vecs
- Dominant language
- Rust
- Stars
- 267
- Forks
- 17
- PR merge metrics
- No merged PRs in 30d
Description
In the binary formats i'm parsing, there are `Vec`s that don't have an explicit length stored in the file with them.
One common method of storing such `Vec`s is by parsing till a sentinel value is encountered. such as a `nullptr` or `-1`
So far I've been using a custom parser, and that works well, until you need custom `Args` or your field is a `Vec` wrapped up in something like a `FilePtr`
```rust
fn terminate(reader: &mut R, ro: &ReadOptions, args: (F,)) -> BinResult>
where
R: Read + Seek,
BR: BinRead,
F: FnMut(&BR) -> bool,
{
let mut vec = vec![];
let mut f = args.0;
let args = ();
loop {
let mut br = BR::read_options(reader, ro, args)?;
if f(&br) {
break;
}
br.after_parse(reader, ro, args)?;
vec.push(br);
}
Ok(vec)
}
```
Keep note that the condition is checked before `BinRead::after_parse` to allow you to check for `nullptr`s and the such. As doing them after would cause errors if the offset isn't valid.
Here's an example of my custom parser in use
```rust
#[derive(Debug, BinRead)]
struct OsageSiblingInfos {
#[br(parse_with=terminate, args(|x: &OsageSiblingInfo| x.bone_name.ptr == 0))]
infos: Vec,
}
#[derive(Debug, BinRead)]
struct OsageSiblingInfo {
bone_name: FilePtr32,
name: FilePtr32,
distance: f32,
}
```
I'm hoping the attribute could work something like
```rust
#[derive(Debug, BinRead)]
struct OsageSiblingInfos {
#[br(terminate=|x| x.bone_name.ptr == 0)]
infos: FilePtr32>,
}
#[derive(Debug, BinRead)]
struct OsageSiblingInfo {
bone_name: FilePtr32,
name: FilePtr32,
distance: f32,
}
```
Note how the closure argument is inferred instead of explicitly set in the previous example and how the field can be a `Vec` wrapped in something.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the custom `terminate` parser shown in the issue and the `BinRead::after_parse` behavior it relies on; then inspect how `FilePtr` wraps a `Vec`. Define tests covering sentinel checks before `after_parse`, custom arguments, and wrapped vectors; done means the attribute handles those cases with inferred closure arguments.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100