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 specifiedBits
except 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_pattern
returns true, then the bit pattern contained inbits
must 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
.