Trait bitvec::field::BitField[][src]

pub trait BitField {
    fn load_le<M>(&self) -> M
    where
        M: BitMemory
;
fn load_be<M>(&self) -> M
    where
        M: BitMemory
;
fn store_le<M>(&mut self, value: M)
    where
        M: BitMemory
;
fn store_be<M>(&mut self, value: M)
    where
        M: BitMemory
; fn load<M>(&self) -> M
    where
        M: BitMemory
, { ... }
fn store<M>(&mut self, value: M)
    where
        M: BitMemory
, { ... } }

Performs C-style bitfield access through a BitSlice.

This trait transfers data between a BitSlice region and a local integer. The trait functions always place the live bits of the value against the least significant bit edge of the local integer (the return value of the load methods, and the argument value of the store methods).

Methods should be called as bits[start .. end].load_or_store(), where the range subslice selects no more than the M::BITS element width.

Target-Specific Behavior

When you are using this trait to manage memory that never leaves your machine, you can use the load and store methods. However, if you are using this trait to operate on a de/serialization buffer, where the exact bit pattern in memory is important to your work and/or you need to be aware of the processor byte endianness, you must not use these methods.

Instead, use load_le, load_be, store_le, orstore_be directly.

The un-suffixed methods choose their implementation based on the target processor byte endianness; the suffixed methods have a consistent and fixed behavior.

Element- and Bit- Ordering Combinations

The _le and _be method suffices refer to the significance of successive elements T in memory, while the BitOrder trait refers to the order that bits within a single element T are traversed. The BitField methods and the BitOrder implementors are not related.

When a load or store operation is contained in only one memory element, then the _le and _be methods have the same behavior. They differ when the operation must touch more than one element.

The module documentation contains a more detailed explanation, and examples, for this behavior.

Required methods

fn load_le<M>(&self) -> M where
    M: BitMemory
[src]

Loads from self, using little-endian element T ordering.

This function interprets a multi-element slice as having its least significant chunk in the low memory address, and its most significant chunk in the high memory address. Each element T is still interpreted from individual bytes according to the local CPU ordering.

Parameters

  • &self: A read reference to some bits in memory. This slice must be trimmed to have a width no more than the M::BITS width of the type being loaded. This can be accomplished with range indexing on a larger slice.

Returns

A value M whose least self.len() significant bits are filled with the bits of self. If self spans multiple elements T, then the lowest-address T is interpreted as containing the least significant bits of the return value M, and the highest-address T is interpreted as containing its most significant bits.

Panics

This method is encouraged to panic if self is empty, or wider than a single element M.

Examples

This example shows how a value is segmented across multiple storage elements:

use bitvec::prelude::*;

let mut data = [0u8; 3];
data.view_bits_mut::<Msb0>()
  [5 .. 17]
  .store_le(0b0000_1_1011_1000_110u16);
//                 O PQRS TUVW XYZ

assert_eq!(data, [
  0b00000_110, 0b1011_1000, 0b1_0000000
//        XYZ    PQRS TUVW    O
]);

let val = data.view_bits::<Msb0>()
  [5 .. 17]
  .load_le::<u16>();
assert_eq!(
  val,
  0b0000_1_1011_1000_110,
//       O PQRS TUVW XYZ
);

And this example shows how the same memory region will be read by different BitOrder implementors:

use bitvec::prelude::*;

// Bit pos:   14                                     19  16
// Lsb0:     ─┤                                       ├──┤
let arr = [0b0100_0000_0000_0011u16, 0b0001_0000_0000_1110u16];
// Msb0:                      ├─       ├──┤
// Bit pos:                  14       16  19

assert_eq!(
  arr.view_bits::<Lsb0>()[14 .. 20].load_le::<u8>(),
  0b111001,
);
assert_eq!(
  arr.view_bits::<Msb0>()[14 .. 20].load_le::<u8>(),
  0b000111,
);

fn load_be<M>(&self) -> M where
    M: BitMemory
[src]

Loads from self, using big-endian element T ordering.

This function interprets a multi-element slice as having its most significant chunk in the low memory address, and its least significant chunk in the high memory address. Each element T is still interpreted from individual bytes according to the local CPU ordering.

