mirror of
https://github.com/Lokathor/bytemuck.git
synced 2024-11-24 15:52:24 +00:00
Move the FooInOption traits into their own files for easier organization.
This commit is contained in:
parent
abe55e525e
commit
1f265a9e0d
55
src/lib.rs
55
src/lib.rs
@ -90,9 +90,13 @@ mod internal;
|
||||
|
||||
mod zeroable;
|
||||
pub use zeroable::*;
|
||||
mod zeroable_in_option;
|
||||
pub use zeroable_in_option::*;
|
||||
|
||||
mod pod;
|
||||
pub use pod::*;
|
||||
mod pod_in_option;
|
||||
pub use pod_in_option::*;
|
||||
|
||||
mod no_uninit;
|
||||
pub use no_uninit::*;
|
||||
@ -108,7 +112,8 @@ pub use transparent::*;
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
pub use bytemuck_derive::{
|
||||
AnyBitPattern, Contiguous, CheckedBitPattern, NoUninit, Pod, TransparentWrapper, Zeroable,
|
||||
AnyBitPattern, CheckedBitPattern, Contiguous, NoUninit, Pod,
|
||||
TransparentWrapper, Zeroable,
|
||||
};
|
||||
|
||||
/// The things that can go wrong when casting between [`Pod`] data forms.
|
||||
@ -185,7 +190,9 @@ pub fn from_bytes_mut<T: NoUninit + AnyBitPattern>(s: &mut [u8]) -> &mut T {
|
||||
/// ## Failure
|
||||
/// * If the `bytes` length is not equal to `size_of::<T>()`.
|
||||
#[inline]
|
||||
pub fn try_pod_read_unaligned<T: AnyBitPattern>(bytes: &[u8]) -> Result<T, PodCastError> {
|
||||
pub fn try_pod_read_unaligned<T: AnyBitPattern>(
|
||||
bytes: &[u8],
|
||||
) -> Result<T, PodCastError> {
|
||||
unsafe { internal::try_pod_read_unaligned(bytes) }
|
||||
}
|
||||
|
||||
@ -238,7 +245,9 @@ pub fn cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
|
||||
///
|
||||
/// This is [`try_cast_mut`] but will panic on error.
|
||||
#[inline]
|
||||
pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(a: &mut A) -> &mut B {
|
||||
pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
|
||||
a: &mut A,
|
||||
) -> &mut B {
|
||||
unsafe { internal::cast_mut(a) }
|
||||
}
|
||||
|
||||
@ -268,19 +277,29 @@ pub fn cast_slice<A: NoUninit, B: AnyBitPattern>(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 + AnyBitPattern>(a: &mut [A]) -> &mut [B] {
|
||||
pub fn cast_slice_mut<
|
||||
A: NoUninit + AnyBitPattern,
|
||||
B: NoUninit + AnyBitPattern,
|
||||
>(
|
||||
a: &mut [A],
|
||||
) -> &mut [B] {
|
||||
unsafe { internal::cast_slice_mut(a) }
|
||||
}
|
||||
|
||||
/// As `align_to`, but safe because of the [`Pod`] bound.
|
||||
#[inline]
|
||||
pub fn pod_align_to<T: NoUninit, U: AnyBitPattern>(vals: &[T]) -> (&[T], &[U], &[T]) {
|
||||
pub fn pod_align_to<T: NoUninit, U: AnyBitPattern>(
|
||||
vals: &[T],
|
||||
) -> (&[T], &[U], &[T]) {
|
||||
unsafe { vals.align_to::<U>() }
|
||||
}
|
||||
|
||||
/// As `align_to_mut`, but safe because of the [`Pod`] bound.
|
||||
#[inline]
|
||||
pub fn pod_align_to_mut<T: NoUninit + AnyBitPattern, U: NoUninit + AnyBitPattern>(
|
||||
pub fn pod_align_to_mut<
|
||||
T: NoUninit + AnyBitPattern,
|
||||
U: NoUninit + AnyBitPattern,
|
||||
>(
|
||||
vals: &mut [T],
|
||||
) -> (&mut [T], &mut [U], &mut [T]) {
|
||||
unsafe { vals.align_to_mut::<U>() }
|
||||
@ -297,7 +316,9 @@ pub fn pod_align_to_mut<T: NoUninit + AnyBitPattern, U: NoUninit + AnyBitPattern
|
||||
///
|
||||
/// * If the types don't have the same size this fails.
|
||||
#[inline]
|
||||
pub fn try_cast<A: NoUninit, B: AnyBitPattern>(a: A) -> Result<B, PodCastError> {
|
||||
pub fn try_cast<A: NoUninit, B: AnyBitPattern>(
|
||||
a: A,
|
||||
) -> Result<B, PodCastError> {
|
||||
unsafe { internal::try_cast(a) }
|
||||
}
|
||||
|
||||
@ -308,7 +329,9 @@ pub fn try_cast<A: NoUninit, B: AnyBitPattern>(a: A) -> Result<B, PodCastError>
|
||||
/// * If the reference isn't aligned in the new type
|
||||
/// * If the source type and target type aren't the same size.
|
||||
#[inline]
|
||||
pub fn try_cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> Result<&B, PodCastError> {
|
||||
pub fn try_cast_ref<A: NoUninit, B: AnyBitPattern>(
|
||||
a: &A,
|
||||
) -> Result<&B, PodCastError> {
|
||||
unsafe { internal::try_cast_ref(a) }
|
||||
}
|
||||
|
||||
@ -316,7 +339,12 @@ pub fn try_cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> Result<&B, PodCastE
|
||||
///
|
||||
/// As [`try_cast_ref`], but `mut`.
|
||||
#[inline]
|
||||
pub fn try_cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(a: &mut A) -> Result<&mut B, PodCastError> {
|
||||
pub fn try_cast_mut<
|
||||
A: NoUninit + AnyBitPattern,
|
||||
B: NoUninit + AnyBitPattern,
|
||||
>(
|
||||
a: &mut A,
|
||||
) -> Result<&mut B, PodCastError> {
|
||||
unsafe { internal::try_cast_mut(a) }
|
||||
}
|
||||
|
||||
@ -336,7 +364,9 @@ pub fn try_cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(a:
|
||||
/// * 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.
|
||||
#[inline]
|
||||
pub fn try_cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> Result<&[B], PodCastError> {
|
||||
pub fn try_cast_slice<A: NoUninit, B: AnyBitPattern>(
|
||||
a: &[A],
|
||||
) -> Result<&[B], PodCastError> {
|
||||
unsafe { internal::try_cast_slice(a) }
|
||||
}
|
||||
|
||||
@ -345,7 +375,10 @@ pub fn try_cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> Result<&[B], Po
|
||||
///
|
||||
/// As [`try_cast_slice`], but `&mut`.
|
||||
#[inline]
|
||||
pub fn try_cast_slice_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
|
||||
pub fn try_cast_slice_mut<
|
||||
A: NoUninit + AnyBitPattern,
|
||||
B: NoUninit + AnyBitPattern,
|
||||
>(
|
||||
a: &mut [A],
|
||||
) -> Result<&mut [B], PodCastError> {
|
||||
unsafe { internal::try_cast_slice_mut(a) }
|
||||
|
44
src/pod.rs
44
src/pod.rs
@ -18,21 +18,22 @@ use super::*;
|
||||
/// [Infallible](core::convert::Infallible)).
|
||||
/// * The type must allow any bit pattern (eg: no `bool` or `char`, which have
|
||||
/// illegal bit patterns).
|
||||
/// * 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).
|
||||
/// * The type needs to have all fields also be `Pod`.
|
||||
/// * The type needs 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.
|
||||
/// * 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.
|
||||
pub unsafe trait Pod: Zeroable + Copy + 'static {}
|
||||
|
||||
unsafe impl Pod for () {}
|
||||
@ -52,27 +53,6 @@ unsafe impl Pod for f32 {}
|
||||
unsafe impl Pod for f64 {}
|
||||
unsafe impl<T: Pod> Pod for Wrapping<T> {}
|
||||
|
||||
/// Trait for types which are [Pod](Pod) when wrapped in [Option](core::option::Option).
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// * `Option<T>` must uphold the same invariants as [Pod](Pod).
|
||||
pub unsafe trait PodInOption: ZeroableInOption + Copy + 'static {}
|
||||
unsafe impl<T: PodInOption> Pod for Option<T> {}
|
||||
|
||||
unsafe impl PodInOption for NonZeroI8 {}
|
||||
unsafe impl PodInOption for NonZeroI16 {}
|
||||
unsafe impl PodInOption for NonZeroI32 {}
|
||||
unsafe impl PodInOption for NonZeroI64 {}
|
||||
unsafe impl PodInOption for NonZeroI128 {}
|
||||
unsafe impl PodInOption for NonZeroIsize {}
|
||||
unsafe impl PodInOption for NonZeroU8 {}
|
||||
unsafe impl PodInOption for NonZeroU16 {}
|
||||
unsafe impl PodInOption for NonZeroU32 {}
|
||||
unsafe impl PodInOption for NonZeroU64 {}
|
||||
unsafe impl PodInOption for NonZeroU128 {}
|
||||
unsafe impl PodInOption for NonZeroUsize {}
|
||||
|
||||
#[cfg(feature = "unsound_ptr_pod_impl")]
|
||||
unsafe impl<T: 'static> Pod for *mut T {}
|
||||
#[cfg(feature = "unsound_ptr_pod_impl")]
|
||||
|
25
src/pod_in_option.rs
Normal file
25
src/pod_in_option.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use super::*;
|
||||
|
||||
// Note(Lokathor): This is the neat part!!
|
||||
unsafe impl<T: PodInOption> Pod for Option<T> {}
|
||||
|
||||
/// Trait for types which are [Pod](Pod) when wrapped in
|
||||
/// [Option](core::option::Option).
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// * `Option<T>` must uphold the same invariants as [Pod](Pod).
|
||||
pub unsafe trait PodInOption: ZeroableInOption + Copy + 'static {}
|
||||
|
||||
unsafe impl PodInOption for NonZeroI8 {}
|
||||
unsafe impl PodInOption for NonZeroI16 {}
|
||||
unsafe impl PodInOption for NonZeroI32 {}
|
||||
unsafe impl PodInOption for NonZeroI64 {}
|
||||
unsafe impl PodInOption for NonZeroI128 {}
|
||||
unsafe impl PodInOption for NonZeroIsize {}
|
||||
unsafe impl PodInOption for NonZeroU8 {}
|
||||
unsafe impl PodInOption for NonZeroU16 {}
|
||||
unsafe impl PodInOption for NonZeroU32 {}
|
||||
unsafe impl PodInOption for NonZeroU64 {}
|
||||
unsafe impl PodInOption for NonZeroU128 {}
|
||||
unsafe impl PodInOption for NonZeroUsize {}
|
@ -42,27 +42,6 @@ unsafe impl Zeroable for f32 {}
|
||||
unsafe impl Zeroable for f64 {}
|
||||
unsafe impl<T: Zeroable> Zeroable for Wrapping<T> {}
|
||||
|
||||
/// Trait for types which are [Zeroable](Zeroable) when wrapped in [Option](core::option::Option).
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// * `Option<T>` must uphold the same invariants as [Zeroable](Zeroable).
|
||||
pub unsafe trait ZeroableInOption: Sized {}
|
||||
unsafe impl<T: ZeroableInOption> Zeroable for Option<T> {}
|
||||
|
||||
unsafe impl ZeroableInOption for NonZeroI8 {}
|
||||
unsafe impl ZeroableInOption for NonZeroI16 {}
|
||||
unsafe impl ZeroableInOption for NonZeroI32 {}
|
||||
unsafe impl ZeroableInOption for NonZeroI64 {}
|
||||
unsafe impl ZeroableInOption for NonZeroI128 {}
|
||||
unsafe impl ZeroableInOption for NonZeroIsize {}
|
||||
unsafe impl ZeroableInOption for NonZeroU8 {}
|
||||
unsafe impl ZeroableInOption for NonZeroU16 {}
|
||||
unsafe impl ZeroableInOption for NonZeroU32 {}
|
||||
unsafe impl ZeroableInOption for NonZeroU64 {}
|
||||
unsafe impl ZeroableInOption for NonZeroU128 {}
|
||||
unsafe impl ZeroableInOption for NonZeroUsize {}
|
||||
|
||||
unsafe impl<T> Zeroable for *mut T {}
|
||||
unsafe impl<T> Zeroable for *const T {}
|
||||
unsafe impl<T> ZeroableInOption for NonNull<T> {}
|
||||
|
26
src/zeroable_in_option.rs
Normal file
26
src/zeroable_in_option.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use super::*;
|
||||
|
||||
// Note(Lokathor): This is the neat part!!
|
||||
unsafe impl<T: ZeroableInOption> Zeroable for Option<T> {}
|
||||
|
||||
/// Trait for types which are [Zeroable](Zeroable) when wrapped in
|
||||
/// [Option](core::option::Option).
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// * `Option<YourType>` must uphold the same invariants as
|
||||
/// [Zeroable](Zeroable).
|
||||
pub unsafe trait ZeroableInOption: Sized {}
|
||||
|
||||
unsafe impl ZeroableInOption for NonZeroI8 {}
|
||||
unsafe impl ZeroableInOption for NonZeroI16 {}
|
||||
unsafe impl ZeroableInOption for NonZeroI32 {}
|
||||
unsafe impl ZeroableInOption for NonZeroI64 {}
|
||||
unsafe impl ZeroableInOption for NonZeroI128 {}
|
||||
unsafe impl ZeroableInOption for NonZeroIsize {}
|
||||
unsafe impl ZeroableInOption for NonZeroU8 {}
|
||||
unsafe impl ZeroableInOption for NonZeroU16 {}
|
||||
unsafe impl ZeroableInOption for NonZeroU32 {}
|
||||
unsafe impl ZeroableInOption for NonZeroU64 {}
|
||||
unsafe impl ZeroableInOption for NonZeroU128 {}
|
||||
unsafe impl ZeroableInOption for NonZeroUsize {}
|
Loading…
Reference in New Issue
Block a user