mirror of
https://github.com/Lokathor/bytemuck.git
synced 2024-11-25 00:02:22 +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()
|
||||
}
|
||||
|
||||
/// 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
|
||||
///
|
||||
/// 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>, ()> {
|
||||
if length == 0 {
|
||||
Ok(Vec::new())
|
||||
@ -121,7 +123,8 @@ pub fn zeroed_vec<T: Zeroable>(length: usize) -> Vec<T> {
|
||||
///
|
||||
/// ## 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]
|
||||
pub fn try_zeroed_slice_box<T: Zeroable>(
|
||||
length: usize,
|
||||
@ -145,7 +148,7 @@ pub fn try_zeroed_slice_box<T: Zeroable>(
|
||||
let slice =
|
||||
unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) };
|
||||
Ok(unsafe { Box::<[T]>::from_raw(slice) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
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.
|
||||
fn wrap_vec(s: Vec<Inner>) -> Vec<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
Inner: Sized
|
||||
Inner: Sized,
|
||||
{
|
||||
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)
|
||||
// * the two types have the identical representation
|
||||
// * the len and capacity fields are valid
|
||||
Vec::from_raw_parts(
|
||||
ptr as *mut Self,
|
||||
length,
|
||||
capacity
|
||||
)
|
||||
Vec::from_raw_parts(ptr as *mut Self, length, capacity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,12 +351,12 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
||||
// the vtables match (because of the `?Sized` restriction relaxation).
|
||||
// A `transmute` doesn't work because the sizes are unspecified.
|
||||
//
|
||||
// SAFETY:
|
||||
// * The unsafe contract requires that pointers to Inner and Self
|
||||
// have identical representations
|
||||
// * Box is guaranteed to have representation identical to a
|
||||
// (non-null) pointer
|
||||
// * The pointer comes from a box (and thus satisfies all safety
|
||||
// SAFETY:
|
||||
// * The unsafe contract requires that pointers to Inner and Self have
|
||||
// identical representations
|
||||
// * Box is guaranteed to have representation identical to a (non-null)
|
||||
// pointer
|
||||
// * The pointer comes from a box (and thus satisfies all safety
|
||||
// requirements of Box)
|
||||
let inner_ptr: *mut Inner = Box::into_raw(s);
|
||||
let wrapper_ptr: *mut Self = transmute!(inner_ptr);
|
||||
@ -367,7 +368,7 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
||||
fn peel_vec(s: Vec<Self>) -> Vec<Inner>
|
||||
where
|
||||
Self: Sized,
|
||||
Inner: Sized
|
||||
Inner: Sized,
|
||||
{
|
||||
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)
|
||||
// * the two types have the identical representation
|
||||
// * the len and capacity fields are valid
|
||||
Vec::from_raw_parts(
|
||||
ptr as *mut Inner,
|
||||
length,
|
||||
capacity
|
||||
)
|
||||
Vec::from_raw_parts(ptr as *mut Inner, length, capacity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,12 +396,12 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
||||
// the vtables match (because of the `?Sized` restriction relaxation).
|
||||
// A `transmute` doesn't work because the sizes are unspecified.
|
||||
//
|
||||
// SAFETY:
|
||||
// * The unsafe contract requires that pointers to Inner and Self
|
||||
// have identical representations
|
||||
// * Box is guaranteed to have representation identical to a
|
||||
// (non-null) pointer
|
||||
// * The pointer comes from a box (and thus satisfies all safety
|
||||
// SAFETY:
|
||||
// * The unsafe contract requires that pointers to Inner and Self have
|
||||
// identical representations
|
||||
// * Box is guaranteed to have representation identical to a (non-null)
|
||||
// pointer
|
||||
// * The pointer comes from a box (and thus satisfies all safety
|
||||
// requirements of Box)
|
||||
let wrapper_ptr: *mut Self = Box::into_raw(s);
|
||||
let inner_ptr: *mut Inner = transmute!(wrapper_ptr);
|
||||
|
@ -5,46 +5,52 @@ use crate::{Pod, Zeroable};
|
||||
/// The requirements for this is very similar to [`Pod`],
|
||||
/// 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
|
||||
/// included types to `repr(C)` `struct`s that contain padding as well as `union`s. Notably, you can only cast
|
||||
/// *immutable* references and *owned* values into [`AnyBitPattern`] types, not
|
||||
/// *mutable* references.
|
||||
/// included types to `repr(C)` `struct`s that contain padding as well as
|
||||
/// `union`s. Notably, you can only cast *immutable* references and *owned*
|
||||
/// values into [`AnyBitPattern`] types, not *mutable* references.
|
||||
///
|
||||
/// [`Pod`] is a subset of [`AnyBitPattern`], meaning that any `T: Pod` is also
|
||||
/// [`AnyBitPattern`] but any `T: AnyBitPattern` is not necessarily [`Pod`].
|
||||
///
|
||||
/// [`AnyBitPattern`] is a subset of [`Zeroable`], meaning that any `T: AnyBitPattern`
|
||||
/// is also [`Zeroable`], but any `T: Zeroable` is not necessarily [`AnyBitPattern ]
|
||||
/// [`AnyBitPattern`] is a subset of [`Zeroable`], meaning that any `T:
|
||||
/// AnyBitPattern` is also [`Zeroable`], but any `T: Zeroable` is not
|
||||
/// necessarily [`AnyBitPattern ]
|
||||
///
|
||||
/// # Derive
|
||||
///
|
||||
/// A `#[derive(AnyBitPattern)]` 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 structs and enums. This is the recommended method for
|
||||
/// implementing the trait, however it's also possible to do manually. If you
|
||||
/// implement it manually, you *must* carefully follow the below safety rules.
|
||||
/// A `#[derive(AnyBitPattern)]` 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 structs and enums. This is the
|
||||
/// recommended method for implementing the trait, however it's also possible to
|
||||
/// 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
|
||||
/// this trait, since it is **unsound** for an enum to have a discriminant value
|
||||
/// that is not one of its defined variants.
|
||||
///
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Similar to [`Pod`] except we disregard the rule about it must not contain uninit bytes.
|
||||
/// Still, this is a quite strong guarantee about a type, so *be careful* when
|
||||
/// implementing it manually.
|
||||
/// Similar to [`Pod`] except we disregard the rule about it must not contain
|
||||
/// uninit bytes. Still, this is a quite strong guarantee about a type, so *be
|
||||
/// careful* when implementing it manually.
|
||||
///
|
||||
/// * The type must be inhabited (eg: no
|
||||
/// [Infallible](core::convert::Infallible)).
|
||||
/// * The type must be valid for any bit pattern of its backing memory.
|
||||
/// * Structs need to have all fields also be `AnyBitPattern`.
|
||||
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`, atomics, and any
|
||||
/// other forms of interior mutability.
|
||||
/// * More precisely: A shared reference to the type must allow reads, and *only* reads. RustBelt's
|
||||
/// separation logic is based on the notion that a type is allowed to define a sharing predicate,
|
||||
/// its own invariant that must hold for shared references, and this predicate is the reasoning
|
||||
/// that allow it to deal with atomic and cells etc. We require the sharing predicate to be
|
||||
/// trivial and permit only read-only access.
|
||||
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`,
|
||||
/// atomics, and any other forms of interior mutability.
|
||||
/// * More precisely: A shared reference to the type must allow reads, and
|
||||
/// *only* reads. RustBelt's separation logic is based on the notion that a
|
||||
/// type is allowed to define a sharing predicate, its own invariant that must
|
||||
/// hold for shared references, and this predicate is the reasoning that allow
|
||||
/// 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).
|
||||
pub unsafe trait AnyBitPattern: Zeroable + Sized + Copy + 'static {}
|
||||
pub unsafe trait AnyBitPattern:
|
||||
Zeroable + Sized + Copy + 'static
|
||||
{
|
||||
}
|
||||
|
||||
unsafe impl<T: Pod> AnyBitPattern for T {}
|
||||
|
111
src/checked.rs
111
src/checked.rs
@ -1,32 +1,40 @@
|
||||
//! Checked versions of the casting functions exposed in crate root
|
||||
//! 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
|
||||
/// 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.
|
||||
/// 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`).
|
||||
/// 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.
|
||||
/// [`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.
|
||||
/// 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
|
||||
///
|
||||
@ -53,7 +61,7 @@ use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// // 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.
|
||||
@ -92,7 +100,7 @@ use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
|
||||
/// 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;
|
||||
@ -107,25 +115,28 @@ use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
|
||||
/// # Safety
|
||||
///
|
||||
/// * `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
|
||||
/// 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 in
|
||||
/// `bits` must also be valid for an instance of `Self`.
|
||||
/// 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
|
||||
/// in `bits` must also be valid for an instance of `Self`.
|
||||
/// * Probably more, don't mess it up (I mean it 2.0)
|
||||
///
|
||||
/// [`is_valid_bit_pattern`]: CheckedBitPattern::is_valid_bit_pattern
|
||||
/// [`Pod`]: crate::Pod
|
||||
pub unsafe trait CheckedBitPattern: Copy {
|
||||
/// `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
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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)]
|
||||
pub enum CheckedCastError {
|
||||
/// An error occurred during a true-[`Pod`] cast
|
||||
PodCastError(crate::PodCastError),
|
||||
/// When casting to a [`CheckedBitPattern`] type, it is possible that the original
|
||||
/// data contains an invalid bit pattern. If so, the cast will fail and
|
||||
/// this error will be returned. Will never happen on casts between
|
||||
/// [`Pod`] types.
|
||||
/// When casting to a [`CheckedBitPattern`] type, it is possible that the
|
||||
/// original data contains an invalid bit pattern. If so, the cast will
|
||||
/// fail and this error will be returned. Will never happen on casts
|
||||
/// between [`Pod`] types.
|
||||
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 slice contains an invalid bit pattern for `T`
|
||||
#[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) }?;
|
||||
|
||||
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`.
|
||||
#[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,
|
||||
) -> Result<&mut B, CheckedCastError> {
|
||||
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).
|
||||
/// * 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.
|
||||
/// * 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]
|
||||
pub fn try_cast_slice<A: NoUninit, B: CheckedBitPattern>(
|
||||
a: &[A],
|
||||
@ -338,7 +356,10 @@ pub fn try_cast_slice<A: NoUninit, B: CheckedBitPattern>(
|
||||
///
|
||||
/// As [`checked_cast_slice`], but `&mut`.
|
||||
#[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],
|
||||
) -> Result<&mut [B], CheckedCastError> {
|
||||
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.
|
||||
#[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) {
|
||||
Ok(t) => t,
|
||||
Err(e) => something_went_wrong("cast_mut", e),
|
||||
@ -448,9 +474,14 @@ pub fn cast_slice<A: NoUninit, B: CheckedBitPattern>(a: &[A]) -> &[B] {
|
||||
///
|
||||
/// This is [`try_cast_slice_mut`] but will panic on error.
|
||||
#[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) {
|
||||
Ok(t) => t,
|
||||
Err(e) => something_went_wrong("cast_slice_mut", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! 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
|
||||
//! the business logic contained in these functions between the versions exported in
|
||||
//! the crate root, `checked`, and `relaxed` modules.
|
||||
//! and therefore marked as unsafe. This is used so that we don't need to
|
||||
//! duplicate the business logic contained in these functions between the
|
||||
//! versions exported in the crate root, `checked`, and `relaxed` modules.
|
||||
#![allow(unused_unsafe)]
|
||||
|
||||
use crate::PodCastError;
|
||||
@ -22,7 +22,9 @@ possibility code branch.
|
||||
/// Immediately panics.
|
||||
#[cold]
|
||||
#[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
|
||||
// here too, which helps assembly readability and also helps keep down
|
||||
// the inline pressure.
|
||||
@ -100,7 +102,9 @@ pub(crate) unsafe fn from_bytes_mut<T: Copy>(s: &mut [u8]) -> &mut T {
|
||||
/// ## Failure
|
||||
/// * If the `bytes` length is not equal to `size_of::<T>()`.
|
||||
#[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>() {
|
||||
Err(PodCastError::SizeMismatch)
|
||||
} else {
|
||||
|
@ -1,68 +1,62 @@
|
||||
use crate::Pod;
|
||||
use core::num::{
|
||||
NonZeroU8,
|
||||
NonZeroI8,
|
||||
NonZeroU16,
|
||||
NonZeroI16,
|
||||
NonZeroU32,
|
||||
NonZeroI32,
|
||||
NonZeroU64,
|
||||
NonZeroI64,
|
||||
NonZeroU128,
|
||||
NonZeroI128,
|
||||
NonZeroUsize,
|
||||
NonZeroIsize,
|
||||
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize,
|
||||
NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
|
||||
};
|
||||
|
||||
/// Marker trait for "plain old data" types with no uninit (or padding) bytes.
|
||||
///
|
||||
/// 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.
|
||||
/// it does not require the type to be [`Zeroable`][crate::Zeroable].
|
||||
/// except that it doesn't require that all bit patterns of the type are valid,
|
||||
/// 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
|
||||
/// 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
|
||||
/// type, no casting of mutable references or mutable references to slices etc.
|
||||
/// *immutable* references to a [`NoUninit`] type into *immutable* references of
|
||||
/// 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
|
||||
/// [`NoUninit`] but any `T: NoUninit` is not necessarily [`Pod`]. If possible,
|
||||
/// prefer implementing [`Pod`] directly. To get more [`Pod`]-like functionality for
|
||||
/// a type that is only [`NoUninit`], consider also implementing [`CheckedBitPattern`][crate::CheckedBitPattern].
|
||||
/// prefer implementing [`Pod`] directly. To get more [`Pod`]-like functionality
|
||||
/// for a type that is only [`NoUninit`], consider also implementing
|
||||
/// [`CheckedBitPattern`][crate::CheckedBitPattern].
|
||||
///
|
||||
/// # Derive
|
||||
///
|
||||
/// A `#[derive(NoUninit)]` 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. If you
|
||||
/// implement it manually, you *must* carefully follow the below safety rules.
|
||||
/// A `#[derive(NoUninit)]` 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. If you implement it manually, you *must* carefully follow the
|
||||
/// below safety rules.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// 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]).
|
||||
/// Still, this is a quite strong guarantee about a type, so *be careful* whem
|
||||
/// implementing it manually.
|
||||
/// allow any bit pattern (i.e. it does not need to be
|
||||
/// [`Zeroable`][crate::Zeroable]). Still, this is a quite strong guarantee
|
||||
/// about a type, so *be careful* whem implementing it manually.
|
||||
///
|
||||
/// * The type must be inhabited (eg: no
|
||||
/// [Infallible](core::convert::Infallible)).
|
||||
/// * The type must not contain any uninit (or padding) bytes, either in the middle or on
|
||||
/// the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has padding in the
|
||||
/// middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which has padding on
|
||||
/// the end).
|
||||
/// * The type must not contain any uninit (or padding) bytes, either in the
|
||||
/// middle or on the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has
|
||||
/// padding in the middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which
|
||||
/// has padding on the end).
|
||||
/// * Structs need to have all fields also be `NoUninit`.
|
||||
/// * 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
|
||||
/// all other rules end up being followed.
|
||||
/// * Enums need to have an explicit `#[repr(Int)]`
|
||||
/// * Enums must have only fieldless variants
|
||||
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`, atomics, and any
|
||||
/// other forms of interior mutability.
|
||||
/// * More precisely: A shared reference to the type must allow reads, and *only* reads. RustBelt's
|
||||
/// separation logic is based on the notion that a type is allowed to define a sharing predicate,
|
||||
/// its own invariant that must hold for shared references, and this predicate is the reasoning
|
||||
/// that allow it to deal with atomic and cells etc. We require the sharing predicate to be
|
||||
/// trivial and permit only read-only access.
|
||||
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`,
|
||||
/// atomics, and any other forms of interior mutability.
|
||||
/// * More precisely: A shared reference to the type must allow reads, and
|
||||
/// *only* reads. RustBelt's separation logic is based on the notion that a
|
||||
/// type is allowed to define a sharing predicate, its own invariant that must
|
||||
/// hold for shared references, and this predicate is the reasoning that allow
|
||||
/// 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).
|
||||
pub unsafe trait NoUninit: Sized + Copy + 'static {}
|
||||
|
||||
@ -83,4 +77,4 @@ unsafe impl NoUninit for NonZeroI64 {}
|
||||
unsafe impl NoUninit for NonZeroU128 {}
|
||||
unsafe impl NoUninit for NonZeroI128 {}
|
||||
unsafe impl NoUninit for NonZeroUsize {}
|
||||
unsafe impl NoUninit for NonZeroIsize {}
|
||||
unsafe impl NoUninit for NonZeroIsize {}
|
||||
|
@ -21,11 +21,15 @@ fn test_transparent_wrapper() {
|
||||
unsafe impl bytemuck::Pod for Wrapper {}
|
||||
|
||||
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 {
|
||||
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()));
|
||||
@ -75,7 +79,7 @@ fn test_transparent_wrapper() {
|
||||
use bytemuck::allocation::TransparentWrapperAlloc;
|
||||
|
||||
let a: Vec<Foreign> = vec![Foreign::default(); 2];
|
||||
|
||||
|
||||
let b: Vec<Wrapper> = Wrapper::wrap_vec(a);
|
||||
assert_eq!(b, [0, 0]);
|
||||
|
||||
@ -83,7 +87,7 @@ fn test_transparent_wrapper() {
|
||||
assert_eq!(c, [0, 0]);
|
||||
|
||||
let d: Box<Foreign> = Box::new(Foreign::default());
|
||||
|
||||
|
||||
let e: Box<Wrapper> = Wrapper::wrap_box(d);
|
||||
assert_eq!(&*e, &0);
|
||||
let f: Box<Foreign> = Wrapper::peel_box(e);
|
||||
|
Loading…
Reference in New Issue
Block a user