-
-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add read_all attribute #387
Conversation
Benchmark for 2bdf2beClick to view benchmark
|
Looks great! Thanks for your work. |
deku-derive/src/lib.rs
Outdated
{ | ||
return Err(cerror( | ||
data.bits.span(), | ||
"conflicting: `read_all` cannot be used with `count`, `bits_read`, or `bytes_read`", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should until
be included here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. pushed to reflect changes.
Add read_all attribute to read until the reader.end() returns true Fix couple of doc bugs
45ba3d9
to
c288e8a
Compare
Benchmark for 999f4fcClick to view benchmark
|
{ | ||
return Err(cerror( | ||
data.bits.span(), | ||
"conflicting: `read_all` cannot be used with `until`, count`, `bits_read`, or `bytes_read`", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"conflicting: `read_all` cannot be used with `until`, count`, `bits_read`, or `bytes_read`", | |
"conflicting: `read_all` cannot be used with `until`, `count`, `bits_read`, or `bytes_read`", |
Sometimes it's useful to have both #[derive(Debug)]
struct VecTilEnd<T>(Vec<T>);
impl<'a, T, Ctx, Predicate> DekuReader<'a, (deku::ctx::Limit<T, Predicate>, Ctx)> for VecTilEnd<T>
where
T: DekuReader<'a, Ctx>,
Ctx: Copy,
Predicate: FnMut(&T) -> bool,
{
fn from_reader_with_ctx<R: std::io::Read>(
reader: &mut deku::reader::Reader<R>,
(limit, inner_ctx): (deku::ctx::Limit<T, Predicate>, Ctx),
) -> Result<Self, DekuError>
where
Self: Sized,
{
let deku::ctx::Limit::Until(mut predicate, _) = limit else {
return Err(DekuError::Parse("`until` is required here".to_string()));
};
let mut res = Vec::new();
let start_read = reader.bits_read;
loop {
if reader.end() {
break;
}
let val = <T>::from_reader_with_ctx(reader, inner_ctx)?;
res.push(val);
if predicate(res.last().unwrap()) {
break;
}
}
Ok(Self(res))
}
}
#[derive(Debug, DekuRead)]
struct MaybeProperty {
#[deku(until = "|b: &u8| *b != b'\\n'")]
ws: VecTilEnd<u8>,
#[deku(cond = "ws.0.last().map_or(false, |c| c != &b'[')")]
property: Option<Property>,
} (For this very silly thing: https://gist.github.com/passcod/9148782657f3f40df75ff85b8dd77c2a) |
@passcod could you clarify your use case with some examples? Trying to understand what you're trying to achieve. I attempted something here, but I didn't need #[derive(Debug, PartialEq, Eq, DekuRead)]
struct MaybePropertyVecTilEnd {
#[deku(until = "|b: &u8| *b != b'\\n'")]
ws: VecTilEnd<u8>,
field: u8,
}
#[derive(Debug, PartialEq, Eq, DekuRead)]
struct MaybePropertyVec {
#[deku(until = "|b: &u8| *b != b'\\n'")]
ws: Vec<u8>,
field: u8,
}
fn main() {
{
let mut input = Cursor::new(b"\n\n\n[a");
let (_, prop) = MaybePropertyVecTilEnd::from_reader((&mut input, 0)).unwrap();
assert_eq!(
prop,
MaybePropertyVecTilEnd {
ws: VecTilEnd(b"\n\n\n[".to_vec()),
field: 0x61,
}
);
}
{
let mut input = Cursor::new(b"\n\n\n[a");
let (_b, prop) = MaybePropertyVec::from_reader((&mut input, 0)).unwrap();
assert_eq!(
prop,
MaybePropertyVec {
ws: b"\n\n\n[".to_vec(), // same as VecTilEnd?
field: 0x61,
}
);
}
} |
I've added the input file to the gist. The way I reasoned about it is that I needed to read [Section]
Key=value
For example this is: "\n[Section]\nKey=value\n" and so I read (in the full example in gist):
With
Now, deku isn't really adapted for this particular usecase, but it does seem like "read until either EOF or a delimiter" would be useful in general. |
handy, thank you - works for me. |
@wcampbell0x2a what do you think of the above? Could be neat to have an indicator of "eof" which could be used in attributes such as: #[deku(until = "|v: &u8| *v == 0 || deku::eof")]
data: Vec<u8> I'm ok with adding a |
I was thinking about this and I'm not sure (out of ignorance; haven't looked) if it would work with deku internals, but something like
that would 'peek' at the next byte/bit/item (where |
How would this convert into a |
@sharksforarms I added a |
Add read_all attribute to read until the reader.end() returns true
Fix couple of doc bugs
Closes #230