mirror of
https://github.com/Lokathor/bytemuck.git
synced 2024-11-22 06:42:25 +00:00
run cargo fmt
(#120)
This commit is contained in:
parent
d75942c484
commit
331762b014
@ -93,11 +93,13 @@ pub fn zeroed_box<T: Zeroable>() -> Box<T> {
|
|||||||
try_zeroed_box().unwrap()
|
try_zeroed_box().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocates a `Vec<T>` of length and capacity exactly equal to `length` and all elements zeroed.
|
/// Allocates a `Vec<T>` of length and capacity exactly equal to `length` and
|
||||||
|
/// all elements zeroed.
|
||||||
///
|
///
|
||||||
/// ## Failure
|
/// ## Failure
|
||||||
///
|
///
|
||||||
/// This fails if the allocation fails, or if a layout cannot be calculated for the allocation.
|
/// This fails if the allocation fails, or if a layout cannot be calculated for
|
||||||
|
/// the allocation.
|
||||||
pub fn try_zeroed_vec<T: Zeroable>(length: usize) -> Result<Vec<T>, ()> {
|
pub fn try_zeroed_vec<T: Zeroable>(length: usize) -> Result<Vec<T>, ()> {
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
@ -121,7 +123,8 @@ pub fn zeroed_vec<T: Zeroable>(length: usize) -> Vec<T> {
|
|||||||
///
|
///
|
||||||
/// ## Failure
|
/// ## Failure
|
||||||
///
|
///
|
||||||
/// This fails if the allocation fails, or if a layout cannot be calculated for the allocation.
|
/// This fails if the allocation fails, or if a layout cannot be calculated for
|
||||||
|
/// the allocation.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_zeroed_slice_box<T: Zeroable>(
|
pub fn try_zeroed_slice_box<T: Zeroable>(
|
||||||
length: usize,
|
length: usize,
|
||||||
@ -145,7 +148,7 @@ pub fn try_zeroed_slice_box<T: Zeroable>(
|
|||||||
let slice =
|
let slice =
|
||||||
unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) };
|
unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) };
|
||||||
Ok(unsafe { Box::<[T]>::from_raw(slice) })
|
Ok(unsafe { Box::<[T]>::from_raw(slice) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// As [`try_zeroed_slice_box`](try_zeroed_slice_box), but unwraps for you.
|
/// As [`try_zeroed_slice_box`](try_zeroed_slice_box), but unwraps for you.
|
||||||
@ -313,12 +316,14 @@ pub fn pod_collect_to_vec<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An extension trait for `TransparentWrapper` and alloc types.
|
/// An extension trait for `TransparentWrapper` and alloc types.
|
||||||
pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
pub trait TransparentWrapperAlloc<Inner: ?Sized>:
|
||||||
|
TransparentWrapper<Inner>
|
||||||
|
{
|
||||||
/// Convert a vec of the inner type into a vec of the wrapper type.
|
/// Convert a vec of the inner type into a vec of the wrapper type.
|
||||||
fn wrap_vec(s: Vec<Inner>) -> Vec<Self>
|
fn wrap_vec(s: Vec<Inner>) -> Vec<Self>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
Inner: Sized
|
Inner: Sized,
|
||||||
{
|
{
|
||||||
let mut s = core::mem::ManuallyDrop::new(s);
|
let mut s = core::mem::ManuallyDrop::new(s);
|
||||||
|
|
||||||
@ -331,11 +336,7 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
|||||||
// * ptr comes from Vec (and will not be double-dropped)
|
// * ptr comes from Vec (and will not be double-dropped)
|
||||||
// * the two types have the identical representation
|
// * the two types have the identical representation
|
||||||
// * the len and capacity fields are valid
|
// * the len and capacity fields are valid
|
||||||
Vec::from_raw_parts(
|
Vec::from_raw_parts(ptr as *mut Self, length, capacity)
|
||||||
ptr as *mut Self,
|
|
||||||
length,
|
|
||||||
capacity
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,10 +352,10 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
|||||||
// A `transmute` doesn't work because the sizes are unspecified.
|
// A `transmute` doesn't work because the sizes are unspecified.
|
||||||
//
|
//
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// * The unsafe contract requires that pointers to Inner and Self
|
// * The unsafe contract requires that pointers to Inner and Self have
|
||||||
// have identical representations
|
// identical representations
|
||||||
// * Box is guaranteed to have representation identical to a
|
// * Box is guaranteed to have representation identical to a (non-null)
|
||||||
// (non-null) pointer
|
// pointer
|
||||||
// * The pointer comes from a box (and thus satisfies all safety
|
// * The pointer comes from a box (and thus satisfies all safety
|
||||||
// requirements of Box)
|
// requirements of Box)
|
||||||
let inner_ptr: *mut Inner = Box::into_raw(s);
|
let inner_ptr: *mut Inner = Box::into_raw(s);
|
||||||
@ -367,7 +368,7 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
|||||||
fn peel_vec(s: Vec<Self>) -> Vec<Inner>
|
fn peel_vec(s: Vec<Self>) -> Vec<Inner>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
Inner: Sized
|
Inner: Sized,
|
||||||
{
|
{
|
||||||
let mut s = core::mem::ManuallyDrop::new(s);
|
let mut s = core::mem::ManuallyDrop::new(s);
|
||||||
|
|
||||||
@ -380,11 +381,7 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
|||||||
// * ptr comes from Vec (and will not be double-dropped)
|
// * ptr comes from Vec (and will not be double-dropped)
|
||||||
// * the two types have the identical representation
|
// * the two types have the identical representation
|
||||||
// * the len and capacity fields are valid
|
// * the len and capacity fields are valid
|
||||||
Vec::from_raw_parts(
|
Vec::from_raw_parts(ptr as *mut Inner, length, capacity)
|
||||||
ptr as *mut Inner,
|
|
||||||
length,
|
|
||||||
capacity
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,10 +397,10 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
|||||||
// A `transmute` doesn't work because the sizes are unspecified.
|
// A `transmute` doesn't work because the sizes are unspecified.
|
||||||
//
|
//
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// * The unsafe contract requires that pointers to Inner and Self
|
// * The unsafe contract requires that pointers to Inner and Self have
|
||||||
// have identical representations
|
// identical representations
|
||||||
// * Box is guaranteed to have representation identical to a
|
// * Box is guaranteed to have representation identical to a (non-null)
|
||||||
// (non-null) pointer
|
// pointer
|
||||||
// * The pointer comes from a box (and thus satisfies all safety
|
// * The pointer comes from a box (and thus satisfies all safety
|
||||||
// requirements of Box)
|
// requirements of Box)
|
||||||
let wrapper_ptr: *mut Self = Box::into_raw(s);
|
let wrapper_ptr: *mut Self = Box::into_raw(s);
|
||||||
|
@ -5,23 +5,25 @@ use crate::{Pod, Zeroable};
|
|||||||
/// The requirements for this is very similar to [`Pod`],
|
/// The requirements for this is very similar to [`Pod`],
|
||||||
/// except that the type can allow uninit (or padding) bytes.
|
/// except that the type can allow uninit (or padding) bytes.
|
||||||
/// This limits what you can do with a type of this kind, but also broadens the
|
/// This limits what you can do with a type of this kind, but also broadens the
|
||||||
/// included types to `repr(C)` `struct`s that contain padding as well as `union`s. Notably, you can only cast
|
/// included types to `repr(C)` `struct`s that contain padding as well as
|
||||||
/// *immutable* references and *owned* values into [`AnyBitPattern`] types, not
|
/// `union`s. Notably, you can only cast *immutable* references and *owned*
|
||||||
/// *mutable* references.
|
/// values into [`AnyBitPattern`] types, not *mutable* references.
|
||||||
///
|
///
|
||||||
/// [`Pod`] is a subset of [`AnyBitPattern`], meaning that any `T: Pod` is also
|
/// [`Pod`] is a subset of [`AnyBitPattern`], meaning that any `T: Pod` is also
|
||||||
/// [`AnyBitPattern`] but any `T: AnyBitPattern` is not necessarily [`Pod`].
|
/// [`AnyBitPattern`] but any `T: AnyBitPattern` is not necessarily [`Pod`].
|
||||||
///
|
///
|
||||||
/// [`AnyBitPattern`] is a subset of [`Zeroable`], meaning that any `T: AnyBitPattern`
|
/// [`AnyBitPattern`] is a subset of [`Zeroable`], meaning that any `T:
|
||||||
/// is also [`Zeroable`], but any `T: Zeroable` is not necessarily [`AnyBitPattern ]
|
/// AnyBitPattern` is also [`Zeroable`], but any `T: Zeroable` is not
|
||||||
|
/// necessarily [`AnyBitPattern ]
|
||||||
///
|
///
|
||||||
/// # Derive
|
/// # Derive
|
||||||
///
|
///
|
||||||
/// A `#[derive(AnyBitPattern)]` macro is provided under the `derive` feature flag which will
|
/// A `#[derive(AnyBitPattern)]` macro is provided under the `derive` feature
|
||||||
/// automatically validate the requirements of this trait and implement the
|
/// flag which will automatically validate the requirements of this trait and
|
||||||
/// trait for you for both structs and enums. This is the recommended method for
|
/// implement the trait for you for both structs and enums. This is the
|
||||||
/// implementing the trait, however it's also possible to do manually. If you
|
/// recommended method for implementing the trait, however it's also possible to
|
||||||
/// implement it manually, you *must* carefully follow the below safety rules.
|
/// do manually. If you implement it manually, you *must* carefully follow the
|
||||||
|
/// below safety rules.
|
||||||
///
|
///
|
||||||
/// * *NOTE: even `C-style`, fieldless enums are intentionally **excluded** from
|
/// * *NOTE: even `C-style`, fieldless enums are intentionally **excluded** from
|
||||||
/// this trait, since it is **unsound** for an enum to have a discriminant value
|
/// this trait, since it is **unsound** for an enum to have a discriminant value
|
||||||
@ -29,22 +31,26 @@ use crate::{Pod, Zeroable};
|
|||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Similar to [`Pod`] except we disregard the rule about it must not contain uninit bytes.
|
/// Similar to [`Pod`] except we disregard the rule about it must not contain
|
||||||
/// Still, this is a quite strong guarantee about a type, so *be careful* when
|
/// uninit bytes. Still, this is a quite strong guarantee about a type, so *be
|
||||||
/// implementing it manually.
|
/// careful* when implementing it manually.
|
||||||
///
|
///
|
||||||
/// * The type must be inhabited (eg: no
|
/// * The type must be inhabited (eg: no
|
||||||
/// [Infallible](core::convert::Infallible)).
|
/// [Infallible](core::convert::Infallible)).
|
||||||
/// * The type must be valid for any bit pattern of its backing memory.
|
/// * The type must be valid for any bit pattern of its backing memory.
|
||||||
/// * Structs need to have all fields also be `AnyBitPattern`.
|
/// * Structs need to have all fields also be `AnyBitPattern`.
|
||||||
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`, atomics, and any
|
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`,
|
||||||
/// other forms of interior mutability.
|
/// atomics, and any other forms of interior mutability.
|
||||||
/// * More precisely: A shared reference to the type must allow reads, and *only* reads. RustBelt's
|
/// * More precisely: A shared reference to the type must allow reads, and
|
||||||
/// separation logic is based on the notion that a type is allowed to define a sharing predicate,
|
/// *only* reads. RustBelt's separation logic is based on the notion that a
|
||||||
/// its own invariant that must hold for shared references, and this predicate is the reasoning
|
/// type is allowed to define a sharing predicate, its own invariant that must
|
||||||
/// that allow it to deal with atomic and cells etc. We require the sharing predicate to be
|
/// hold for shared references, and this predicate is the reasoning that allow
|
||||||
/// trivial and permit only read-only access.
|
/// it to deal with atomic and cells etc. We require the sharing predicate to
|
||||||
|
/// be trivial and permit only read-only access.
|
||||||
/// * There's probably more, don't mess it up (I mean it).
|
/// * There's probably more, don't mess it up (I mean it).
|
||||||
pub unsafe trait AnyBitPattern: Zeroable + Sized + Copy + 'static {}
|
pub unsafe trait AnyBitPattern:
|
||||||
|
Zeroable + Sized + Copy + 'static
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl<T: Pod> AnyBitPattern for T {}
|
unsafe impl<T: Pod> AnyBitPattern for T {}
|
||||||
|
105
src/checked.rs
105
src/checked.rs
@ -1,32 +1,40 @@
|
|||||||
//! Checked versions of the casting functions exposed in crate root
|
//! Checked versions of the casting functions exposed in crate root
|
||||||
//! that support [`CheckedBitPattern`] types.
|
//! that support [`CheckedBitPattern`] types.
|
||||||
|
|
||||||
use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
|
use crate::{
|
||||||
|
internal::{self, something_went_wrong},
|
||||||
|
AnyBitPattern, NoUninit,
|
||||||
|
};
|
||||||
|
|
||||||
/// A marker trait that allows types that have some invalid bit patterns to be used
|
/// A marker trait that allows types that have some invalid bit patterns to be
|
||||||
/// in places that otherwise require [`AnyBitPattern`] or [`Pod`] types by performing
|
/// used in places that otherwise require [`AnyBitPattern`] or [`Pod`] types by
|
||||||
/// a runtime check on a perticular set of bits. This is particularly
|
/// 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.
|
/// 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 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
|
/// to `Self` other than the invalid bit patterns which disallow `Self` from
|
||||||
/// being [`AnyBitPattern`]. This `Bits` type must itself implement [`AnyBitPattern`].
|
/// being [`AnyBitPattern`]. This `Bits` type must itself implement
|
||||||
/// Then, we implement a function that checks wheter a certain instance
|
/// [`AnyBitPattern`]. Then, we implement a function that checks wheter a
|
||||||
/// of the `Bits` is also a valid bit pattern of `Self`. If this check passes, then we
|
/// certain instance of the `Bits` is also a valid bit pattern of `Self`. If
|
||||||
/// can allow casting from the `Bits` to `Self` (and therefore, any type which
|
/// this check passes, then we can allow casting from the `Bits` to `Self` (and
|
||||||
/// is able to be cast to `Bits` is also able to be cast to `Self`).
|
/// 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
|
/// [`AnyBitPattern`] is a subset of [`CheckedBitPattern`], meaning that any `T:
|
||||||
/// [`CheckedBitPattern`]. This means you can also use any [`AnyBitPattern`] type in the checked versions
|
/// AnyBitPattern` is also [`CheckedBitPattern`]. This means you can also use
|
||||||
/// of casting functions in this module. If it's possible, prefer implementing [`AnyBitPattern`] for your
|
/// any [`AnyBitPattern`] type in the checked versions of casting functions in
|
||||||
/// type directly instead of [`CheckedBitPattern`] as it gives greater flexibility.
|
/// this module. If it's possible, prefer implementing [`AnyBitPattern`] for
|
||||||
|
/// your type directly instead of [`CheckedBitPattern`] as it gives greater
|
||||||
|
/// flexibility.
|
||||||
///
|
///
|
||||||
/// # Derive
|
/// # Derive
|
||||||
///
|
///
|
||||||
/// A `#[derive(CheckedBitPattern)]` macro is provided under the `derive` feature flag which will
|
/// A `#[derive(CheckedBitPattern)]` macro is provided under the `derive`
|
||||||
/// automatically validate the requirements of this trait and implement the
|
/// feature flag which will automatically validate the requirements of this
|
||||||
/// trait for you for both enums and structs. This is the recommended method for
|
/// trait and implement the trait for you for both enums and structs. This is
|
||||||
/// implementing the trait, however it's also possible to do manually.
|
/// the recommended method for implementing the trait, however it's also
|
||||||
|
/// possible to do manually.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -107,25 +115,28 @@ use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// * `Self` *must* have the same layout as the specified `Bits` except for
|
/// * `Self` *must* have the same layout as the specified `Bits` except for
|
||||||
/// the possible invalid bit patterns being checked during [`is_valid_bit_pattern`].
|
/// 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
|
/// * 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
|
/// specified repr, but if you think you know better, you probably don't. If
|
||||||
/// still think you know better, be careful and have fun. And don't mess it up
|
/// you still think you know better, be careful and have fun. And don't mess
|
||||||
/// (I mean it).
|
/// it up (I mean it).
|
||||||
/// * If [`is_valid_bit_pattern`] returns true, then the bit pattern contained in
|
/// * If [`is_valid_bit_pattern`] returns true, then the bit pattern contained
|
||||||
/// `bits` must also be valid for an instance of `Self`.
|
/// in `bits` must also be valid for an instance of `Self`.
|
||||||
/// * Probably more, don't mess it up (I mean it 2.0)
|
/// * Probably more, don't mess it up (I mean it 2.0)
|
||||||
///
|
///
|
||||||
/// [`is_valid_bit_pattern`]: CheckedBitPattern::is_valid_bit_pattern
|
/// [`is_valid_bit_pattern`]: CheckedBitPattern::is_valid_bit_pattern
|
||||||
/// [`Pod`]: crate::Pod
|
/// [`Pod`]: crate::Pod
|
||||||
pub unsafe trait CheckedBitPattern: Copy {
|
pub unsafe trait CheckedBitPattern: Copy {
|
||||||
/// `Self` *must* have the same layout as the specified `Bits` except for
|
/// `Self` *must* have the same layout as the specified `Bits` except for
|
||||||
/// the possible invalid bit patterns being checked during [`is_valid_bit_pattern`].
|
/// the possible invalid bit patterns being checked during
|
||||||
|
/// [`is_valid_bit_pattern`].
|
||||||
///
|
///
|
||||||
/// [`is_valid_bit_pattern`]: CheckedBitPattern::is_valid_bit_pattern
|
/// [`is_valid_bit_pattern`]: CheckedBitPattern::is_valid_bit_pattern
|
||||||
type Bits: AnyBitPattern;
|
type Bits: AnyBitPattern;
|
||||||
|
|
||||||
/// If this function returns true, then it must be valid to reinterpret `bits` as `&Self`.
|
/// If this function returns true, then it must be valid to reinterpret `bits`
|
||||||
|
/// as `&Self`.
|
||||||
fn is_valid_bit_pattern(bits: &Self::Bits) -> bool;
|
fn is_valid_bit_pattern(bits: &Self::Bits) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,15 +170,16 @@ unsafe impl CheckedBitPattern for bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The things that can go wrong when casting between [`CheckedBitPattern`] data forms.
|
/// The things that can go wrong when casting between [`CheckedBitPattern`] data
|
||||||
|
/// forms.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum CheckedCastError {
|
pub enum CheckedCastError {
|
||||||
/// An error occurred during a true-[`Pod`] cast
|
/// An error occurred during a true-[`Pod`] cast
|
||||||
PodCastError(crate::PodCastError),
|
PodCastError(crate::PodCastError),
|
||||||
/// When casting to a [`CheckedBitPattern`] type, it is possible that the original
|
/// When casting to a [`CheckedBitPattern`] type, it is possible that the
|
||||||
/// data contains an invalid bit pattern. If so, the cast will fail and
|
/// original data contains an invalid bit pattern. If so, the cast will
|
||||||
/// this error will be returned. Will never happen on casts between
|
/// fail and this error will be returned. Will never happen on casts
|
||||||
/// [`Pod`] types.
|
/// between [`Pod`] types.
|
||||||
InvalidBitPattern,
|
InvalidBitPattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +244,9 @@ pub fn try_from_bytes_mut<T: CheckedBitPattern + NoUninit>(
|
|||||||
/// * If the `bytes` length is not equal to `size_of::<T>()`.
|
/// * If the `bytes` length is not equal to `size_of::<T>()`.
|
||||||
/// * If the slice contains an invalid bit pattern for `T`
|
/// * If the slice contains an invalid bit pattern for `T`
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_pod_read_unaligned<T: CheckedBitPattern>(bytes: &[u8]) -> Result<T, CheckedCastError> {
|
pub fn try_pod_read_unaligned<T: CheckedBitPattern>(
|
||||||
|
bytes: &[u8],
|
||||||
|
) -> Result<T, CheckedCastError> {
|
||||||
let pod = unsafe { internal::try_pod_read_unaligned(bytes) }?;
|
let pod = unsafe { internal::try_pod_read_unaligned(bytes) }?;
|
||||||
|
|
||||||
if <T as CheckedBitPattern>::is_valid_bit_pattern(pod) {
|
if <T as CheckedBitPattern>::is_valid_bit_pattern(pod) {
|
||||||
@ -290,7 +304,10 @@ pub fn try_cast_ref<A: NoUninit, B: CheckedBitPattern>(
|
|||||||
///
|
///
|
||||||
/// As [`checked_cast_ref`], but `mut`.
|
/// As [`checked_cast_ref`], but `mut`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_cast_mut<A: NoUninit + AnyBitPattern, B: CheckedBitPattern + NoUninit>(
|
pub fn try_cast_mut<
|
||||||
|
A: NoUninit + AnyBitPattern,
|
||||||
|
B: CheckedBitPattern + NoUninit,
|
||||||
|
>(
|
||||||
a: &mut A,
|
a: &mut A,
|
||||||
) -> Result<&mut B, CheckedCastError> {
|
) -> Result<&mut B, CheckedCastError> {
|
||||||
let pod = unsafe { internal::try_cast_mut(a) }?;
|
let pod = unsafe { internal::try_cast_mut(a) }?;
|
||||||
@ -317,7 +334,8 @@ pub fn try_cast_mut<A: NoUninit + AnyBitPattern, B: CheckedBitPattern + NoUninit
|
|||||||
/// that's a failure).
|
/// that's a failure).
|
||||||
/// * Similarly, you can't convert between a [ZST](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
|
/// * Similarly, you can't convert between a [ZST](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
|
||||||
/// and a non-ZST.
|
/// and a non-ZST.
|
||||||
/// * If any element of the converted slice would contain an invalid bit pattern for `B` this fails.
|
/// * If any element of the converted slice would contain an invalid bit pattern
|
||||||
|
/// for `B` this fails.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_cast_slice<A: NoUninit, B: CheckedBitPattern>(
|
pub fn try_cast_slice<A: NoUninit, B: CheckedBitPattern>(
|
||||||
a: &[A],
|
a: &[A],
|
||||||
@ -338,7 +356,10 @@ pub fn try_cast_slice<A: NoUninit, B: CheckedBitPattern>(
|
|||||||
///
|
///
|
||||||
/// As [`checked_cast_slice`], but `&mut`.
|
/// As [`checked_cast_slice`], but `&mut`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_cast_slice_mut<A: NoUninit + AnyBitPattern, B: CheckedBitPattern + NoUninit>(
|
pub fn try_cast_slice_mut<
|
||||||
|
A: NoUninit + AnyBitPattern,
|
||||||
|
B: CheckedBitPattern + NoUninit,
|
||||||
|
>(
|
||||||
a: &mut [A],
|
a: &mut [A],
|
||||||
) -> Result<&mut [B], CheckedCastError> {
|
) -> Result<&mut [B], CheckedCastError> {
|
||||||
let pod = unsafe { internal::try_cast_slice_mut(a) }?;
|
let pod = unsafe { internal::try_cast_slice_mut(a) }?;
|
||||||
@ -409,7 +430,12 @@ pub fn cast<A: NoUninit, B: CheckedBitPattern>(a: A) -> B {
|
|||||||
///
|
///
|
||||||
/// This is [`try_cast_mut`] but will panic on error.
|
/// This is [`try_cast_mut`] but will panic on error.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + CheckedBitPattern>(a: &mut A) -> &mut B {
|
pub fn cast_mut<
|
||||||
|
A: NoUninit + AnyBitPattern,
|
||||||
|
B: NoUninit + CheckedBitPattern,
|
||||||
|
>(
|
||||||
|
a: &mut A,
|
||||||
|
) -> &mut B {
|
||||||
match try_cast_mut(a) {
|
match try_cast_mut(a) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => something_went_wrong("cast_mut", e),
|
Err(e) => something_went_wrong("cast_mut", e),
|
||||||
@ -448,7 +474,12 @@ pub fn cast_slice<A: NoUninit, B: CheckedBitPattern>(a: &[A]) -> &[B] {
|
|||||||
///
|
///
|
||||||
/// This is [`try_cast_slice_mut`] but will panic on error.
|
/// This is [`try_cast_slice_mut`] but will panic on error.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cast_slice_mut<A: NoUninit + AnyBitPattern, B: NoUninit + CheckedBitPattern>(a: &mut [A]) -> &mut [B] {
|
pub fn cast_slice_mut<
|
||||||
|
A: NoUninit + AnyBitPattern,
|
||||||
|
B: NoUninit + CheckedBitPattern,
|
||||||
|
>(
|
||||||
|
a: &mut [A],
|
||||||
|
) -> &mut [B] {
|
||||||
match try_cast_slice_mut(a) {
|
match try_cast_slice_mut(a) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => something_went_wrong("cast_slice_mut", e),
|
Err(e) => something_went_wrong("cast_slice_mut", e),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Internal implementation of casting functions not bound by marker traits
|
//! Internal implementation of casting functions not bound by marker traits
|
||||||
//! and therefore marked as unsafe. This is used so that we don't need to duplicate
|
//! and therefore marked as unsafe. This is used so that we don't need to
|
||||||
//! the business logic contained in these functions between the versions exported in
|
//! duplicate the business logic contained in these functions between the
|
||||||
//! the crate root, `checked`, and `relaxed` modules.
|
//! versions exported in the crate root, `checked`, and `relaxed` modules.
|
||||||
#![allow(unused_unsafe)]
|
#![allow(unused_unsafe)]
|
||||||
|
|
||||||
use crate::PodCastError;
|
use crate::PodCastError;
|
||||||
@ -22,7 +22,9 @@ possibility code branch.
|
|||||||
/// Immediately panics.
|
/// Immediately panics.
|
||||||
#[cold]
|
#[cold]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub(crate) fn something_went_wrong<D: core::fmt::Display>(_src: &str, _err: D) -> ! {
|
pub(crate) fn something_went_wrong<D: core::fmt::Display>(
|
||||||
|
_src: &str, _err: D,
|
||||||
|
) -> ! {
|
||||||
// Note(Lokathor): Keeping the panic here makes the panic _formatting_ go
|
// Note(Lokathor): Keeping the panic here makes the panic _formatting_ go
|
||||||
// here too, which helps assembly readability and also helps keep down
|
// here too, which helps assembly readability and also helps keep down
|
||||||
// the inline pressure.
|
// the inline pressure.
|
||||||
@ -100,7 +102,9 @@ pub(crate) unsafe fn from_bytes_mut<T: Copy>(s: &mut [u8]) -> &mut T {
|
|||||||
/// ## Failure
|
/// ## Failure
|
||||||
/// * If the `bytes` length is not equal to `size_of::<T>()`.
|
/// * If the `bytes` length is not equal to `size_of::<T>()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) unsafe fn try_pod_read_unaligned<T: Copy>(bytes: &[u8]) -> Result<T, PodCastError> {
|
pub(crate) unsafe fn try_pod_read_unaligned<T: Copy>(
|
||||||
|
bytes: &[u8],
|
||||||
|
) -> Result<T, PodCastError> {
|
||||||
if bytes.len() != size_of::<T>() {
|
if bytes.len() != size_of::<T>() {
|
||||||
Err(PodCastError::SizeMismatch)
|
Err(PodCastError::SizeMismatch)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,68 +1,62 @@
|
|||||||
use crate::Pod;
|
use crate::Pod;
|
||||||
use core::num::{
|
use core::num::{
|
||||||
NonZeroU8,
|
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize,
|
||||||
NonZeroI8,
|
NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
|
||||||
NonZeroU16,
|
|
||||||
NonZeroI16,
|
|
||||||
NonZeroU32,
|
|
||||||
NonZeroI32,
|
|
||||||
NonZeroU64,
|
|
||||||
NonZeroI64,
|
|
||||||
NonZeroU128,
|
|
||||||
NonZeroI128,
|
|
||||||
NonZeroUsize,
|
|
||||||
NonZeroIsize,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Marker trait for "plain old data" types with no uninit (or padding) bytes.
|
/// Marker trait for "plain old data" types with no uninit (or padding) bytes.
|
||||||
///
|
///
|
||||||
/// The requirements for this is very similar to [`Pod`],
|
/// The requirements for this is very similar to [`Pod`],
|
||||||
/// except that it doesn't require that all bit patterns of the type are valid, i.e.
|
/// except that it doesn't require that all bit patterns of the type are valid,
|
||||||
/// it does not require the type to be [`Zeroable`][crate::Zeroable].
|
/// i.e. it does not require the type to be [`Zeroable`][crate::Zeroable].
|
||||||
/// This limits what you can do with a type of this kind, but also broadens the
|
/// This limits what you can do with a type of this kind, but also broadens the
|
||||||
/// included types to things like C-style enums. Notably, you can only cast from
|
/// included types to things like C-style enums. Notably, you can only cast from
|
||||||
/// *immutable* references to a [`NoUninit`] type into *immutable* references of any other
|
/// *immutable* references to a [`NoUninit`] type into *immutable* references of
|
||||||
/// type, no casting of mutable references or mutable references to slices etc.
|
/// any other type, no casting of mutable references or mutable references to
|
||||||
|
/// slices etc.
|
||||||
///
|
///
|
||||||
/// [`Pod`] is a subset of [`NoUninit`], meaning that any `T: Pod` is also
|
/// [`Pod`] is a subset of [`NoUninit`], meaning that any `T: Pod` is also
|
||||||
/// [`NoUninit`] but any `T: NoUninit` is not necessarily [`Pod`]. If possible,
|
/// [`NoUninit`] but any `T: NoUninit` is not necessarily [`Pod`]. If possible,
|
||||||
/// prefer implementing [`Pod`] directly. To get more [`Pod`]-like functionality for
|
/// prefer implementing [`Pod`] directly. To get more [`Pod`]-like functionality
|
||||||
/// a type that is only [`NoUninit`], consider also implementing [`CheckedBitPattern`][crate::CheckedBitPattern].
|
/// for a type that is only [`NoUninit`], consider also implementing
|
||||||
|
/// [`CheckedBitPattern`][crate::CheckedBitPattern].
|
||||||
///
|
///
|
||||||
/// # Derive
|
/// # Derive
|
||||||
///
|
///
|
||||||
/// A `#[derive(NoUninit)]` macro is provided under the `derive` feature flag which will
|
/// A `#[derive(NoUninit)]` macro is provided under the `derive` feature flag
|
||||||
/// automatically validate the requirements of this trait and implement the
|
/// which will automatically validate the requirements of this trait and
|
||||||
/// trait for you for both enums and structs. This is the recommended method for
|
/// implement the trait for you for both enums and structs. This is the
|
||||||
/// implementing the trait, however it's also possible to do manually. If you
|
/// recommended method for implementing the trait, however it's also possible to
|
||||||
/// implement it manually, you *must* carefully follow the below safety rules.
|
/// do manually. If you implement it manually, you *must* carefully follow the
|
||||||
|
/// below safety rules.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The same as [`Pod`] except we disregard the rule about it must
|
/// The same as [`Pod`] except we disregard the rule about it must
|
||||||
/// allow any bit pattern (i.e. it does not need to be [`Zeroable`][crate::Zeroable]).
|
/// allow any bit pattern (i.e. it does not need to be
|
||||||
/// Still, this is a quite strong guarantee about a type, so *be careful* whem
|
/// [`Zeroable`][crate::Zeroable]). Still, this is a quite strong guarantee
|
||||||
/// implementing it manually.
|
/// about a type, so *be careful* whem implementing it manually.
|
||||||
///
|
///
|
||||||
/// * The type must be inhabited (eg: no
|
/// * The type must be inhabited (eg: no
|
||||||
/// [Infallible](core::convert::Infallible)).
|
/// [Infallible](core::convert::Infallible)).
|
||||||
/// * The type must not contain any uninit (or padding) bytes, either in the middle or on
|
/// * The type must not contain any uninit (or padding) bytes, either in the
|
||||||
/// the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has padding in the
|
/// middle or on the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has
|
||||||
/// middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which has padding on
|
/// padding in the middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which
|
||||||
/// the end).
|
/// has padding on the end).
|
||||||
/// * Structs need to have all fields also be `NoUninit`.
|
/// * Structs need to have all fields also be `NoUninit`.
|
||||||
/// * Structs need to be `repr(C)` or `repr(transparent)`. In the case of
|
/// * Structs need to be `repr(C)` or `repr(transparent)`. In the case of
|
||||||
/// `repr(C)`, the `packed` and `align` repr modifiers can be used as long as
|
/// `repr(C)`, the `packed` and `align` repr modifiers can be used as long as
|
||||||
/// all other rules end up being followed.
|
/// all other rules end up being followed.
|
||||||
/// * Enums need to have an explicit `#[repr(Int)]`
|
/// * Enums need to have an explicit `#[repr(Int)]`
|
||||||
/// * Enums must have only fieldless variants
|
/// * Enums must have only fieldless variants
|
||||||
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`, atomics, and any
|
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`,
|
||||||
/// other forms of interior mutability.
|
/// atomics, and any other forms of interior mutability.
|
||||||
/// * More precisely: A shared reference to the type must allow reads, and *only* reads. RustBelt's
|
/// * More precisely: A shared reference to the type must allow reads, and
|
||||||
/// separation logic is based on the notion that a type is allowed to define a sharing predicate,
|
/// *only* reads. RustBelt's separation logic is based on the notion that a
|
||||||
/// its own invariant that must hold for shared references, and this predicate is the reasoning
|
/// type is allowed to define a sharing predicate, its own invariant that must
|
||||||
/// that allow it to deal with atomic and cells etc. We require the sharing predicate to be
|
/// hold for shared references, and this predicate is the reasoning that allow
|
||||||
/// trivial and permit only read-only access.
|
/// it to deal with atomic and cells etc. We require the sharing predicate to
|
||||||
|
/// be trivial and permit only read-only access.
|
||||||
/// * There's probably more, don't mess it up (I mean it).
|
/// * There's probably more, don't mess it up (I mean it).
|
||||||
pub unsafe trait NoUninit: Sized + Copy + 'static {}
|
pub unsafe trait NoUninit: Sized + Copy + 'static {}
|
||||||
|
|
||||||
|
@ -21,11 +21,15 @@ fn test_transparent_wrapper() {
|
|||||||
unsafe impl bytemuck::Pod for Wrapper {}
|
unsafe impl bytemuck::Pod for Wrapper {}
|
||||||
|
|
||||||
impl PartialEq<u8> for Foreign {
|
impl PartialEq<u8> for Foreign {
|
||||||
fn eq(&self, &other: &u8) -> bool { self.0 == other }
|
fn eq(&self, &other: &u8) -> bool {
|
||||||
|
self.0 == other
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<u8> for Wrapper {
|
impl PartialEq<u8> for Wrapper {
|
||||||
fn eq(&self, &other: &u8) -> bool { self.0 == other }
|
fn eq(&self, &other: &u8) -> bool {
|
||||||
|
self.0 == other
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _: u8 = bytemuck::cast(Wrapper::wrap(Foreign::default()));
|
let _: u8 = bytemuck::cast(Wrapper::wrap(Foreign::default()));
|
||||||
|
Loading…
Reference in New Issue
Block a user