#[repr(C, packed)]
pub struct BitPtr<M = Const, T = usize, O = Lsb0> where
    M: Mutability,
    T: BitStore,
    O: BitOrder
{ /* private fields */ }
Expand description

Single-Bit Pointer

This structure defines a pointer to exactly one bit in a memory element. It is a structure, rather than an encoding of a *Bit raw pointer, because it contains more information than can be packed into such a pointer. Furthermore, it can uphold the same requirements and guarantees that the rest of the crate demands, whereäs a raw pointer cannot.

Original

*bool and NonNull<bool>

API Differences

Since raw pointers are not sufficient in space or guarantees, and are limited by not being marked #[fundamental], this is an ordinary struct. Because it cannot use the *const/*mut distinction that raw pointers and references can, this encodes mutability in a type parameter instead.

In order to be consistent with the rest of the crate, particularly the *BitSlice encoding, this enforces that all T element addresses are well-aligned to T and non-null. While this type is used in the API as an analogue of raw pointers, it is restricted in value to only contain the values of valid references to memory, not arbitrary pointers.

ABI Differences

This is aligned to 1, rather than the processor word, in order to enable some crate-internal space optimizations.

Type Parameters

  • M: Marks whether the pointer has mutability permissions to the referent memory. Only Mut pointers can be used to create &mut references.
  • T: A memory type used to select both the register width and the bus behavior when performing memory accesses.
  • O: The ordering of bits within a memory element.

Usage

This structure is used as the bitvec equivalent to *bool. It is used in all raw-pointer APIs and provides behavior to emulate raw pointers. It cannot be directly dereferenced, as it is not a pointer; it can only be transformed back into higher referential types, or used in functions that accept it.

These pointers can never be null or misaligned.

Safety

Rust and LLVM do not have a concept of bit-level initialization yet. Furthermore, the underlying foundational code that this type uses to manipulate individual bits in memory relies on construction of shared references to memory, which means that unlike standard pointers, the T element to which BitPtr values point must always be already initialized in your program context.

bitvec is not able to detect or enforce this requirement, and is currently not able to avoid it. See BitAccess for more information.

Implementations

The canonical dangling pointer. This selects the starting bit of the canonical dangling pointer for T.

Tries to construct a BitPtr from a memory location and a bit index.

Parameters
  • ptr: The address of a memory element. Address wraps raw pointers or references, and enforces that they are not null. BitPtr additionally requires that the address be well-aligned to its type; misaligned addresses cause this to return an error.
  • bit: The index of the selected bit within *ptr.
Returns

This returns an error if ptr is not aligned to T; otherwise, it returns a new bit-pointer structure to the given element and bit.

You should typically prefer to use constructors that take directly from a memory reference or pointer, such as the TryFrom<*T> implementations, the From<&/mut T> implementations, or the ::from_ref(), ::from_mut(), ::from_slice(), or ::from_slice_mut() functions.

Constructs a BitPtr from an address and head index, without checking the address for validity.

Parameters
  • addr: The memory address to use in the bit-pointer. See the Safety section.
  • head: The index of the bit in *addr that this bit-pointer selects.
Returns

A new bit-pointer composed of the parameters. No validity checking is performed.

Safety

The Address type imposes a non-null requirement. BitPtr additionally requires that addr is well-aligned for T, and presumes that the caller has ensured this with bv_ptr::check_alignment. If this is not the case, then the program is incorrect, and subsequent behavior is not specified.

Gets the address of the base storage element.

Gets the BitIdx that selects the bit within the memory element.

Decomposes a bit-pointer into its element address and bit index.

Parameters
  • self
Returns
  • .0: The memory address in which the referent bit is located.
  • .1: The index of the referent bit in *.0 according to the O type parameter.

Removes write permissions from a bit-pointer.

Adds write permissions to a bit-pointer.

Safety

This pointer must have been derived from a *mut pointer.

Constructs a BitPtr to the zeroth bit in a single element.

Constructs a BitPtr to the zeroth bit in the zeroth element of a slice.

This method is distinct from Self::from_ref(&elem[0]), because it ensures that the returned bit-pointer has provenance over the entire slice. Indexing within a slice narrows the provenance range, and makes departure from the subslice, even within the original slice, illegal.

