Crate bondrewd_derive[][src]

Expand description

Fast and easy bitfield proc macro

Provides a proc macro for compressing a data structure with data which can be expressed with bit lengths that are not a power of Two.

Derive Generated Functions:

  • Conversion between a sized u8 array and the rust structure you define.
  • Peek and Set functions that allow the field to be accessed or overwritten within a sized u8 array.

For example we can define a data structure with 5 total bytes as:

  • a field named one will be the first 3 bits.
  • a field named two will be the next 19 bits.
  • a field named six will be the next 14 bits.
  • a field named four will be the next 4 bits.
// Users code
use bondrewd::*;
#[derive(Bitfields)]
#[bondrewd(default_endianness = "be")]
struct SimpleExample {
    #[bondrewd(bit_length = 3)]
    one: u8,
    #[bondrewd(bit_length = 19)]
    two: u32,
    #[bondrewd(bit_length = 14)]
    six: u16,
    #[bondrewd(bit_length = 4)]
    four: u8,
}
// Generated Code
impl Bitfields<5usize> for SimpleExample {
    const BIT_SIZE: usize = 40usize;
    fn into_bytes(self) -> [u8; 5usize] { .. }
    fn from_bytes([u8; 5usize]) -> Self { .. }
}
impl SimpleExample {
    pub fn peek_one(&[u8; 5usize]) -> u8 { .. }
    pub fn peek_two(&[u8; 5usize]) -> u32 { .. }
    pub fn peek_six(&[u8; 5usize]) -> u16 { .. }
    pub fn peek_four(&[u8; 5usize]) -> u8 { .. }
    pub fn set_one(&mut [u8; 5usize], u8) { .. }
    pub fn set_two(&mut [u8; 5usize], u32) { .. }
    pub fn set_six(&mut [u8; 5usize], u16) { .. }
    pub fn set_four(&mut [u8; 5usize], u8) { .. }
}

Supported Field Types

  • All primitives other than usize and isize (i believe ambiguous sizing is bad for this type of work).
  • Enums which implement the BitfieldEnum trait in bondrewd.
  • Structs which implement the Bitfield trait in bondrewd.

Struct Attributes

  • default_endianness = {"le" or "be"} describes a default endianness for primitive fields.
  • read_from = {"msb0" or "lsb0"} defines bit positioning. which end of the byte array to start at.
  • enforce_bytes = {BYTES} defines a required resulting BIT_SIZE divided by 8 of the structure in condensed form.
  • enforce_bits = {BYTES} defines a required resulting BIT_SIZE of the structure in condensed form.
  • enforce_full_bytes defines that the resulting BIT_SIZE is required to be a multiple of 8.
  • reverse defines that the entire byte array should be reversed before reading. no runtime cost.

Field Attributes

  • bit_length = {BITS} define the total amount of bits to use when condensed.
  • byte_length = {BYTES} define the total amount of bytes to use when condensed.
  • endianness = {"le" or "be"} define per field endianess.
  • block_bit_length = {BITS} describes a bit length for the entire array dropping lower indexes first. (default array type)
  • block_byte_length = {BYTES} describes a byte length for the entire array dropping lower indexes first. (default array type)
  • element_bit_length = {BITS} describes a bit length for each element of an array.
  • element_byte_length = {BYTES} describes a byte length for each element of an array.
  • enum_primitive = "u8" defines the size of the enum. the BitfieldEnum currently only supports u8.
  • struct_size = {SIZE} defines the field as a struct which implements the Bitfield trait and the BYTE_SIZE const defined in said trait.
  • reserve defines that this field should be ignored in from and into bytes functions.
  • /!Untested!\ bits = "RANGE" - define the bit indexes yourself rather than let the proc macro figure it out. using a rust range in quotes.

Crate Features:

  • slice_fns generates slice functions:
    • fn peek_slice_{field}(&[u8]) -> Result<{field_type}, BondrewdSliceError> {}
    • fn set_slice_{field}(&mut [u8], {field_type}) -> Result<(), BondrewdSliceError> {}
  • hex_fns provided from/into hex functions like from/into bytes. the hex inputs/outputs are [u8;N] where N is double the calculated bondrewd STRUCT_SIZE. hex encoding and decoding is based off the hex crate’s from/into slice functions but with statically sized arrays so we could eliminate sizing errors.

Full Example Generated code

