Expand description
Bit fields and masks for rust!
Provides a macro for generating bit field
types
complete with flags and some helpful trait implementations.
Supports field widths of 8
, 16
, 32
, 64
and 128
bits.
Note: the example module is only complied with documentation builds and is not available for importing in the wild.
Usage
Generate a bitfield struct with a flag enum… (The following examples all use this as a definition.)
use ubits::bitfield;
bitfield! {
pub u8 ExampleField
ExampleFlags {
0 : Flag0,
1 : Flag1,
2 : Flag2,
3 : Flag3,
4 : Flag4,
5 : Flag5,
6 : Flag6,
7 : Flag7,
}
}
Instances
From integer:
let from_integer = ExampleField(123);
assert_eq!(ExampleField(123), from_integer);
From a binary string:
let from_binary = ExampleField::from_binary_str("01111011");
assert_eq!(ExampleField(123), from_binary)
From ones:
let from_ones = ExampleField::ones();
assert_eq!("11111111", from_ones.as_binary());
assert_eq!(255, from_ones.as_integer());
From zeros:
let from_zeros = ExampleField::zeros();
assert_eq!("00000000", from_zeros.as_binary());
assert_eq!(0, from_zeros.as_integer());
Field Access
Get bit value by field:
let field = ExampleField::from_binary_str("01010101");
assert!(field.get(ExampleFlags::Flag0));
assert!(!field.get(ExampleFlags::Flag1));
Get bit value by index:
let field = ExampleField::from_binary_str("01010101");
assert!(field.get_index(0));
assert!(!field.get_index(1));
Set bit value by field:
let mut field = ExampleField::from_binary_str("01010101");
field.set(ExampleFlags::Flag1);
field.set(ExampleFlags::Flag3);
assert_eq!("01011111", field.as_binary());
Set bit value by index:
let mut field = ExampleField::from_binary_str("01010101");
field.set_index(1);
field.set_index(3);
assert_eq!("01011111", field.as_binary());
Clear bit value by field:
let mut field = ExampleField::from_binary_str("01010101");
field.clear(ExampleFlags::Flag0);
field.clear(ExampleFlags::Flag2);
assert_eq!("01010000", field.as_binary());
Clear bit value by index:
let mut field = ExampleField::from_binary_str("01010101");
field.clear_index(0);
field.clear_index(2);
assert_eq!("01010000", field.as_binary());
Toggle bit value by field:
let mut field = ExampleField::from_binary_str("01010101");
field.toggle(ExampleFlags::Flag0);
assert_eq!("01010100", field.as_binary());
field.toggle(ExampleFlags::Flag0);
assert_eq!("01010101", field.as_binary());
Toggle bit value by index:
let mut field = ExampleField::from_binary_str("01010101");
field.toggle_index(0);
assert_eq!("01010100", field.as_binary());
field.toggle_index(0);
assert_eq!("01010101", field.as_binary());
Named Getters and Setters
Ubits can generate getter and setter methods for zero or more fields, if a name is provided.
use ubits::bitfield;
bitfield! {
pub u8 ExampleField
ExampleFlags {
0 : Flag0 : (field_0), // is_field_0 & set_field_0 & clear_field_0 & toggle_field_0
1 : Flag1 : (field_1), // is_field_1 & set_field_1 & clear_field_1 & toggle_field_1
2 : Flag2,
3 : Flag3,
4 : Flag4,
5 : Flag5,
6 : Flag6,
7 : Flag7,
}
}
let mut field = ExampleField::from_binary_str("01010101");
assert_eq!(true, field.is_field_0());
assert_eq!(false, field.is_field_1());
field.set_field_1();
assert_eq!(true, field.is_field_1());
field.clear_field_1();
assert_eq!(false, field.is_field_1());
field.toggle_field_1();
assert_eq!(true, field.is_field_1());
Combinations
Combine bit fields:
(use into_combined
to consume self)
let mut a = ExampleField::from_binary_str("01010101");
let b = ExampleField::from_binary_str("10101010");
assert_eq!("11111111", a.combine(b).as_binary());
Get the intersection of two bitfields:
(use into_intersection
to consume self)
let mut a = ExampleField::from_binary_str("11000011");
let b = ExampleField::from_binary_str("01111110");
assert_eq!("01000010", a.intersect(b).as_binary());
Get the diff of two bitfields:
(use into_diff
to consume self)
let mut a = ExampleField::from_binary_str("11000011");
let b = ExampleField::from_binary_str("01100110");
assert_eq!("10100101", a.diff(b).as_binary());
Bitwise
Both bit field instances and flags use bitwise operators to change bit values.
let mut from_zeros = ExampleField::zeros();
assert_eq!("00000000", from_zeros.as_binary());
// set bit to 1
from_zeros |= ExampleFlags::Flag1;
assert_eq!("00000010", from_zeros.as_binary());
// set bit back to 0
from_zeros &= ExampleFlags::Flag1;
assert_eq!("00000000", from_zeros.as_binary());
// toggle a bit
from_zeros ^= ExampleFlags::Flag1;
assert_eq!("00000010", from_zeros.as_binary());
from_zeros ^= ExampleFlags::Flag1;
assert_eq!("00000000", from_zeros.as_binary());
Operations can also be chained together:
let mut from_zeros = ExampleField::zeros() | ExampleFlags::Flag1 | ExampleFlags::Flag3;
assert_eq!("00001010", from_zeros.as_binary());
Bitfield instances can also be created from combining flags:
let mut from_zeros = ExampleFlags::Flag1 | ExampleFlags::Flag3;
assert_eq!("00001010", from_zeros.as_binary());
Fields named with flags
The generated flags enum allows you to access bits by name.
The flag has an associated u8
value,
which determines the index its target bit.
(See bitfield
for more info)
With the following input…
1 0 1 0 0 1 1 0
and the following flags…
0 : f1
1 : f1
2 : f2
3 : f3
4 : f4
5 : f5
6 : f6
7 : f7
we end up with this layout.
name | f7 | f6 | f5 | f4 | f3 | f2 | f1 | f0 |
---|---|---|---|---|---|---|---|---|
bit value | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
With the same input and only the first few flags:
0 : f0
1 : f1
2 : f2
we end up with this layout.
name | f2 | f1 | f0 | |||||
---|---|---|---|---|---|---|---|---|
bit value | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Using the same input, but with dispersed flags:
1 : f0
3 : f1
6 : f2
we end up with this layout.
name | f2 | f1 | f0 | |||||
---|---|---|---|---|---|---|---|---|
bit value | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Modules
Examples of generated output using different configurations.
Macros
Generates a bitfield struct and a corresponding flag enum.