Trait bytemuck::checked::CheckedBitPattern [−][src]
pub unsafe trait CheckedBitPattern: Copy {
type Bits: AnyBitPattern;
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 wheter 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).
- This almost certainly means your type must be
- 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)
Associated Types
type 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
fn 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.
