Skip to content
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

Is there a way to get the current index of a sub-parser in a vec in the parent parser? #363

Open
vext01 opened this issue Sep 29, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@vext01
Copy link
Contributor

vext01 commented Sep 29, 2023

Best explained by example:

struct Parent {
  num: usize,
  #[deku(count = "num")]
  subs: Vec<Sub>
}

struct Sub {
  idx: usize,
  ...
}

How can I get each Sub::idx to be set to the index of the Sub in Parent::subs?

Cheers

@vext01
Copy link
Contributor Author

vext01 commented Sep 29, 2023

I thought this may be possible with ctx, but it can only see previously parsed fields.

@wcampbell0x2a
Copy link
Collaborator

You could achieve it with a reader.

We could add a __deku variable that could be used.

@wcampbell0x2a wcampbell0x2a added the enhancement New feature or request label Sep 29, 2023
@vext01
Copy link
Contributor Author

vext01 commented Sep 29, 2023

How would I access the parent parser in a reader though?

@wcampbell0x2a
Copy link
Collaborator

wcampbell0x2a commented Sep 29, 2023

use deku::{
    bitvec::{BitSlice, Msb0},
    prelude::*,
};

#[derive(DekuRead, Debug, PartialEq, Eq)]
struct Parent {
    #[deku(bytes = "1")]
    num: usize,
    #[deku(reader = "Parent::read(deku::rest, *num)")]
    #[deku(count = "num")]
    subs: Vec<Sub>,
}

impl Parent {
    fn read(
        rest: &BitSlice<u8, Msb0>,
        count: usize,
    ) -> Result<(&BitSlice<u8, Msb0>, Vec<Sub>), DekuError> {
        let mut subs = Vec::with_capacity(count);
        let mut left_rest = rest;
        for n in 0..count {
            let (l_rest, mut sub) = Sub::read(left_rest, ())?;
            sub.idx = n;
            println!("{:?}", sub);
            subs.push(sub);
            left_rest = l_rest;
        }
        Ok((left_rest, subs))
    }
}

#[derive(DekuRead, Debug, PartialEq, Eq)]
struct Sub {
    #[deku(skip)]
    idx: usize,
    a: u8,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_00() {
        let bytes: &[u8] = &[0x02, 0x0f, 0xf0];
        let parent = Parent::try_from(bytes).unwrap();
        assert_eq!(
            parent,
            Parent {
                num: 2,
                subs: vec![Sub { idx: 0, a: 0x0f }, Sub { idx: 1, a: 0xf0 }]
            }
        )
    }
}

@vext01
Copy link
Contributor Author

vext01 commented Sep 29, 2023

Thanks. Right, so you have to manually parse the sub-struct.

It would indeed be useful to have some way to do it without that burden.

perhaps for a Vec field, you pass down some implicit context or similar?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants