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

Using types for struct fields #86

Open
T-Bakker opened this issue Feb 8, 2022 · 3 comments
Open

Using types for struct fields #86

T-Bakker opened this issue Feb 8, 2022 · 3 comments

Comments

@T-Bakker
Copy link

T-Bakker commented Feb 8, 2022

Hi,

I am trying to replace modular_bitfield with packet_struct as that library is no longer maintained. As such, I am trying to use packet_struct with a non-struct type as a field:

pub type Field = Integer<u8, packed_bits::Bits::<4>>;

#[derive(PackedStruct, Debug, Clone, Copy, PartialEq)]
pub struct S {
    pub a: Field,
    pub b: Field,
}

This results in the following error: Couldn't determine the bit/byte width for this field.

Please note that I use the Field type in various structs in my code. Removing that type and simply specifying Interger<...> for each usage is undesired. I can also not use struct nesting as the struct require a byte boundary, which is not possible for me.

Explicitly specifying the bit positions results in a different error which I do not fully understand:

pub type Field = Integer<u8, packed_bits::Bits::<4>>;

#[derive(PackedStruct, Debug, Clone, Copy, PartialEq)]
#[packed_struct(bit_numbering="msb0")]
pub struct S {
    #[packed_field(bits="0..=3")]
    pub a: Field,
    #[packed_field(bits="4..=7")]
    pub b: Field,
}

Error: no function or associated item named unpack found for struct packed_struct::types::Integer<u8, Bits<4_usize>> in the current scope
function or associated item not found in `packed_struct::types::Integer<u8, Bits<4_usize>>

Am I missing something? Is this possible somehow?

Thanks in advance,
Tommas

@rudib
Copy link
Member

rudib commented Feb 9, 2022

Hi,

Unfortunately, type aliases are not supported in this way. A derive macro in Rust receives only the source of the particular struct, with no way to inspect the previously defined alias. It might be possible to support this exact scenario by implementing the packing traits on the Integer<> wrappers, but for now, this isn't supported. The definitions would also need to be even more explicit, as there is also a semi-hidden MSB/LSB wrapper around them.

However, if you want, you can define a structure just for this case, but then you need to give a hint what is the exact width of each individual field. A Deref implementation on the helper struct will also help with the ergonomics. I've written a small test and this seems to work fine for me. Not sure what you meant by byte boundary, but structures can be placed on a per bit level.

use packed_struct::prelude::*;

#[derive(PackedStruct, Debug, Clone, Copy, PartialEq, Default)]
#[packed_struct(bit_numbering="msb0")]
pub struct FieldStruct {
    #[packed_field(bits="4..")]
    pub data: Integer<u8, packed_bits::Bits::<4>>
}

#[derive(PackedStruct, Debug, Clone, Copy, PartialEq, Default)]
#[packed_struct(bit_numbering="msb0")]
pub struct S {
    #[packed_field(bits="0..4")]
    pub a: FieldStruct,
    #[packed_field(size_bits="4")]
    pub b: FieldStruct
}

#[test]
#[cfg(test)]
fn test_packed_type_alias() {
    let mut s = S::default();
    s.a.data = 0b1001.into();
    s.b.data = 0b0110.into();

    println!("data: {:#?}", s);
    let packed = s.pack().unwrap();
    println!("packed: {:#X?}", packed);

    let u = S::unpack(&packed).unwrap();
    assert_eq!(s, u);
}

@rudib
Copy link
Member

rudib commented Feb 9, 2022

This actually compiles:

pub type Field = MsbInteger<u8, packed_bits::Bits::<4>, Integer<u8, packed_bits::Bits::<4>>>;

#[derive(PackedStruct)]
#[packed_struct(bit_numbering="msb0")]
pub struct S {
    #[packed_field(bits="0..", size_bits="4")]
    pub a: Field,
    #[packed_field(size_bits="4")]
    pub b: Field
}

However those types were never designed to be used this way, so there are a couple of conversion traits that would have to be implemented to make things usable. Also, it's missing the critical traits like Copy/Clone/PartialEq/etc... So a valid feature request, but I'd have to dig a bit deeper how this interacts with the generated code.

@cujomalainey
Copy link

Would appreciate this implementation, i have a downstream upstream (code flow) of packed types and I rather they pass in the proper type size than cross my fingers im not truncating types

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

No branches or pull requests

3 participants