Struct bitvec::BitSlice

source ·
#[repr(transparent)]
pub struct BitSlice<C = BigEndian, T = u8>where
    C: Cursor,
    T: Bits,
{ /* private fields */ }
Expand description

A compact slice of bits, whose cursor and storage type can be customized.

BitSlice is a newtype wrapper over [T], and as such can only be held by reference. It is impossible to create a Box<BitSlice<C, T>> from this library, and assembling one yourself is Undefined Behavior for which this library is not responsible. Do not try to create a Box<BitSlice>. If you want an owned bit collection, use BitVec. (This may change in a future release.)

BitSlice is strictly a reference type. The memory it governs must be owned by some other type, and a shared or exclusive reference to it as BitSlice can be created by using the From implementation on &BitSlice and &mut BitSlice.

BitSlice is to BitVec what [T] is to Vec<T>.

BitSlice takes two type parameters.

  • C: Cursor must be an implementor of the Cursor trait. BitVec takes a PhantomData marker for access to the associated functions, and will never make use of an instance of the trait. The default implementations, LittleEndian and BigEndian, are zero-sized, and any further implementations should be as well, as the invoked functions will never receive state.
  • T: Bits must be a primitive type. Rust decided long ago to not provide a unifying trait over the primitives, so Bits provides access to just enough properties of the primitives for BitVec to use. This trait is sealed against downstream implementation, and can only be implemented in this crate.

Implementations

Gets the bit value at the given position.

The index value is a semantic count, not a bit address. It converts to a bit position internally to this function.

Examples
use bitvec::*;
let bv = bitvec![0, 0, 1, 0, 0];
let bits: &BitSlice = &bv;
assert!(bits.get(2));

Sets the bit value at the given position.

The index value is a semantic count, not a bit address. It converts to a bit position internally to this function.

Examples
use bitvec::*;
let mut bv = bitvec![0; 5];
let bits: &mut BitSlice = &mut bv;
bits.set(2, true);
assert!(bits.get(2));

Returns true if all bits in the slice are set (logical ).

Truth Table
0 0 => 0
0 1 => 0
1 0 => 0
1 1 => 1
Examples
use bitvec::*;
let all = bitvec![1; 10];
let any = bitvec![0, 0, 1, 0, 0];
let some = bitvec![1, 1, 0, 1, 1];
let none = bitvec![0; 10];

assert!(all.all());
assert!(!any.all());
assert!(!some.all());
assert!(!none.all());

Returns true if any bit in the slice is set (logical ).

Truth Table
0 0 => 0
0 1 => 1
1 0 => 1
1 1 => 1
Examples
use bitvec::*;
let all = bitvec![1; 10];
let any = bitvec![0, 0, 1, 0, 0];
let some = bitvec![1, 1, 0, 1, 1];
let none = bitvec![0; 10];

assert!(all.any());
assert!(any.any());
assert!(some.any());
assert!(!none.any());

Returns true if any bit in the slice is unset (logical ¬∧).

Truth Table
0 0 => 1
0 1 => 1
1 0 => 1
1 1 => 0
Examples
use bitvec::*;
let all = bitvec![1; 10];
let any = bitvec![0, 0, 1, 0, 0];
let some = bitvec![1, 1, 0, 1, 1];
let none = bitvec![0; 10];

assert!(!all.not_all());
assert!(any.not_all());
assert!(some.not_all());
assert!(none.not_all());

Returns true if all bits in the slice are unset (logical ¬∨).

Truth Table
0 0 => 1
0 1 => 0
1 0 => 0
1 1 => 0
Examples
use bitvec::*;
let all = bitvec![1; 10];
let any = bitvec![0, 0, 1, 0, 0];
let some = bitvec![1, 1, 0, 1, 1];
let none = bitvec![0; 10];

assert!(!all.not_any());
assert!(!any.not_any());
assert!(!some.not_any());
assert!(none.not_any());

Returns true if some, but not all, bits are set and some, but not all, are unset.

This is false if either all() or none() are true.

Truth Table
0 0 => 0
0 1 => 1
1 0 => 1
1 1 => 0
Examples
use bitvec::*;
let all = bitvec![1; 2];
let some = bitvec![1, 0];
let none = bitvec![0; 2];

assert!(!all.some());
assert!(some.some());
assert!(!none.some());

Counts how many bits are set high.

Examples
use bitvec::*;
let bv = bitvec![1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1];
assert_eq!(bv.count_ones(), 7);

