Hello. I do quite like this library but had a need for some more features, so I wrote a PR for them.
This PR adds attributes and traits to add static or dynamic headers and footers to a packed struct.
For static values a header and/or footer can be specified with the header and footer attributes. They will be added on pack and will be ignored on unpack. No validation is happening on unpack for either field.
If a more dynamic value is needed for either header or footer I've added two traits, PackedStructHeader and PackedStructFooter. They each provide the get_(header/footer) and validate_(header/footer) methods, which receive the already packed structure and can be used to generate values and to validate them. Currently the size of the header or footer must be specified with an attribute ((header/footer)_size = X) because I could not find a way to get the size of the return value in the derive macro. The validation method gets called before the rest of the struct gets unpacked. I added a PackingError::UserError to allow users to easily return possible validation errors
#[derive(PackedStruct, Debug, Clone, PartialEq)]
#[packed_struct(bit_numbering = "msb0", endian = "msb", footer_size = 1)]
pub struct DynamicCommand {
[...]
}
impl PackedStructFooter for DynamicCommand {
type FooterByteArray = [u8; 1];
fn get_footer(&self, data: &[u8]) -> packed_struct::PackingResult<Self::FooterByteArray> {
let mut xor: u8 = 0;
data.into_iter().for_each(|value| xor ^= value);
Ok([xor])
}
fn validate_footer(src: &[u8]) -> packed_struct::PackingResult<()> {
let mut xor: u8 = 0;
// We don't want to xor the xor value at the end
src[0..src.len()].into_iter().for_each(|value| xor ^= value);
if src.ends_with(&[xor]) {
Ok(())
} else {
Err(PackingError::UserError(format!("Invalid xor: {} to {:?}", xor, src.last().unwrap())))
}
}
}
I've also added tests/examples for the above. I'm currently also looking into allowing enums with structs inside to work with packed_struct as well by using PackedStructHeader but if I do this it'll be part of a separate PR
Hello. I do quite like this library but had a need for some more features, so I wrote a PR for them. This PR adds attributes and traits to add static or dynamic headers and footers to a packed struct.
For static values a header and/or footer can be specified with the
header
andfooter
attributes. They will be added on pack and will be ignored on unpack. No validation is happening on unpack for either field.This fixes https://github.com/hashmismatch/packed_struct.rs/issues/91
If a more dynamic value is needed for either header or footer I've added two traits,
PackedStructHeader
andPackedStructFooter
. They each provide theget_(header/footer)
andvalidate_(header/footer)
methods, which receive the already packed structure and can be used to generate values and to validate them. Currently the size of the header or footer must be specified with an attribute ((header/footer)_size = X
) because I could not find a way to get the size of the return value in the derive macro. The validation method gets called before the rest of the struct gets unpacked. I added aPackingError::UserError
to allow users to easily return possible validation errorsI've also added tests/examples for the above. I'm currently also looking into allowing enums with structs inside to work with packed_struct as well by using
PackedStructHeader
but if I do this it'll be part of a separate PR