Parameters

  • &self: A read reference to some bits in memory. This slice must be trimmed to have a width no more than the M::BITS width of the type being loaded. This can be accomplished with range indexing on a larger slice.

Returns

A value M whose least self.len() significant bits are filled with the bits of self. If self spans multiple elements T, then the lowest-address T is interpreted as containing the most significant bits of the return value M, and the highest-address T is interpreted as containing its least significant bits.

Panics

This method is encouraged to panic if self is empty, or wider than a single element M.

Examples

This example shows how a value is segmented across multiple storage elements:

use bitvec::prelude::*;

let mut data = [0u8; 3];
data.view_bits_mut::<Msb0>()
  [5 .. 17]
  .store_be(0b0000_110_1000_1011_1u16);
//                 OPQ RSTU VWXY Z

assert_eq!(data, [
  0b00000_110, 0b1000_1011, 0b1_0000000
//        OPQ    RSTU VWXY    Z
]);

let val = data.view_bits::<Msb0>()
  [5 .. 17]
  .load_be::<u16>();
assert_eq!(
  val,
  0b0000_110_1000_1011_1,
//       OPQ RSTU VWXY Z
);

And this example shows how the same memory region will be read by different BitOrder implementations:

use bitvec::prelude::*;
// Bit pos:   14                                     19  16
// Lsb0:     ─┤                                       ├──┤
let arr = [0b0100_0000_0000_0011u16, 0b0001_0000_0000_1110u16];
// Msb0:                      ├─       ├──┤
// Bit pos:                  14       16  19

assert_eq!(
  arr.view_bits::<Lsb0>()[14 .. 20].load_be::<u8>(),
  0b011110,
);
assert_eq!(
  arr.view_bits::<Msb0>()[14 .. 20].load_be::<u8>(),
  0b110001,
);

fn store_le<M>(&mut self, value: M) where
    M: BitMemory
[src]

Stores into self, using little-endian element ordering.

This function interprets a multi-element slice as having its least significant chunk in the low memory address, and its most significant chunk in the high memory address. Each element T is still interpreted from individual bytes according to the local CPU ordering.

Parameters

  • &mut self: A write reference to some bits in memory. This slice must be trimmed to have a width no more than the M::BITS width of the type being stored. This can be accomplished with range indexing on a larger slice.
  • value: A value, whose self.len() least significant bits will be stored into self.

Behavior

The self.len() least significant bits of value are written into the domain of self. If self spans multiple elements T, then the lowest-address T is interpreted as containing the least significant bits of the M return value, and the highest-address T is interpreted as containing its most significant bits.

Panics

This method is encouraged to panic if self is empty, or wider than a single element M.

Examples

This example shows how a value is segmented across multiple storage elements:

use bitvec::prelude::*;

let mut data = [0u8; 3];
data.view_bits_mut::<Lsb0>()
  [5 .. 17]
  .store_le(0b0000_1_1011_1000_110u16);
//                 O PQRS TUVW XYZ

assert_eq!(data, [
  0b110_00000, 0b1011_1000, 0b0000000_1
//  XYZ          PQRS TUVW            O
]);

let val = data.view_bits::<Lsb0>()
  [5 .. 17]
  .load_le::<u16>();
assert_eq!(
  val,
  0b0000_1_1011_1000_110u16,
//       O PQRS TUVW XYZ
);

And this example shows how the same memory region is written by different BitOrder implementations:

use bitvec::prelude::*;
let mut lsb0 = bitarr![Lsb0, u16; 0; 32];
let mut msb0 = bitarr![Msb0, u16; 0; 32];

// Bit pos:        14                                     19  16
// Lsb0:          ─┤                                       ├──┤
let exp_lsb0 = [0b0100_0000_0000_0000u16, 0b0000_0000_0000_1110u16];
let exp_msb0 = [0b0000_0000_0000_0011u16, 0b0001_0000_0000_0000u16];
// Msb0:                           ├─       ├──┤
// Bit pos:                       14       16  19