Gets a raw pointer to the memory element containing the selected bit.

Constructs a mutable BitPtr to the zeroth bit in a single element.

Constructs a BitPtr to the zeroth bit in the zeroth element of a mutable slice.

This method is distinct from Self::from_mut(&mut elem[0]), because it ensures that the returned bit-pointer has provenance over the entire slice. Indexing within a slice narrows the provenance range, and makes departure from the subslice, even within the original slice, illegal.

Constructs a mutable BitPtr to the zeroth bit in the zeroth element of a slice.

This method is distinct from Self::from_mut(&mut elem[0]), because it ensures that the returned bit-pointer has provenance over the entire slice. Indexing within a slice narrows the provenance range, and makes departure from the subslice, even within the original slice, illegal.

Gets a raw pointer to the memory location containing the selected bit.

Port of the *bool inherent API.

👎 Deprecated:

BitPtr is never null

Tests if a bit-pointer is the null value.

This is always false, as a BitPtr is a NonNull internally. Use Option<BitPtr> to express the potential for a null pointer.

Original

pointer::is_null

Casts to a BitPtr with a different storage parameter.

This is not free! In order to maintain value integrity, it encodes a BitSpan encoded descriptor with its value, casts that, then decodes into a BitPtr of the target type. If T and U have different ::Mem associated types, then this may change the selected bit in memory. This is an unavoidable cost of the addressing and encoding schemes.

Original

pointer::cast

Decomposes a bit-pointer into its address and head-index components.

Original

pointer::to_raw_parts

API Differences

The original method is unstable as of 1.54.0; however, because BitPtr already has a similar API, the name is optimistically stabilized here. Prefer .raw_parts() until the original inherent stabilizes.

Produces a proxy reference to the referent bit.

Because BitPtr guarantees that it is non-null and well-aligned, this never returns None. However, this is still unsafe to call on any bit-pointers created from conjured values rather than known references.

Original

pointer::as_ref

API Differences

This produces a proxy type rather than a true reference. The proxy implements Deref<Target = bool>, and can be converted to &bool with a reborrow &*.

Safety

Since BitPtr does not permit null or misaligned pointers, this method will always dereference the pointer in order to create the proxy. As such, you must ensure the following conditions are met:

  • the pointer must be dereferenceable as defined in the standard library documentation
  • the pointer must point to an initialized instance of T
  • you must ensure that no other pointer will race to modify the referent location while this call is reading from memory to produce the proxy
Examples
use bitvec::prelude::*;

let data = 1u8;
let ptr = BitPtr::<_, _, Lsb0>::from_ref(&data);
let val = unsafe { ptr.as_ref() }.unwrap();
assert!(*val);

Creates a new bit-pointer at a specified offset from the original.

count is in units of bits.

Original

pointer::offset

Safety

BitPtr is implemented with Rust raw pointers internally, and is subject to all of Rust’s rules about provenance and permission tracking. You must abide by the safety rules established in the original method, to which this internally delegates.

Additionally, bitvec imposes its own rules: while Rust cannot observe provenance beyond an element or byte level, bitvec demands that &mut BitSlice have exclusive view over all bits it observes. You must not produce a bit-pointer that departs a BitSlice region and intrudes on any &mut BitSlice’s handle, and you must not produce a write-capable bit-pointer that intrudes on a &BitSlice handle that expects its contents to be immutable.

Note that it is illegal to construct a bit-pointer that invalidates any of these rules. If you wish to defer safety-checking to the point of dereferencing, and allow the temporary construction but not dereference of illegal BitPtrs, use .wrapping_offset() instead.

Examples
use bitvec::prelude::*;

let data = 5u8;
let ptr = BitPtr::<_, _, Lsb0>::from_ref(&data);
unsafe {
  assert!(ptr.read());
  assert!(!ptr.offset(1).read());
  assert!(ptr.offset(2).read());
}

Creates a new bit-pointer at a specified offset from the original.

count is in units of bits.

Original

pointer::wrapping_offset

API Differences

bitvec makes it explicitly illegal to wrap a pointer around the high end of the address space, because it is incapable of representing a null pointer.

However, <*T>::wrapping_offset has additional properties as a result of its tolerance for wrapping the address space: it tolerates departing a provenance region, and is not unsafe to use to create a bit-pointer that is outside the bounds of its original provenance.

