pub unsafe trait BitOrder: 'static {
fn at<R>(index: BitIdx<R>) -> BitPos<R>
where
R: BitRegister;
fn select<R>(index: BitIdx<R>) -> BitSel<R>
where
R: BitRegister,
{ ... }
fn mask<R>(
from: impl Into<Option<BitIdx<R>>>,
upto: impl Into<Option<BitTail<R>>>
) -> BitMask<R>
where
R: BitRegister,
{ ... }
}
Expand description
An ordering over a register.
Usage
bitvec
structures store and operate on semantic index counters, not
electrical bit positions. The BitOrder::at
function takes a semantic
ordering, BitIdx
, and produces a corresponding electrical position,
BitPos
.
Safety
If your implementation violates any of the requirements on these functions, then the program will become incorrect, and have unspecified behavior. The best-case outcome is that operations relying on your implementation will crash the program; the worst-case is that memory access will silently become corrupt.
You are responsible for adhering to the requirements of these functions. There are verification functions that you can use in your test suite; however, it is not yet possible to prove correctness at compile-time.
This is an unsafe trait
to implement because you are responsible for upholding
the stated requirements.
The implementations of BitOrder
are trusted to drive safe code, and once data
leaves a BitOrder
implementation, it is considered safe to use as the basis
for interaction with memory.
Verification
The verify
and verify_for_type
functions are available for your test
suites. They ensure that a BitOrder
implementation satisfies the requirements
when invoked for a given register type.
Examples
Implementations are not required to remain contiguous over a register. This example swizzles the high and low halves of each byte, but any translation is valid as long as it satisfies the strict one-to-one requirement of index-to-position.
use bitvec::{
prelude::BitOrder,
// Additional symbols:
index::{BitIdx, BitPos},
mem::BitRegister,
};
pub struct HiLo;
unsafe impl BitOrder for HiLo {
fn at<R: BitRegister>(idx: BitIdx<R>) -> BitPos<R> {
BitPos::new(idx.value() ^ 4).unwrap()
}
}
#[test]
#[cfg(test)]
fn prove_hilo() {
bitvec::order::verify::<HiLo>();
}
Required methods
fn at<R>(index: BitIdx<R>) -> BitPos<R> where
R: BitRegister,
fn at<R>(index: BitIdx<R>) -> BitPos<R> where
R: BitRegister,
Converts a semantic bit index into an electrical bit position.
This function is the basis of the trait, and must adhere to a number of requirements in order for an implementation to be correct.
Type Parameters
R
: The register type that the index and position govern.
Parameters
index
: The semantic index of a bit within a registerR
.
Returns
The electrical position of the indexed bit within the register R
. See
the BitPos
documentation for what electrical positions are
considered to mean.
Requirements
This function must satisfy the following requirements for all possible
input and output values, for all possible R
type parameters:
Totality
This function must be able to accept every input in the range
BitIdx::ZERO
to BitIdx::LAST
, and produce a value in the same
range as a BitPos
.
Bijection
There must be an exactly one-to-one correspondence between input value and output value. No input index may choose its output from a set of more than one position, and no output position may be produced by more than one input index.
Purity
The translation from index to position must be consistent for the
lifetime of at least all data structures in the program. This function
may refer to global state, but that state must be immutable while
any bitvec
data structures exist, and must not be used to violate
the totality or bijection requirements.
Output Validity
The produced BitPos
must be within the valid range of that type.
Call sites of this function will not take any steps to constrain or
check the return value. If you use unsafe
code to produce an invalid
BitPos
, the program is incorrect, and will likely crash.
Usage
This function is only ever called with input values in the valid
BitIdx
range. Implementors are not required to consider any values
outside this range in their function body.
Provided methods
fn select<R>(index: BitIdx<R>) -> BitSel<R> where
R: BitRegister,
fn select<R>(index: BitIdx<R>) -> BitSel<R> where
R: BitRegister,
Converts a semantic bit index into a one-hot selector mask.
This is an optional function; a default implementation is provided for you. If you choose to override it, your implementation must retain the behavior of the default implementation.
The default implementation calls Self::at
to convert the index into
a position, then turns that position into a selector mask with the
expression 1 << pos
. BitOrder
implementations may choose to provide
a faster mask production here, as long as they match this behavior.
Type Parameters
R
: The register type that the index and selector govern.
Parameters
index
: The semantic index of a bit within a registerR
.
Returns
A one-hot selector mask for the bit indicated by the index value.
Requirements
A one-hot encoding means that there is exactly one bit set in the
produced value. It must be equivalent to 1 << Self::at::<R>(index)
.
As with at
, this function must produce a unique mapping from each
legal index in the BitIdx
domain to a one-hot value of R
.
Constructs a multiple-bit selector mask for batched operations on a
register R
.
The default implementation of this function traverses the index range,
converting each index into a single-bit selector with Self::select
and accumulating into a combined register value.
Type Parameters
R
: The register type for which the mask is built.
Parameters
from
: The inclusive starting index for the mask.upto
: The exclusive ending index for the mask.
Returns
A bit-mask with all bits corresponding to the input index range set high and all others set low.
Requirements
This function must always be equivalent to this expression:
(from .. upto)
.map(Self::select::<R>)
.fold(0, |mask, sel| mask | sel)