sharksforarms / deku

Declarative binary reading and writing: bit-level, symmetric, serialization/deserialization
Apache License 2.0
1.05k stars 54 forks source link

Weird parsing with `bool` and non-aligned data. #417

Closed jwnhy closed 5 months ago

jwnhy commented 5 months ago

I have this struct

#[derive(Default, Debug, Clone, Copy, DekuRead, DekuWrite)]
pub struct Header {
    entry_type: u8,
    entry_size: u8,
    #[deku(bits="14")]
    __unused: u16,
    #[deku(bits="1")]
    optional: bool,
    #[deku(bits="1")]
    updatable: bool,
}

I expect that __unused only consumes 14 bits of the original data, but it consumes all 16 bits, leaving optional and updatable as 0.

Weird still, if change __unused to u8 and remove #[deku(bits=...)], all things automatically work.

wcampbell0x2a commented 5 months ago

I can't reproduce what you are describing:

use deku::prelude::*;

#[derive(Default, Debug, Clone, Copy, DekuRead, DekuWrite)]
pub struct Header {
    entry_type: u8,
    entry_size: u8,

    #[deku(bits = "14")]
    __unused: u16,

    #[deku(bits = "1")]
    optional: bool,

    #[deku(bits = "1")]
    updatable: bool,
}

fn main() {
    let bytes = [0xff, 0x00, 0b1111_1111, 0b1111_11_00];
    let d = Header::from_bytes((&bytes, 0)).unwrap();
    dbg_hex::dbg_hex!(d);
}
[src/main.rs:21:5] d = (
    (
        [],
        0x0,
    ),
    Header {
        entry_type: 0xff,
        entry_size: 0x0,
        __unused: 0x3fff,
        optional: true,
        updatable: true,
    },
)
jwnhy commented 5 months ago

The exact same code yields different results on my machine...

Mine is Gentoo, Intel 1260P...deku is 0.16.0

use deku::prelude::*;

#[derive(Default, Debug, Clone, Copy, DekuRead, DekuWrite)]
pub struct Header {
    entry_type: u8,
    entry_size: u8,

    #[deku(bits = "14")]
    __unused: u16,

    #[deku(bits = "1")]
    optional: bool,

    #[deku(bits = "1")]
    updatable: bool,
}

fn main() {
    let bytes = [0xff, 0x00, 0b1111_1111, 0b1111_11_00];
    let d = Header::from_bytes((&bytes, 0)).unwrap();
    println!("{:?}", d);
}

The results are

image
wcampbell0x2a commented 5 months ago

Oh that's totally my bad, I was messing around with the input to make sure my test was correct. I get:

[src/main.rs:21:5] d = (
    (
        [],
        0x0,
    ),
    Header {
        entry_type: 0xff,
        entry_size: 0x0,
        __unused: 0x3fff,
        optional: false,
        updatable: false,
    },
)

Which is expected.

jwnhy commented 5 months ago

You're right, after some digging, it turns out to be a bug in my own program.

Sorry about that. Thank you for your time...Closing.