lsb0[14 ..= 19].store_le(0b111001u8);
msb0[14 ..= 19].store_le(0b000111u8);
assert_eq!(lsb0.as_raw_slice(), exp_lsb0);
assert_eq!(msb0.as_raw_slice(), exp_msb0);

fn store_be<M>(&mut self, value: M) where
    M: BitMemory
[src]

Stores into self, using big-endian element ordering.

This function interprets a multi-element slice as having its most significant chunk in the low memory address, and its least significant chunk in the high memory address. Each element T is still interpreted from individual bytes according to the local CPU ordering.

Parameters

  • &mut self: A write reference to some bits in memory. This slice must be trimmed to have a width no more than the M::BITS width of the type being stored. This can be accomplished with range indexing on a larger slice.
  • value: A value, whose self.len() least significant bits will be stored into self.

Behavior

The self.len() least significant bits of value are written into the domain of self. If self spans multiple elements T, then the lowest-address T is interpreted as containing the most significant bits of the M return value, and the highest-address T is interpreted as containing its least significant bits.

Panics

This method is encouraged to panic if self is empty, or wider than a single element M.

Examples

This example shows how a value is segmented across multiple storage elements:

use bitvec::prelude::*;

let mut data = [0u8; 3];
data.view_bits_mut::<Lsb0>()
  [5 .. 17]
  .store_be(0b0000_110_1000_1011_1u16);
//                 OPQ RSTU VWXY Z

assert_eq!(data, [
  0b110_00000, 0b1000_1011, 0b0000000_1
//  OPQ          RSTU VWXY            Z
]);

let val = data.view_bits::<Lsb0>()
  [5 .. 17]
  .load_be::<u16>();
assert_eq!(
  val,
  0b0000_110_1000_1011_1u16,
//       OPQ RSTU VWXY Z
);

And this example shows how the same memory region is written by different BitOrder implementations:

use bitvec::prelude::*;
let mut lsb0 = bitarr![Lsb0, u16; 0; 32];
let mut msb0 = bitarr![Msb0, u16; 0; 32];

// Bit pos:        14                                     19  16
// Lsb0:          ─┤                                       ├──┤
let exp_lsb0 = [0b0100_0000_0000_0000u16, 0b0000_0000_0000_1110u16];
let exp_msb0 = [0b0000_0000_0000_0011u16, 0b0001_0000_0000_0000u16];
// Msb0:                           ├─       ├──┤
// Bit pos:                       14       16  19

lsb0[14 ..= 19].store_be(0b011110u8);
msb0[14 ..= 19].store_be(0b110001u8);
assert_eq!(lsb0.as_raw_slice(), exp_lsb0);
assert_eq!(msb0.as_raw_slice(), exp_msb0);
Loading content...

Provided methods

fn load<M>(&self) -> M where
    M: BitMemory
[src]

Loads the bits in the self region into a local value.

This can load into any of the unsigned integers which implement BitMemory. Any further transformation must be done by the user.

Target-Specific Behavior

THIS FUNCTION CHANGES BEHAVIOR FOR DIFFERENT TARGETS.

The default implementation of this function calls load_le on little-endian byte-ordered CPUs, and load_be on big-endian byte-ordered CPUs.

If you are using this function from a region that crosses multiple elements in memory, be aware that it will behave differently on big-endian and little-endian target architectures.

Parameters

  • &self: A read reference to some bits in memory. This slice must be trimmed to have a width no more than the M::BITS width of the type being loaded. This can be accomplished with range indexing on a larger slice.

Returns

A value M whose least self.len() significant bits are filled with the bits of self.

Panics

This method is encouraged to panic if self is empty, or wider than a single element M.

fn store<M>(&mut self, value: M) where
    M: BitMemory
[src]

Stores a sequence of bits from the user into the domain of self.

This can store any of the unsigned integers which implement BitMemory. Any other types must first be transformed by the user.

Target-Specific Behavior

THIS FUNCTION CHANGES BEHAVIOR FOR DIFFERENT TARGETS.

The default implementation of this function calls store_le on little-endian byte-ordered CPUs, and store_be on big-endian byte-ordered CPUs.