Safety

This function is safe to use because the bit-pointers it creates defer their provenance checks until the point of dereference. As such, you can safely use this to perform arbitrary pointer arithmetic that Rust considers illegal in ordinary arithmetic, as long as you do not dereference the bit-pointer until it has been brought in bounds of the originating provenance region.

This means that, to the Rust rule engine, let z = x.wrapping_add(y as usize).wrapping_sub(x as usize); is not equivalent to y, but z is safe to construct, and z.wrapping_add(x as usize).wrapping_sub(y as usize) produces a bit-pointer that is equivalent to x.

See the documentation of the original method for more details about provenance regions, and the distinctions that the optimizer makes about them.

Examples
use bitvec::prelude::*;

let data = 0u32;
let mut ptr = BitPtr::<_, _, Lsb0>::from_ref(&data);
let end = ptr.wrapping_offset(32);
while ptr < end {
  println!("{}", unsafe { ptr.read() });
  ptr = ptr.wrapping_offset(3);
}

Calculates the distance (in bits) between two bit-pointers.

This method is the inverse of .offset().

Original

pointer::offset_from

API Differences

The base pointer may have a different BitStore type parameter, as long as they share an underlying memory type. This is necessary in order to accommodate aliasing markers introduced between when an origin pointer was taken and when self compared against it.

Safety

Both self and origin must be drawn from the same provenance region. This means that they must be created from the same Rust allocation, whether with let or the allocator API, and must be in the (inclusive) range base ..= base + len. The first bit past the end of a region can be addressed, just not dereferenced.

See the original <*T>::offset_from for more details on region safety.

Examples
use bitvec::prelude::*;

let data = 0u32;
let base = BitPtr::<_, _, Lsb0>::from_ref(&data);
let low = unsafe { base.add(10) };
let high = unsafe { low.add(15) };
unsafe {
  assert_eq!(high.offset_from(low), 15);
  assert_eq!(low.offset_from(high), -15);
  assert_eq!(low.offset(15), high);
  assert_eq!(high.offset(-15), low);
}

While this method is safe to construct bit-pointers that depart a provenance region, it remains illegal to dereference those pointers!

This usage is incorrect, and a program that contains it is not well-formed.

use bitvec::prelude::*;

let a = 0u8;
let b = !0u8;

let a_ptr = BitPtr::<_, _, Lsb0>::from_ref(&a);
let b_ptr = BitPtr::<_, _, Lsb0>::from_ref(&b);
let diff = (b_ptr.pointer() as isize)
  .wrapping_sub(a_ptr.pointer() as isize)
  // Remember: raw pointers are byte-stepped,
  // but bit-pointers are bit-stepped.
  .wrapping_mul(8);
// This pointer to `b` has `a`’s provenance:
let b_ptr_2 = a_ptr.wrapping_offset(diff);

// They are *arithmetically* equal:
assert_eq!(b_ptr, b_ptr_2);
// But it is still undefined behavior to cross provenances!
assert_eq!(0, unsafe { b_ptr_2.offset_from(b_ptr) });

Adjusts a bit-pointer upwards in memory. This is equivalent to .offset(count as isize).

count is in units of bits.

Original

pointer::add

Safety

See .offset().

Adjusts a bit-pointer downwards in memory. This is equivalent to .offset((count as isize).wrapping_neg()).

count is in units of bits.

Original

pointer::sub

Safety

See .offset().

Adjusts a bit-pointer upwards in memory, using wrapping semantics. This is equivalent to .wrapping_offset(count as isize).

count is in units of bits.

Original

pointer::wrapping_add

Safety

See .wrapping_offset().

Adjusts a bit-pointer downwards in memory, using wrapping semantics. This is equivalent to .wrapping_offset((count as isize).wrapping_neg()).

count is in units of bits.

Original

pointer::wrapping_add

Safety

See .wrapping_offset().

Reads the bit from *self.

Original

pointer::read

Safety

See ptr::read.

Reads the bit from *self using a volatile load.

Prefer using a crate such as voladdress to manage volatile I/O and use bitvec only on the local objects it provides. Individual I/O operations for individual bits are likely not the behavior you want.

Original

pointer::read_volatile

Safety

