ubits

crates.io Downloads Build Docs Licence

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.) ```rust 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: ```rust

let frominteger = ExampleField(123); asserteq!(ExampleField(123), from_integer); ```

From a binary string: ```rust

let frombinary = ExampleField::frombinarystr("01111011"); asserteq!(ExampleField(123), from_binary) ```

From ones: ```rust

let fromones = ExampleField::ones(); asserteq!("11111111", fromones.asbinary()); asserteq!(255, fromones.as_integer()); ```

From zeros: ```rust

let fromzeros = ExampleField::zeros(); asserteq!("00000000", fromzeros.asbinary()); asserteq!(0, fromzeros.as_integer()); ```

Field Access

Get bit value by field: ```rust

let field = ExampleField::frombinarystr("01010101"); assert!(field.get(ExampleFlags::Flag0)); assert!(!field.get(ExampleFlags::Flag1)); ```

Get bit value by index:

```rust

let field = ExampleField::frombinarystr("01010101"); assert!(field.getindex(0)); assert!(!field.getindex(1)); ```

Set bit value by field:

```rust

let mut field = ExampleField::frombinarystr("01010101"); field.set(ExampleFlags::Flag1); field.set(ExampleFlags::Flag3); asserteq!("01011111", field.asbinary()); ```

Set bit value by index:

```rust

let mut field = ExampleField::frombinarystr("01010101"); field.setindex(1); field.setindex(3); asserteq!("01011111", field.asbinary()); ```

Clear bit value by field:

```rust

let mut field = ExampleField::frombinarystr("01010101"); field.clear(ExampleFlags::Flag0); field.clear(ExampleFlags::Flag2); asserteq!("01010000", field.asbinary()); ```

Clear bit value by index:

```rust

let mut field = ExampleField::frombinarystr("01010101"); field.clearindex(0); field.clearindex(2); asserteq!("01010000", field.asbinary()); ```

Toggle bit value by field:

```rust

let mut field = ExampleField::frombinarystr("01010101"); field.toggle(ExampleFlags::Flag0); asserteq!("01010100", field.asbinary()); field.toggle(ExampleFlags::Flag0); asserteq!("01010101", field.asbinary()); ```

Toggle bit value by index:

```rust

let mut field = ExampleField::frombinarystr("01010101"); field.toggleindex(0); asserteq!("01010100", field.asbinary()); field.toggleindex(0); asserteq!("01010101", field.asbinary()); ```

Named Getters and Setters

Ubits can generate getter and setter methods for zero or more fields, if a name is provided.

```rust use ubits::bitfield; bitfield! { pub u8 ExampleField ExampleFlags { 0 : Flag0 : (field0), // isfield0 & setfield0 & clearfield0 & togglefield0 1 : Flag1 : (field1), // isfield1 & setfield1 & clearfield1 & togglefield1 2 : Flag2, 3 : Flag3, 4 : Flag4, 5 : Flag5, 6 : Flag6, 7 : Flag7, } }

let mut field = ExampleField::frombinarystr("01010101"); asserteq!(true, field.isfield0()); asserteq!(false, field.isfield1());

field.setfield1(); asserteq!(true, field.isfield_1());

field.clearfield1(); asserteq!(false, field.isfield_1());

field.togglefield1(); asserteq!(true, field.isfield_1()); ```

Combinations

Combine bit fields:
(use into_combined to consume self)

```rust

let mut a = ExampleField::frombinarystr("01010101"); let b = ExampleField::frombinarystr("10101010"); asserteq!("11111111", a.combine(b).asbinary()); ```

Get the intersection of two bitfields:
(use into_intersection to consume self) ```rust

let mut a = ExampleField::frombinarystr("11000011"); let b = ExampleField::frombinarystr("01111110"); asserteq!("01000010", a.intersect(b).asbinary()); ```

Get the diff of two bitfields:
(use into_diff to consume self)

```rust

let mut a = ExampleField::frombinarystr("11000011"); let b = ExampleField::frombinarystr("01100110"); asserteq!("10100101", a.diff(b).asbinary()); ```

Bitwise

Both bit field instances and flags use bitwise operators to change bit values.

```rust

let mut fromzeros = ExampleField::zeros(); asserteq!("00000000", fromzeros.asbinary());

// set bit to 1 fromzeros |= ExampleFlags::Flag1; asserteq!("00000010", fromzeros.asbinary());

// set bit back to 0 fromzeros &= ExampleFlags::Flag1; asserteq!("00000000", fromzeros.asbinary());

// toggle a bit fromzeros ^= ExampleFlags::Flag1; asserteq!("00000010", fromzeros.asbinary());

fromzeros ^= ExampleFlags::Flag1; asserteq!("00000000", fromzeros.asbinary()); ```

Operations can also be chained together:

```rust

let mut fromzeros = ExampleField::zeros() | ExampleFlags::Flag1 | ExampleFlags::Flag3; asserteq!("00001010", fromzeros.asbinary());

```

Bitfield instances can also be created from combining flags:

```rust

let mut fromzeros = ExampleFlags::Flag1 | ExampleFlags::Flag3; asserteq!("00001010", fromzeros.asbinary());

```

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... no_compile 1 0 1 0 0 1 1 0

and the following flags... no_compile 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:

no_compile 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:

no_compile 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 |