If you are using this function to store into a region that crosses multiple elements in memory, be aware that it will behave differently on big-endian and little-endian target architectures.

Parameters

  • &mut self: A write reference to some bits in memory. This slice must be trimmed to have a width no more than the M::BITS width of the type being stored. This can be accomplished with range indexing on a larger slice.
  • value: A value, whose self.len() least significant bits will be stored into self.

Behavior

The self.len() least significant bits of value are written into the domain of self.

Panics

This method is encouraged to panic if self is empty, or wider than a single element M.

Loading content...

Implementors

impl<O, T> BitField for BitBox<O, T> where
    O: BitOrder,
    T: BitStore,
    BitSlice<O, T>: BitField
[src]

impl<O, T> BitField for BitVec<O, T> where
    O: BitOrder,
    T: BitStore,
    BitSlice<O, T>: BitField
[src]

impl<O, V> BitField for BitArray<O, V> where
    O: BitOrder,
    V: BitViewSized,
    BitSlice<O, V::Store>: BitField
[src]

impl<T> BitField for BitSlice<Lsb0, T> where
    T: BitStore
[src]

fn load_le<M>(&self) -> M where
    M: BitMemory
[src]

Loads from self, using little-endian element ordering if self spans more than one T element.

If self.domain() produces a Domain::Region, then:

  • its head element contains the least significant segment of the returned value, in the bits at the most significant edge of the element,
  • its body slice contains successively more-significant segments, and
  • its tail element contains the most significant segment of the returned value, in the bits at the least significant edge of the element.

If the domain is an Enclave, then the referent element is merely loaded, shifted, and masked; no recombination of segments is necessary.

Examples

use bitvec::prelude::*;

let mut data = [0u8; 3];
data.view_bits_mut::<Lsb0>()[5 .. 21].store_le::<u16>(
  0b1_1011_0100_1100_011
//  K LMNO PQRS TUVW XYZ
);
assert_eq!(data, [
  0b011_00000, 0b0100_1100, 0b000_1_1011
//  XYZ          PQRS TUVW        K LMNO
]);
let val = data.view_bits::<Lsb0>()[5 .. 21].load_le::<u16>();
assert_eq!(
  val,
  0b1_1011_0100_1100_011,
//  K LMNO PQRS TUVW XYZ
);

fn load_be<M>(&self) -> M where
    M: BitMemory
[src]

Loads from self, using big-endian element ordering if self spans more than one T element.

If self.domain() produces a Domain::Region, then:

  • its head element contains the most significant segment of the returned value, in the bits at the most significant edge of the element,
  • its body slice contains successively less-significant segments, and
  • its tail element contains the least significant segment of the returned value, in the bits at the least significant edge of the element.

If the domain is an Enclave, then the referent element is merely loaded, shifted, and masked; no recombination of segments is necessary.

Examples

use bitvec::prelude::*;

let mut data = [0u8; 3];
data.view_bits_mut::<Lsb0>()[5 .. 21].store_be::<u16>(
  0b011_1100_0100_1011_1,
//  KLM NOPQ RSTU VWXY Z
);
assert_eq!(data, [
  0b011_00000, 0b1100_0100, 0b000_1011_1
//  KLM          NOPQ RSTU        VWXY Z
]);
let val = data.view_bits::<Lsb0>()[5 .. 21].load_be::<u16>();
assert_eq!(
  val,
  0b011_1100_0100_1011_1,
//  KLM NOPQ RSTU VWXY Z
);

fn store_le<M>(&mut self, value: M) where
    M: BitMemory
[src]

Stores into self, using little-endian element ordering if self spans more than one T element.

If self.domain() produces a Domain::Region, then:

  • its head element receives the least significant segment of value, in the bits at the most significant edge of the element,
  • its body slice receives successively more-significant segments of value, and
  • its tail element receives the most significant segment of value, in the bits at the least significant edge of the element.

If the domain is an Enclave, then value is shifted into place and written without any segmentation.

Examples

See the documentation for <BitSlice<Lsb0, u8> as BitField>::load_le.

fn store_be<M>(&mut self, value: M) where
    M: BitMemory
