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
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).
- This almost certainly means your type must be
- 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)
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
.