Counts how many bits are set low.

Examples
use bitvec::*;
let bv = bitvec![1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1];
assert_eq!(bv.count_zeros(), 6);

Returns the number of bits contained in the BitSlice.

Examples
use bitvec::*;
let bv = bitvec![1; 10];
let bits: &BitSlice = &bv;
assert_eq!(bits.len(), 10);

Counts how many whole storage elements are in the BitSlice.

If the BitSlice length is not an even multiple of the width of T, then the slice under this BitSlice is one element longer than this method reports, and the number of bits in it are reported by bits().

Examples
use bitvec::*;
let bv = bitvec![1; 10];
let bits: &BitSlice = &bv;
assert_eq!(bits.elts(), 1);
use bitvec::*;
let bv = bitvec![1; 16];
let bits: &BitSlice = &bv;
assert_eq!(bits.elts(), 2);

Counts how many bits are in the trailing partial storage element.

If the BitSlice length is an even multiple of the width of T, then this returns 0 and the BitSlice does not consider its final element to be partially used.

Examples
use bitvec::*;
let bv = bitvec![1; 10];
let bits: &BitSlice = &bv;
assert_eq!(bits.bits(), 2);
use bitvec::*;
let bv = bitvec![1; 16];
let bits: &BitSlice = &bv;
assert_eq!(bits.bits(), 0);

Returns true if the slice contains no bits.

Examples
use bitvec::*;
let bv = bitvec![];
let bits: &BitSlice = &bv;
assert!(bits.is_empty());
use bitvec::*;
let bv = bitvec![0; 5];
let bits: &BitSlice = &bv;
assert!(!bits.is_empty());

Provides read-only iteration across the collection.

The iterator returned from this method implements ExactSizeIterator and DoubleEndedIterator just as the consuming .into_iter() method’s iterator does.

Provides mutable traversal of the collection.

It is impossible to implement IndexMut on BitSlice because bits do not have addresses, so there can be no &mut u1. This method allows the client to receive an enumerated bit, and provide a new bit to set at each index.

Examples
use bitvec::*;
let mut bv = bitvec![1; 8];
let bref: &mut BitSlice = &mut bv;
bref.for_each(|idx, bit| {
    if idx % 2 == 0 {
        !bit
    }
    else {
        bit
    }
});
assert_eq!(&[0b01010101], bref.as_ref());

Trait Implementations

Performs unsigned addition in place on a BitSlice.

If the addend BitSlice is shorter than self, the addend is zero-extended at the left (so that its final bit matches with self’s final bit). If the addend is longer, the excess front length is unused.

Addition proceeds from the right ends of each slice towards the left. Because this trait is forbidden from returning anything, the final carry-out bit is discarded.

Note that, unlike BitVec, there is no subtraction implementation until I find a subtraction algorithm that does not require modifying the subtrahend.

Subtraction can be implemented by negating the intended subtrahend yourself and then using addition, or by using BitVecs instead of BitSlices.

Performs unsigned wrapping addition in place.

Examples

This example shows addition of a slice wrapping from MAX to zero.

use bitvec::*;
let nums: [BitVec; 3] = [
    bitvec![1, 1, 1, 0],
    bitvec![1, 1, 1, 1],
    bitvec![0, 0, 0, 0],
];
let one = bitvec![0, 1];
let mut num = nums[0].clone();
let numr: &mut BitSlice = &mut num;
*numr += &one;
assert_eq!(numr, &nums[1] as &BitSlice);
*numr += &one;
assert_eq!(numr, &nums[2] as &BitSlice);

Gives write access to all elements in the underlying storage, including the partially-filled tail element (if present).

Accesses the underlying store.

Examples
use bitvec::*;
let mut bv: BitVec = bitvec![0, 0, 0, 0, 0, 0, 0, 0, 1];
for elt in bv.as_mut() {
  *elt += 2;
}
assert_eq!(&[2, 130], bv.as_ref());

Gives read access to all elements in the underlying storage, including the partially-filled tail element (if present).

Accesses the underlying store.

Examples
use bitvec::*;
let bv = bitvec![0, 0, 0, 0, 0, 0, 0, 0, 1];
let bref: &BitSlice = &bv;
assert_eq!(&[0, 0b1000_0000], bref.as_ref());

Performs the Boolean AND operation against another bitstream and writes the result into self. If the other bitstream ends before self does, it is extended with zero, clearing all remaining bits in self.

