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.
- [
bitfield
] - macro documentation. - [
examples
] - examples of the output generated by the [bitfield
] macro.
Note: the example module is only complied with documentation builds and is not available for importing in the wild.
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,
}
}
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());
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());
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());
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());
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());
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 |