Bit-Precision Array Immediate

This type is a wrapper over the array fundamental [T; N] that views its contents as a BitSlice region. As an array, it can be held directly by value and does not require an indirection such as the &BitSlice reference.

Original

[T; N]

Usage

BitArray is a Rust analogue of the C++ std::bitset<N> container. However, restrictions in the Rust type system do not allow specifying exact bit lengths in the array type. Instead, it must specify a storage array that can contain all the bits you want.

Because BitArray is a plain-old-data object, its fields are public and it has no restrictions on its interior value. You can freely access the interior storage and move data in or out of the BitArray type with no cost.

As a convenience, the BitArr! type-constructor macro can produce correct type definitions from an exact bit count and your memory-layout type parameters. Values of that type can then be built from the bitarr! value-constructor macro:

use bitvec::prelude::*;

type Example = BitArr!(for 43, in u32, Msb0);
let example: Example = bitarr!(u32, Msb0; 1; 33);

struct HasBitfield {
  inner: Example,
}

let ex2 = HasBitfield {
  inner: BitArray::new([1, 2]),
};

Note that the actual type of the Example alias is BitArray<[u32; 2], Msb0>, as that is ceil(32, 43), so the bitarr! macro can accept any number of bits in 33 .. 65 and will produce a value of the correct type.

Type Parameters

BitArray differs from the other data structures in the crate in that it does not take a T: BitStore parameter, but rather takes A: BitViewSized. That trait is implemented by all T: BitStore scalars and all [T; N] arrays of them, and provides the logic to translate the aggregate storage into the memory sequence that the crate expects.

As with all BitSlice regions, the O: BitOrder parameter specifies the ordering of bits within a single A::Store element.

Future API Changes

Exact bit lengths cannot be encoded into the BitArray type until the const-generics system in the compiler can allow type-level computation on type integers. When this stabilizes, bitvec will issue a major upgrade that replaces the BitArray<A, O> definition with BitArray<T, O, const N: usize> and match the C++ std::bitset<N> definition.

Large Bit-Arrays

As with ordinary arrays, large arrays can be expensive to move by value, and should generally be preferred to have static locations such as actual static bindings, a long lifetime in a low stack frame, or a heap allocation. While you certainly can Box<[BitArray<A, O>]> directly, you may instead prefer the BitBox or BitVec heap-allocated regions. These offer the same storage behavior and are better optimized than Box<BitArray> for working with the contained BitSlice region.

Examples

use bitvec::prelude::*;

const WELL_KNOWN: BitArr!(for 16, in u8, Lsb0) = BitArray::<[u8; 2], Lsb0> {
  data: *b"bv",
  ..BitArray::ZERO
};

struct HasBitfields {
  inner: BitArr!(for 50, in u8, Lsb0),
}

impl HasBitfields {
  fn new() -> Self {
    Self {
      inner: bitarr!(u8, Lsb0; 0; 50),
    }
  }

  fn some_field(&self) -> &BitSlice<u8, Lsb0> {
    &self.inner[2 .. 52]
  }
}