ANDs a bitstream into a slice.

Examples
use bitvec::*;
let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1];
let rhs                =      bitvec![0, 0, 1, 1];
*lhs &= rhs;
assert_eq!("000100", &format!("{}", lhs));

Performs the Boolean OR operation against another bitstream and writes the result into self. If the other bitstream ends before self does, it is extended with zero, leaving all remaining bits in self as they were.

ORs a bitstream into a slice.

Examples
use bitvec::*;
let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1];
let rhs                =      bitvec![0, 0, 1, 1];
*lhs |= rhs;
assert_eq!("011101", &format!("{}", lhs));

Performs the Boolean XOR operation against another bitstream and writes the result into self. If the other bitstream ends before self does, it is extended with zero, leaving all remaining bits in self as they were.

XORs a bitstream into a slice.

Examples
use bitvec::*;
let lhs: &mut BitSlice = &mut bitvec![0, 1, 0, 1, 0, 1];
let rhs                =      bitvec![0, 0, 1, 1];
*lhs ^= rhs;
assert_eq!("011001", &format!("{}", lhs));

Signifies that BitSlice is the borrowed form of BitVec.

Borrows the BitVec as a BitSlice.

Examples
use bitvec::*;
use std::borrow::Borrow;
let bv = bitvec![0; 8];
let bref: &BitSlice = bv.borrow();
assert!(!bref.get(7));

Signifies that BitSlice is the borrowed form of BitVec.

Mutably borrows the BitVec as a BitSlice.

Examples
use bitvec::*;
use std::borrow::BorrowMut;
let mut bv = bitvec![0; 8];
let bref: &mut BitSlice = bv.borrow_mut();
assert!(!bref.get(7));
bref.set(7, true);
assert!(bref.get(7));

Prints the BitSlice for debugging.

The output is of the form BitSlice<C, T> [ELT, *] where <C, T> is the endianness and element type, with square brackets on each end of the bits and all the elements of the array printed in binary. The printout is always in semantic order, and may not reflect the underlying buffer. To see the underlying buffer, use .as_ref().

