run cargo fmt (#120)

This commit is contained in:
Waffle Maybe 2022-07-24 19:27:49 +04:00 committed by GitHub
parent d75942c484
commit 331762b014
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 176 additions and 140 deletions

View File

@ -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);

View File

@ -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 {}

View File

@ -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),

View File

@ -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 {

View File

@ -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 {}

View File

@ -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()));