Macro u8bits::u8bits

source ·
macro_rules! u8bits {
    (@field $(#[$attr:meta])* $t:ty, $id:ident:
     w $byte:expr, $lsb:expr, $msb:expr;) => { ... };
    (@field $(#[$attr:meta])* $t:ty, $id:ident:
     r $byte:expr, $lsb:expr, $msb:expr;) => { ... };
    (@field $(#[$attr:meta])* $t:ty, $id:ident:
     rw $byte:expr, $lsb:expr, $msb:expr;) => { ... };
    (@field $(#[$attr:meta])* $id:ident: w $byte:expr, $bit:expr;) => { ... };
    (@field $(#[$attr:meta])* $id:ident: r $byte:expr, $bit:expr;) => { ... };
    (@field $(#[$attr:meta])* $id:ident: rw $byte:expr, $bit:expr;) => { ... };
    ( $(#[$attr:meta])* $t:ty, $id:ident: $f:ident $($expr:expr),+; $($rest:tt)*) => { ... };
    ( $(#[$attr:meta])* $id:ident: $f:ident $($expr:expr),+; $($rest:tt)*) => { ... };
    () => { ... };
}
Expand description

This macro allows the generaion of bit field like getters and setters for a New Type struct of type [u8;N]. There are bit wise accessors and bit range accessors. The bitwise operations map to an boolean value whereas the bit range operations use an provided type which has to implement the .into() conversion trait. The bit wise field declaration is as follows:

  • Optional attributes (#[...]), documentation comments (///) are attributes;
  • the identifier, which will be suffixed by ‘set_’ and / or ‘get_’
  • A colon
  • an ‘r’ or ‘w’ or ‘rw’ flag which indicates which accessor are created (read->get,write->set or both)
  • the byte number followed by a comma
  • the bit number

The bit range operations are as follows:

  • Optional attributes (#[...]), documentation comments (///) are attributes;
  • An type, which has to provide the core conversion Into trait, followed by a comma
  • the identifier, which will be suffixed by ‘set_’ and / or ‘get_’
  • A colon
  • an ‘r’ or ‘w’ or ‘rw’ flag which indicates which accessor are created (read->get,write->set or both)
  • the byte number followed by a comma
  • the lsb (least significant) bit number
  • the msb (most significant) bit number inclusive

So a typical declaration might look like:

use u8bits::u8bits;

struct Bytes( [u8;2]);
impl Bytes {
   u8bits! {
       /// foo is bit 4 of byte 0
       foo: rw 0,4;
       /// bar are bits 0..3 of byte 1
       u8, bar: rw 1,0,3;
   }
}
 

which will expand to:

struct Bytes([u8; 2]);
    impl Bytes {
        #[inline]
        #[doc = r" foo is bit 4 of byte 0"]
        pub fn get_foo(&self) -> bool { ::u8bits::get_bit(&self.0[0], 4) }
        #[inline]
        #[doc = r" foo is bit 4 of byte 0"]
        pub fn set_foo(&mut self, value: bool) {
            ::u8bits::set_bit(&mut self.0[0], 4, value)
        }
        #[inline]
        #[doc = r" bar are bits 0..3 of byte 1"]
        pub fn get_bar(&self) -> u8 {
            ::u8bits::get_bit_range(&self.0[1], 0, 3).into()
        }
        #[inline]
        #[doc = r" bar are bits 0..3 of byte 1"]
        pub fn set_bar(&mut self, value: u8) {
            ::u8bits::set_bit_range(&mut self.0[1], 0, 3, value.into())
        }
    }

For the use of bitfield like enums see for example the surjective-enum crate or the test of this crate.