use bondrewd::*;
struct SimpleFull {
    one: u8,
    two: u32,
    six: u16,
    four: u8,
}
impl Bitfields<5usize> for SimpleFull {
    const BIT_SIZE: usize = 40usize;
    fn into_bytes(self) -> [u8; 5usize] {
        let mut output_byte_buffer: [u8; 5usize] = [0u8; 5usize];
        output_byte_buffer[0usize] |= ((self.one as u8) << 5usize) & 224u8;
        let two_bytes = (self.two.rotate_left(2u32)).to_be_bytes();
        output_byte_buffer[0usize] |= two_bytes[1usize] & 31u8;
        output_byte_buffer[1usize] |= two_bytes[2usize];
        output_byte_buffer[2usize] |= two_bytes[3usize] & 252u8;
        let six_bytes = (self.six.rotate_right(4u32)).to_be_bytes();
        output_byte_buffer[2usize] |= six_bytes[0usize] & 3u8;
        output_byte_buffer[3usize] |= six_bytes[1usize];
        output_byte_buffer[4usize] |= six_bytes[0] & 240u8;
        output_byte_buffer[4usize] |= ((self.four as u8) << 0usize) & 15u8;
        output_byte_buffer
    }
    fn from_bytes(mut input_byte_buffer: [u8; 5usize]) -> Self {
        let one = Self::peek_one(&input_byte_buffer);
        let two = Self::peek_two(&input_byte_buffer);
        let six = Self::peek_six(&input_byte_buffer);
        let four = Self::peek_four(&input_byte_buffer);
        Self {
            one,
            two,
            six,
            four,
        }
    }
}
impl SimpleFull {
    #[inline]
    pub fn peek_one(input_byte_buffer: &[u8; 5usize]) -> u8 {
        ((input_byte_buffer[0usize] & 224u8) >> 5usize) as u8
    }
    #[inline]
    pub fn peek_two(input_byte_buffer: &[u8; 5usize]) -> u32 {
        u32::from_be_bytes({
            let mut two_bytes: [u8; 4usize] = [0u8; 4usize];
            two_bytes[1usize] = input_byte_buffer[0usize] & 31u8;
            two_bytes[2usize] |= input_byte_buffer[1usize];
            two_bytes[3usize] |= input_byte_buffer[2usize] & 252u8;
            two_bytes
        })
        .rotate_right(2u32)
    }
    #[inline]
    pub fn peek_six(input_byte_buffer: &[u8; 5usize]) -> u16 {
        u16::from_be_bytes({
            let mut six_bytes: [u8; 2usize] = [0u8; 2usize];
            six_bytes[0usize] = input_byte_buffer[2usize] & 3u8;
            six_bytes[1usize] |= input_byte_buffer[3usize];
            six_bytes[0] |= input_byte_buffer[4usize] & 240u8;
            six_bytes
        })
        .rotate_left(4u32)
    }
    #[inline]
    pub fn peek_four(input_byte_buffer: &[u8; 5usize]) -> u8 {
        ((input_byte_buffer[4usize] & 15u8) >> 0usize) as u8
    }
    #[inline]
    pub fn set_one(output_byte_buffer: &mut [u8; 5usize], one: u8) {
        output_byte_buffer[0usize] &= 31u8;
        output_byte_buffer[0usize] |= ((one as u8) << 5usize) & 224u8;
    }
    #[inline]
    pub fn set_two(output_byte_buffer: &mut [u8; 5usize], two: u32) {
        output_byte_buffer[0usize] &= 224u8;
        output_byte_buffer[2usize] &= 3u8;
        let two_bytes = (two.rotate_left(2u32)).to_be_bytes();
        output_byte_buffer[0usize] |= two_bytes[1usize] & 31u8;
        output_byte_buffer[1usize] |= two_bytes[2usize];
        output_byte_buffer[2usize] |= two_bytes[3usize] & 252u8;
    }
    #[inline]
    pub fn set_six(output_byte_buffer: &mut [u8; 5usize], six: u16) {
        output_byte_buffer[2usize] &= 252u8;
        output_byte_buffer[3usize] = 0u8;
        output_byte_buffer[4usize] &= 15u8;
        let six_bytes = (six.rotate_right(4u32)).to_be_bytes();
        output_byte_buffer[2usize] |= six_bytes[0usize] & 3u8;
        output_byte_buffer[3usize] |= six_bytes[1usize];
        output_byte_buffer[4usize] |= six_bytes[0] & 240u8;
    }
    #[inline]
    pub fn set_four(output_byte_buffer: &mut [u8; 5usize], four: u8) {
        output_byte_buffer[4usize] &= 240u8;
        output_byte_buffer[4usize] |= ((four as u8) << 0usize) & 15u8;
    }
}

Derive Macros

Generates an implementation of bondrewd::BitfieldEnum trait.

Generates an implementation of the bondrewd::Bitfield trait, as well as peek and set functions for direct sized u8 arrays access.