[src]

Stores into self, using big-endian element ordering if self spans more than one T element.

If self.domain() produces a Domain::Region, then:

  • its head element receives the most significant segment of value, in the bits at the most significant edge of the element,
  • its body slice receives successively less-significant segments of value, and
  • its tail element receives the least significant segment of value, in the bits at the least significant edge of the element.

If the domain is an Enclave, then value is shifted into place and written without any segmentation.

Examples

See the documentation for <BitSlice<Lsb0, u8> as BitField>::load_be.

impl<T> BitField for BitSlice<Msb0, T> where
    T: BitStore
[src]

fn load_le<M>(&self) -> M where
    M: BitMemory
[src]

Loads from self, using little-endian element ordering if self spans more than one T element.

If self.domain() produces a Domain::Region, then:

  • its head element contains the least significant segment of the returned value, in the bits at the least significant edge of the element,
  • its body slice contains successively more-significant segments, and
  • its tail element contains the most significant segment of the returned value, in the bits at the most significant edge of the element.

If the domain is an Enclave, then the referent element is merely loaded, shifted, and masked; no recombination of segments is necessary.

Examples

use bitvec::prelude::*;

let mut data = [0u8; 3];
data.view_bits_mut::<Msb0>()[5 .. 21].store_le::<u16>(
  0b1_1011_0100_1100_110
//  K LMNO PQRS TUVW XYZ
);
assert_eq!(data, [
  0b00000_110, 0b0100_1100, 0b1_1011_000
//        XYZ    PQRS TUVW    K LMNO
]);
let val = data.view_bits::<Msb0>()[5 .. 21].load_le::<u16>();
assert_eq!(
  val,
  0b1_1011_0100_1100_110,
//  K LMNO PQRS TUVW XYZ
);

fn load_be<M>(&self) -> M where
    M: BitMemory
[src]

Loads from self, using big-endian element ordering if self spans more than one element T.

If self.domain() produces a Domain::Region, then:

  • its head element contains the most significant segment of the returned value, in the bits at the least significant edge of the element,
  • its body slice contains successively less-significant segments, and
  • its tail element contains the least significant segment of the returned value, in the bits at the most significant edge of the element.

If the domain is an Enclave, then the referent element is merely loaded, shifted, and masked; no recombination of segments is necessary.

Examples

use bitvec::prelude::*;

let mut data = [0u8; 3];
data.view_bits_mut::<Msb0>()[5 .. 21].store_be::<u16>(
  0b110_1011_1100_0100_1
//  KLM NOPQ RSTU VWXY Z
);
assert_eq!(data, [
  0b00000_110, 0b1011_1100, 0b0100_1_000
//        KLM    NOPQ RSTU    VWXY Z
]);
let val = data.view_bits::<Msb0>()[5 .. 21].load_be::<u16>();
assert_eq!(
  val,
  0b110_1011_1100_0100_1,
//  KLM NOPQ RSTU VWXY Z
);

fn store_le<M>(&mut self, value: M) where
    M: BitMemory
[src]

Stores into self, using little-endian element ordering if self spans more than one T element.

If self.domain() produces a Domain::Region, then:

  • its head element receives the least significant segment of value, in the bits at the least significant edge of the element,
  • its body slice receives successively more-significant segments of value, and
  • its tail element receives the most significant segment of value, in the bits at the most significant edge of the element.

If the domain is an Enclave, then value is shifted into place and written without any segmentation.

Examples

See the documentation for <BitSlice<Msb0, u8> as BitField>::load_le.

fn store_be<M>(&mut self, value: M) where
    M: BitMemory
[src]

Stores into self, using big-endian element ordering if self spans more than one T element.

If self.domain() produces a Domain::Region, then:

  • its head element receives the most significant segment of value, in the bits at the least significant edge of the element,
  • its body slice receives successively less-significant segments of value, and
  • its tail element receives the least significant segment of value, in the bits at the most significant edge of the element.

If the domain is an Enclave, then value is shifted into place and written without any segmentation.

Examples

See the documentation for <BitSlice<Lsb0, u8> as BitField>::load_be.

Loading content...