pub unsafe trait CheckedBitPattern: Copy {
    type Bits: AnyBitPattern;

    // Required method
    fn is_valid_bit_pattern(bits: &Self::Bits) -> bool;
}
Expand description

A marker trait that allows types that have some invalid bit patterns to be used in places that otherwise require AnyBitPattern or Pod types by performing a runtime check on a perticular set of bits. This is particularly useful for types like fieldless (‘C-style’) enums, char, bool, and structs containing them.

To do this, we define a Bits type which is a type with equivalent layout to Self other than the invalid bit patterns which disallow Self from being AnyBitPattern. This Bits type must itself implement AnyBitPattern. Then, we implement a function that checks whether a certain instance of the Bits is also a valid bit pattern of Self. If this check passes, then we can allow casting from the Bits to Self (and therefore, any type which is able to be cast to Bits is also able to be cast to Self).

AnyBitPattern is a subset of CheckedBitPattern, meaning that any T: AnyBitPattern is also CheckedBitPattern. This means you can also use any AnyBitPattern type in the checked versions of casting functions in this module. If it’s possible, prefer implementing AnyBitPattern for your type directly instead of CheckedBitPattern as it gives greater flexibility.

Derive

A #[derive(CheckedBitPattern)] macro is provided under the derive feature flag which will automatically validate the requirements of this trait and implement the trait for you for both enums and structs. This is the recommended method for implementing the trait, however it’s also possible to do manually.

Example

If manually implementing the trait, we can do something like so:

use bytemuck::{CheckedBitPattern, NoUninit};

#[repr(u32)]
#[derive(Copy, Clone)]
enum MyEnum {
    Variant0 = 0,
    Variant1 = 1,
    Variant2 = 2,
}

unsafe impl CheckedBitPattern for MyEnum {
    type Bits = u32;

    fn is_valid_bit_pattern(bits: &u32) -> bool {
        match *bits {
            0 | 1 | 2 => true,
            _ => false,
        }
    }
}

// It is often useful to also implement `NoUninit` on our `CheckedBitPattern` types.
// This will allow us to do casting of mutable references (and mutable slices).
// It is not always possible to do so, but in this case we have no padding so it is.
unsafe impl NoUninit for MyEnum {}

We can now use relevant casting functions. For example,

use bytemuck::{bytes_of, bytes_of_mut};
use bytemuck::checked;

let bytes = bytes_of(&2u32);
let result = checked::try_from_bytes::<MyEnum>(bytes);
assert_eq!(result, Ok(&MyEnum::Variant2));

// Fails for invalid discriminant
let bytes = bytes_of(&100u32);
let result = checked::try_from_bytes::<MyEnum>(bytes);
assert!(result.is_err());

// Since we implemented NoUninit, we can also cast mutably from an original type
// that is `NoUninit + AnyBitPattern`:
let mut my_u32 = 2u32;
{
  let as_enum_mut = checked::cast_mut::<_, MyEnum>(&mut my_u32);
  assert_eq!(as_enum_mut, &mut MyEnum::Variant2);
  *as_enum_mut = MyEnum::Variant0;
}
assert_eq!(my_u32, 0u32);

Safety

  • Self must have the same layout as the specified Bits except for the possible invalid bit patterns being checked during is_valid_bit_pattern.
  • This almost certainly means your type must be #[repr(C)] or a similar specified repr, but if you think you know better, you probably don’t. If you still think you know better, be careful and have fun. And don’t mess it up (I mean it).
  • If is_valid_bit_pattern returns true, then the bit pattern contained in bits must also be valid for an instance of Self.
  • Probably more, don’t mess it up (I mean it 2.0)

Required Associated Types§

source

type Bits: AnyBitPattern

Self must have the same layout as the specified Bits except for the possible invalid bit patterns being checked during is_valid_bit_pattern.

Required Methods§

source

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

If this function returns true, then it must be valid to reinterpret bits as &Self.

Implementations on Foreign Types§

source§

impl CheckedBitPattern for char

§

type Bits = u32

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroU8

§

type Bits = u8

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroU16

§

type Bits = u16

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroU64

§

type Bits = u64

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroI16

§

type Bits = i16

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroI64

§

type Bits = i64

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroU32

§

type Bits = u32

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroI32

§

type Bits = i32

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroU128

source§

impl CheckedBitPattern for NonZeroIsize

source§

impl CheckedBitPattern for NonZeroI128

source§

impl CheckedBitPattern for bool

§

type Bits = u8

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

source§

impl CheckedBitPattern for NonZeroUsize

source§

impl CheckedBitPattern for NonZeroI8

§

type Bits = i8

source§

fn is_valid_bit_pattern(bits: &Self::Bits) -> bool

Implementors§