See ptr::read_volatile.

👎 Deprecated:

BitPtr does not have unaligned addresses

Reads the bit from *self using an unaligned memory access.

BitPtr forbids unaligned addresses. If you have such an address, you must perform your memory accesses on the raw element, and only use bitvec on a well-aligned stack temporary. This method should never be necessary.

Original

pointer::read_unaligned

Safety

See ptr::read_unaligned

Copies count bits from self to dest. The source and destination may overlap.

Note that overlap is only defined when O and O2 are the same type. If they differ, then bitvec does not define overlap, and assumes that they are wholly discrete in memory.

Original

pointer::copy_to

Safety

See ptr::copy.

Copies count bits from self to dest. The source and destination may not overlap.

Original

pointer::copy_to_nonoverlapping

Safety

See ptr::copy_nonoverlapping.

Computes the offset (in bits) that needs to be applied to the bit-pointer in order to make it aligned to the given byte alignment.

“Alignment” here means that the bit-pointer selects the starting bit of a memory location whose address satisfies the requested alignment.

align is measured in bytes. If you wish to align your bit-pointer to a specific fraction (½, ¼, or ⅛ of one byte), please file an issue and I will work on adding this functionality.

Original

pointer::align_offset

Notes

If the base-element address of the bit-pointer is already aligned to align, then this will return the bit-offset required to select the first bit of the successor element.

If it is not possible to align the bit-pointer, then the implementation returns usize::MAX.

The return value is measured in bits, not T elements or bytes. The only thing you can do with it is pass it into .add() or .wrapping_add().

Note from the standard library: It is permissible for the implementation to always return usize::MAX. Only your algorithm’s performance can depend on getting a usable offset here; it must be correct independently of this function providing a useful value.

Safety

There are no guarantees whatsoëver that offsetting the bit-pointer will not overflow or go beyond the allocation that the bit-pointer selects. It is up to the caller to ensure that the returned offset is correct in all terms other than alignment.

Panics

This method panics if align is not a power of two.

Examples
use bitvec::prelude::*;

let data = [0u8; 3];
let ptr = BitPtr::<_, _, Lsb0>::from_slice(&data);
let ptr = unsafe { ptr.add(2) };
let count = ptr.align_offset(2);
assert!(count >= 6);

Port of the *mut bool inherent API.

Produces a proxy reference to the referent bit.

Because BitPtr guarantees that it is non-null and well-aligned, this never returns None. However, this is still unsafe to call on any bit-pointers created from conjured values rather than known references.

Original

pointer::as_mut

API Differences

This produces a proxy type rather than a true reference. The proxy implements DerefMut<Target = bool>, and can be converted to &mut bool with a reborrow &mut *.

Writes to the proxy are not reflected in the proxied location until the proxy is destroyed, either through Drop or its .commit() method.

Safety

Since BitPtr does not permit null or misaligned pointers, this method will always dereference the pointer in order to create the proxy. As such, you must ensure the following conditions are met:

  • the pointer must be dereferenceable as defined in the standard library documentation
  • the pointer must point to an initialized instance of T
  • you must ensure that no other pointer will race to modify the referent location while this call is reading from memory to produce the proxy
  • you must ensure that no other bitvec handle targets the referent bit
Examples
use bitvec::prelude::*;

let mut data = 0u8;
let ptr = BitPtr::<_, _, Lsb0>::from_mut(&mut data);
let mut val = unsafe { ptr.as_mut() }.unwrap();
assert!(!*val);
*val = true;
assert!(*val);

Copies count bits from the region starting at src to the region starting at self.

The regions are free to overlap; the implementation will detect overlap and correctly avoid it.

Note: this has the opposite argument order from ptr::copy: self is the destination, not the source.

Original

pointer::copy_from

Safety

See ptr::copy.

Copies count bits from the region starting at src to the region starting at self.

Unlike .copy_from(), the two regions may not overlap; this method does not attempt to detect overlap and thus may have a slight performance boost over the overlap-handling .copy_from().

Note: this has the opposite argument order from ptr::copy_nonoverlapping: self is the destination, not the source.

Original

pointer::copy_from_nonoverlapping

Safety

See ptr::copy_nonoverlapping.

👎 Deprecated:

this has no effect, and should not be called

