bitvec

Macro bits

Source
macro_rules! bits {
    (static mut Cell<$store:ident>, $order:ty; $val:expr; $len:expr) => { ... };
    (static mut $store:ident, $order:ident; $val:expr; $len:expr) => { ... };
    (static mut Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => { ... };
    (static mut $store:ident, $order:ident; $($val:expr),* $(,)?) => { ... };
    (static mut $val:expr; $len:expr) => { ... };
    (static mut $($val:expr),* $(,)?) => { ... };
    (static Cell<$store:ident>, $order:ty; $val:expr; $len:expr) => { ... };
    (static Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => { ... };
    (static $store:ident, $order:ident; $val:expr; $len:expr) => { ... };
    (static $val:expr; $len:expr) => { ... };
    (static $store:ident, $order:ident; $($val:expr),* $(,)?) => { ... };
    (static $($val:expr),* $(,)?) => { ... };
    (mut Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => { ... };
    (mut Cell<$store:ident>, $order:path; $($val:expr),* $(,)?) => { ... };
    (mut $store:ident, $order:ident; $($val:expr),* $(,)?) => { ... };
    (mut $store:ident, $order:path; $($val:expr),* $(,)?) => { ... };
    (mut $store:ty, $order:ty; $val:expr; $len:expr) => { ... };
    (mut $val:expr; $len:expr) => { ... };
    (mut $($val:expr),* $(,)?) => { ... };
    ($store:ty, $order:ty; $val:expr; $len:expr) => { ... };
    (Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => { ... };
    ($store:ident, $order:ident; $($val:expr),* $(,)?) => { ... };
    (Cell<$store:ident>, $order:path; $($val:expr),* $(,)?) => { ... };
    ($store:ident, $order:path; $($val:expr),* $(,)?) => { ... };
    ($val:expr; $len:expr) => { ... };
    ($($val:expr),* $(,)?) => { ... };
}
Expand description

§Bit-Slice Region Constructor

This macro provides a bit-initializer syntax for BitSlice reference values. It takes a superset of the vec! arguments, and is capable of producing bit-slices in const contexts (for known type parameters).

Like vec!, it can accept a sequence of comma-separated bit values, or a semicolon-separated pair of a bit value and a repetition counter. Bit values may be any integer or name of a const integer, but should only be 0 or 1.

§Argument Syntax

It accepts two modifier prefixes, zero or two type parameters, and the bit expressions described above.

The modifier prefixes are separated from the remaining arguments by clearspace.

  • static: If the first argument is the keyword static, then this produces a &'static BitSlice reference bound into a (hidden, unnameable) static BitArray item. If not, then it produces a stack temporary that the Rust compiler automatically extends to have the lifetime of the returned reference. Note that non-static invocations rely on the compiler’s escape analysis, and you should typically not try to move them up the call stack.
  • mut: If the first argument is the keyword mut, then this produces a &mut writable BitSlice.
  • static mut: These can be combined to create a &'static mut BitSlice. It is always safe to use this reference, because the static mut BitArray it creates is concealed and unreachable by any other codepath, and so the produced reference is always the sole handle that can reach it.

The next possible arguments are a pair of BitOrder/BitStore type parameters.

  • $order ,: When this is one of the three literal tokens LocalBits, Lsb0, or Msb0, then the macro is able to compute the encoded bit-array contents at compile time, including in const contexts. When it is anything else, the encoding must take place at runtime. The name or path chosen must be in scope at the macro invocation site.

    When not provided, this defaults to Lsb0.

  • $store ;: This must be one of uTYPE, Cell<uTYPE>, AtomicUTYPE, or RadiumUTYPE where TYPE is one of 8, 16, 32, 64, or size. The macro recognizes this token textually, and does not have access to the type system resolver, so it will not accept aliases or qualified paths.

    When not provided, this defaults to usize.

The static/mut modifiers may be individually present or absent independently of the type-parameter pair. The pair must be either both absent or both present together.

Previous versions of bitvec supported $order`-only arguments. This has been removed for clarity of use and ease of implementation.

§Safety

Rust considers all static mut bindings to be unsafe to use. While bits! can prevent some of this unsafety by preventing direct access to the created static mut buffer, there are still ways to create multiple names referring to the same underlying buffer.

use bitvec::prelude::*;

fn unsound() -> &'static mut BitSlice<usize, Lsb0> {
  unsafe { bits![static mut 0; 64] }
}

let a = unsound();
let b = unsound();

The two names a and b can be used to produce aliasing &mut [usize] references.

You must not invoke bits![static mut …] in a context where it can be used to create multiple escaping names. This, and only this, argument combination of the macro produces a value that requires a call-site unsafe block to use.

If you do not use this behavior to create multiple names over the same underlying buffer, then the macro’s expansion is safe to use, as bitvec’s existing alias-protection behavior suffices.

§Examples

use bitvec::prelude::*;
use core::cell::Cell;
use radium::types::*;

let a: &BitSlice = bits![0, 1, 0, 0, 1];

let b: &BitSlice = bits![1; 5];
assert_eq!(b.len(), 5);

let c = bits![u16, Lsb0; 0, 1, 0, 0, 1];
let d = bits![static Cell<u16>, Msb0; 1; 10];
let e = unsafe { bits![static mut u32, LocalBits; 0; 15] };
let f = bits![RadiumU32, Msb0; 1; 20];