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
Selfmust have the same layout as the specifiedBitsexcept for the possible invalid bit patterns being checked duringis_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_patternreturns true, then the bit pattern contained inbitsmust also be valid for an instance ofSelf. - Probably more, don’t mess it up (I mean it 2.0)
Required Associated Types§
Sourcetype Bits: AnyBitPattern
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§
Sourcefn is_valid_bit_pattern(bits: &Self::Bits) -> bool
fn is_valid_bit_pattern(bits: &Self::Bits) -> bool
If this function returns true, then it must be valid to reinterpret bits
as &Self.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.