Runs the destructor of the referent value.

bool has no destructor; this function does nothing.

Original

pointer::drop_in_place

Safety

See ptr::drop_in_place.

Writes a new bit into the given location.

Original

pointer::write

Safety

See ptr::write.

Writes a new bit using volatile I/O operations.

Because processors do not generally have single-bit read or write instructions, this must perform a volatile read of the entire memory location, perform the write locally, then perform another volatile write to the entire location. These three steps are guaranteed to be sequential with respect to each other, but are not guaranteed to be atomic.

Volatile operations are intended to act on I/O memory, and are only guaranteed not to be elided or reördered by the compiler across other I/O operations.

You should not use bitvec to act on volatile memory. You should use a crate specialized for volatile I/O work, such as voladdr, and use it to explicitly manage the I/O and ask it to perform bitvec work only on the local snapshot of a volatile location.

Original

pointer::write_volatile

Safety

See ptr::write_volatile.

👎 Deprecated:

BitPtr does not have unaligned addresses

Writes a bit into memory, tolerating unaligned addresses.

BitPtr does not have unaligned addresses. BitPtr itself is capable of operating on misaligned addresses, but elects to disallow use of them in keeping with the rest of bitvec’s requirements.

Original

pointer::write_unaligned

Safety

See ptr::write_unaligned.

Replaces the bit at *self with a new value, returning the previous value.

Original

pointer::replace

Safety

See ptr::replace.

Swaps the bits at two mutable locations.

Original

pointer::swap

Safety

See ptr::swap.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Converts to this type from the input type.

Converts to this type from the input type.

Feeds this value into the given Hasher. Read more

Feeds a slice of this type into the given Hasher. Read more

This method returns an Ordering between self and other. Read more

Compares and returns the maximum of two values. Read more

Compares and returns the minimum of two values. Read more

Restrict a value to a certain interval. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method returns an ordering between self and other values if one exists. Read more

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

Formats the value using the given formatter.

Start index bound. Read more

End index bound. Read more

Returns true if item is contained in the range. 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.

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

Converts self into T using Into<T>. Read more

Causes self to use its Binary implementation when Debug-formatted. Read more

Causes self to use its Display implementation when Debug-formatted. Read more

Causes self to use its LowerExp implementation when Debug-formatted. Read more

Causes self to use its LowerHex implementation when Debug-formatted. Read more

Causes self to use its Octal implementation when Debug-formatted. Read more

Causes self to use its Pointer implementation when Debug-formatted. Read more

Causes self to use its UpperExp implementation when Debug-formatted. Read more

Causes self to use its UpperHex implementation when Debug-formatted. Read more

Formats each item in a sequence. 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.

Pipes by value. This is generally the method you want to use. Read more

Borrows self and passes that borrow into the pipe function. Read more

Mutably borrows self and passes that borrow into the pipe function. Read more

Borrows self, then passes self.borrow() into the pipe function. Read more

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more

Borrows self, then passes self.as_ref() into the pipe function.

Mutably borrows self, then passes self.as_mut() into the pipe function. Read more

Borrows self, then passes self.deref() into the pipe function.

Mutably borrows self, then passes self.deref_mut() into the pipe function. Read more

Immutable access to a value. Read more

Mutable access to a value. Read more

Immutable access to the Borrow<B> of a value. Read more

Mutable access to the BorrowMut<B> of a value. Read more

Immutable access to the AsRef<R> view of a value. Read more

Mutable access to the AsMut<R> view of a value. Read more

Immutable access to the Deref::Target of a value. Read more

Mutable access to the Deref::Target of a value. Read more

Calls .tap() only in debug builds, and is erased in release builds.

Calls .tap_mut() only in debug builds, and is erased in release builds. Read more

Calls .tap_borrow() only in debug builds, and is erased in release builds. Read more

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds. Read more

Calls .tap_ref() only in debug builds, and is erased in release builds. Read more

Calls .tap_ref_mut() only in debug builds, and is erased in release builds. Read more

Calls .tap_deref() only in debug builds, and is erased in release builds. Read more

Calls .tap_deref_mut() only in debug builds, and is erased in release builds. Read more

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

Uses borrowed data to replace owned data, usually by cloning. Read more

Attempts to convert self into T using TryInto<T>. 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.