The alternate character {:#?} prints each element on its own line, rather than having all elements on the same line.

Renders the BitSlice type header and contents for debug.

Examples
use bitvec::*;
let bits: &BitSlice<LittleEndian, u16> = &bitvec![
  LittleEndian, u16;
  0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1,
  0, 1
];
assert_eq!(
    "BitSlice<LittleEndian, u16> [0101000011110101, 01]",
    &format!("{:?}", bits)
);

Prints the BitSlice for displaying.

This prints each element in turn, formatted in binary in semantic order (so the first bit seen is printed first and the last bit seen is printed last). Each element of storage is separated by a space for ease of reading.

The alternate character {:#} prints each element on its own line.

To see the in-memory representation, use .as_ref() to get access to the raw elements and print that slice instead.

Renders the BitSlice contents for display.

Examples
use bitvec::*;
let bits: &BitSlice = &bitvec![0, 1, 0, 0, 1, 0, 1, 1, 0, 1];
assert_eq!("01001011 01", &format!("{}", bits));

Builds a BitSlice from a slice of elements. The resulting BitSlice will always completely fill the original slice, and will not have a partial tail.

Wraps an &[T: Bits] in an &BitSlice<C: Cursor, T>. The endianness must be specified by the call site. The element type cannot be changed.

Examples
use bitvec::*;
let src = vec![1u8, 2, 3];
let borrow: &[u8] = &src;
let bits: &BitSlice<BigEndian, _> = borrow.into();
assert_eq!(bits.len(), 24);
assert_eq!(bits.elts(), 3);
assert_eq!(bits.bits(), 0);
assert!(bits.get(7));  // src[0] == 0b0000_0001
assert!(bits.get(14)); // src[1] == 0b0000_0010
assert!(bits.get(22)); // src[2] == 0b0000_0011
assert!(bits.get(23));

Copies a BitSlice into an owned BitVec.

The idiomatic BitSlice to BitVec conversion is BitSlice::to_owned, but just as &[T].into() yields a Vec, &BitSlice.into() yields a BitVec.

Converts to this type from the input type.

Builds a mutable BitSlice from a slice of mutable elements. The resulting BitSlice will always completely fill the original slice, and will not have a partial tail.

Wraps an &mut [T: Bits] in an &mut BitSlice<C: Cursor, T>. The endianness must be specified by the call site. The element type cannot be changed.

Examples
use bitvec::*;
let mut src = vec![1u8, 2, 3];
let borrow: &mut [u8] = &mut src;
let bits: &mut BitSlice<LittleEndian, _> = borrow.into();
//  The first bit read is the LSb of the first element, which is set.
assert!(bits.get(0));
bits.set(0, false);
assert!(!bits.get(0));

Writes the contents of the BitSlice, in semantic bit order, into a hasher.

Writes each bit of the BitSlice, as a full bool, into the hasher.

Indexes a single bit by element and bit index within the element. The element index must be less than the length of the underlying store, and the bit index must be less than the width of the underlying element.

This index is not recommended for public use.

Looks up a single bit by storage element and bit indices. The bit index is still a semantic count, not an absolute index into the element.

Examples
use bitvec::*;
let mut bv = bitvec![0; 10];
bv.push(true);
let bits: &BitSlice = &bv;
assert!(bits[(1, 2)]); // 10
assert!(!bits[(1, 1)]); // 9
The returned type after indexing.

Indexes a single bit by semantic count. The index must be less than the length of the BitSlice.

Looks up a single bit by semantic count.

Examples
use bitvec::*;
let bv = bitvec![0, 0, 1, 0, 0];
let bits: &BitSlice = &bv;
assert!(bits[2]);
assert!(!bits[3]);
The returned type after indexing.

Produces a read-only iterator over all the bits in the BitSlice.

This iterator follows the ordering in the BitSlice type, and implements ExactSizeIterator as BitSlice has a known, fixed length, and DoubleEndedIterator as it has known ends.

Iterates over the slice.

Examples
use bitvec::*;
let bv = bitvec![1, 0, 1, 0, 1, 1, 0, 0];
let bref: &BitSlice = &bv;
let mut count = 0;
for bit in bref {
    if bit { count += 1; }
}
assert_eq!(count, 4);
The type of the elements being iterated over.
Which kind of iterator are we turning this into?

Performs fixed-width 2’s-complement negation of a BitSlice.

Unlike the ! operator (Not trait), the unary - operator treats the BitSlice as if it represents a signed 2’s-complement integer of fixed width. The negation of a number in 2’s complement is defined as its inversion (using !) plus one, and on fixed-width numbers has the following discontinuities:

  • A slice whose bits are all zero is considered to represent the number zero which negates as itself.
  • A slice whose bits are all one is considered to represent the most negative number, which has no correpsonding positive number, and thus negates as zero.

This behavior was chosen so that all possible values would have some output, and so that repeated application converges at idempotence. The most negative input can never be reached by negation, but --MOST_NEG converges at the least unreasonable fallback value, 0.

Because BitSlice cannot move, the negation is performed in place.

Perform 2’s-complement fixed-width negation.

Examples

The contortions shown here are a result of this operator applying to a mutable reference, and this example balancing access to the original BitVec for comparison with aquiring a mutable borrow as a slice to ensure that the BitSlice implementation is used, not the BitVec.

Negate an arbitrary positive number (first bit unset).

use bitvec::*;
let mut num = bitvec![0, 1, 1, 0];
- (&mut num as &mut BitSlice);
assert_eq!(num, bitvec![1, 0, 1, 0]);

Negate an arbitrary negative number. This example will use the above result to demonstrate round-trip correctness.

use bitvec::*;
let mut num = bitvec![1, 0, 1, 0];
- (&mut num as &mut BitSlice);
assert_eq!(num, bitvec![0, 1, 1, 0]);

Negate the most negative number, which will become zero, and show convergence at zero.

use bitvec::*;
let zero = bitvec![0; 10];
let mut num = bitvec![1; 10];
- (&mut num as &mut BitSlice);
assert_eq!(num, zero);
- (&mut num as &mut BitSlice);
assert_eq!(num, zero);
The resulting type after applying the - operator.

Flips all bits in the slice, in place.

This invokes the ! operator on each element of the borrowed storage, and so it will also flip bits in the tail that are outside the BitSlice length if any. Use ^= repeat(true) to flip only the bits actually inside the BitSlice purview. ^= also has the advantage of being a borrowing operator rather than a consuming/returning operator.

Inverts all bits in the slice.

Examples
use bitvec::*;
let mut bv = bitvec![0; 10];
let bits: &mut BitSlice = &mut bv;
let new_bits = !bits;
//  The `bits` binding is consumed by the `!` operator, and a new reference
//  is returned.
// assert_eq!(bits.as_ref(), &[!0, !0]);
assert_eq!(new_bits.as_ref(), &[!0, !0]);
The resulting type after applying the ! operator.
This method returns an Ordering between self and other. Read more

Tests if two BitSlices are semantically — not bitwise — equal.

It is valid to compare two slices of different endianness or element types.

The equality condition requires that they have the same number of total bits and that each pair of bits in semantic order are identical.

Performs a comparison by ==.

Examples
use bitvec::*;
let l: BitVec<LittleEndian, u16> = bitvec![LittleEndian, u16; 0, 1, 0, 1];
let r: BitVec<BigEndian, u32> = bitvec![BigEndian, u32; 0, 1, 0, 1];

let ls: &BitSlice<_, _> = &l;
let rs: &BitSlice<_, _> = &r;
assert!(ls == rs);
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more

Compares two BitSlices by semantic — not bitwise — ordering.

The comparison sorts by testing each index for one slice to have a set bit where the other has an unset bit. If the slices are different, the slice with the set bit sorts greater than the slice with the unset bit.

If one of the slices is exhausted before they differ, the longer slice is greater.

Performs a comparison by < or >.

Examples
use bitvec::*;
let a = bitvec![0, 1, 0, 0];
let b = bitvec![0, 1, 0, 1];
let c = bitvec![0, 1, 0, 1, 1];
let aref: &BitSlice = &a;
let bref: &BitSlice = &b;
let cref: &BitSlice = &c;
assert!(aref < bref);
assert!(bref < cref);
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

Shifts all bits in the array to the left — DOWN AND TOWARDS THE FRONT.

On primitives, the left-shift operator << moves bits away from the origin and towards the ceiling. This is because we label the bits in a primitive with the minimum on the right and the maximum on the left, which is big-endian bit order. This increases the value of the primitive being shifted.

THAT IS NOT HOW BitSlice WORKS!

BitSlice defines its layout with the minimum on the left and the maximum on the right! Thus, left-shifting moves bits towards the minimum.

In BigEndian order, the effect in memory will be what you expect the << operator to do.

In LittleEndian order, the effect will be equivalent to using >> on the primitives in memory!

Notes

In order to preserve the effecs in memory that this operator traditionally expects, the bits that are emptied by this operation are zeroed rather than left to their old value.

The shift amount is modulated against the array length, so it is not an error to pass a shift amount greater than the array length.

A shift amount of zero is a no-op, and returns immediately.

Shifts a slice left, in place.

Examples
use bitvec::*;
let mut bv = bitvec![1, 1, 1, 0, 0, 0, 0, 0, 1];
let bits: &mut BitSlice = &mut bv;
*bits <<= 3;
assert_eq!("00000100 0", &format!("{}", bits));
//               ^ former tail

Shifts all bits in the array to the right — UP AND TOWARDS THE BACK.

On primitives, the right-shift operator >> moves bits towards the origin and away from the ceiling. This is because we label the bits in a primitive with the minimum on the right and the maximum on the left, which is big-endian bit order. This decreases the value of the primitive being shifted.

THAT IS NOT HOW BitSlice WORKS!

BitSlice defines its layout with the minimum on the left and the maximum on the right! Thus, right-shifting moves bits towards the maximum.

In Big-Endian order, the effect in memory will be what you expect the >> operator to do.

In LittleEndian order, the effect will be equivalent to using << on the primitives in memory!

Notes

In order to preserve the effects in memory that this operator traditionally expects, the bits that are emptied by this operation are zeroed rather than left to their old value.

The shift amount is modulated against the array length, so it is not an error to pass a shift amount greater than the array length.

A shift amount of zero is a no-op, and returns immediately.

Shifts a slice right, in place.

Examples
use bitvec::*;
let mut bv = bitvec![1, 0, 0, 0, 0, 0, 1, 1, 1];
let bits: &mut BitSlice = &mut bv;
*bits >>= 3;
assert_eq!("00010000 0", &format!("{}", bits));
//             ^ former head

Creates a new BitVec out of a BitSlice.

Clones a borrowed BitSlice into an owned BitVec.

Examples
use bitvec::*;
let src = bitvec![0; 5];
let src_ref: &BitSlice = &src;
let dst = src_ref.to_owned();
assert_eq!(src, dst);
The resulting type after obtaining ownership.
Uses borrowed data to replace owned data, usually by cloning. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.