summaryrefslogtreecommitdiff
path: root/vendor/bytemuck/src/transparent.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/bytemuck/src/transparent.rs')
-rw-r--r--vendor/bytemuck/src/transparent.rs288
1 files changed, 288 insertions, 0 deletions
diff --git a/vendor/bytemuck/src/transparent.rs b/vendor/bytemuck/src/transparent.rs
new file mode 100644
index 0000000..5b9fe0e
--- /dev/null
+++ b/vendor/bytemuck/src/transparent.rs
@@ -0,0 +1,288 @@
+use super::*;
+
+/// A trait which indicates that a type is a `#[repr(transparent)]` wrapper
+/// around the `Inner` value.
+///
+/// This allows safely copy transmuting between the `Inner` type and the
+/// `TransparentWrapper` type. Functions like `wrap_{}` convert from the inner
+/// type to the wrapper type and `peel_{}` functions do the inverse conversion
+/// from the wrapper type to the inner type. We deliberately do not call the
+/// wrapper-removing methods "unwrap" because at this point that word is too
+/// strongly tied to the Option/ Result methods.
+///
+/// # Safety
+///
+/// The safety contract of `TransparentWrapper` is relatively simple:
+///
+/// For a given `Wrapper` which implements `TransparentWrapper<Inner>`:
+///
+/// 1. `Wrapper` must be a wrapper around `Inner` with an identical data
+/// representations. This either means that it must be a
+/// `#[repr(transparent)]` struct which contains a either a field of type
+/// `Inner` (or a field of some other transparent wrapper for `Inner`) as
+/// the only non-ZST field.
+///
+/// 2. Any fields *other* than the `Inner` field must be trivially constructable
+/// ZSTs, for example `PhantomData`, `PhantomPinned`, etc. (When deriving
+/// `TransparentWrapper` on a type with ZST fields, the ZST fields must be
+/// [`Zeroable`]).
+///
+/// 3. The `Wrapper` may not impose additional alignment requirements over
+/// `Inner`.
+/// - Note: this is currently guaranteed by `repr(transparent)`, but there
+/// have been discussions of lifting it, so it's stated here explicitly.
+///
+/// 4. All functions on `TransparentWrapper` **may not** be overridden.
+///
+/// ## Caveats
+///
+/// If the wrapper imposes additional constraints upon the inner type which are
+/// required for safety, it's responsible for ensuring those still hold -- this
+/// generally requires preventing access to instances of the inner type, as
+/// implementing `TransparentWrapper<U> for T` means anybody can call
+/// `T::cast_ref(any_instance_of_u)`.
+///
+/// For example, it would be invalid to implement TransparentWrapper for `str`
+/// to implement `TransparentWrapper` around `[u8]` because of this.
+///
+/// # Examples
+///
+/// ## Basic
+///
+/// ```
+/// use bytemuck::TransparentWrapper;
+/// # #[derive(Default)]
+/// # struct SomeStruct(u32);
+///
+/// #[repr(transparent)]
+/// struct MyWrapper(SomeStruct);
+///
+/// unsafe impl TransparentWrapper<SomeStruct> for MyWrapper {}
+///
+/// // interpret a reference to &SomeStruct as a &MyWrapper
+/// let thing = SomeStruct::default();
+/// let inner_ref: &MyWrapper = MyWrapper::wrap_ref(&thing);
+///
+/// // Works with &mut too.
+/// let mut mut_thing = SomeStruct::default();
+/// let inner_mut: &mut MyWrapper = MyWrapper::wrap_mut(&mut mut_thing);
+///
+/// # let _ = (inner_ref, inner_mut); // silence warnings
+/// ```
+///
+/// ## Use with dynamically sized types
+///
+/// ```
+/// use bytemuck::TransparentWrapper;
+///
+/// #[repr(transparent)]
+/// struct Slice<T>([T]);
+///
+/// unsafe impl<T> TransparentWrapper<[T]> for Slice<T> {}
+///
+/// let s = Slice::wrap_ref(&[1u32, 2, 3]);
+/// assert_eq!(&s.0, &[1, 2, 3]);
+///
+/// let mut buf = [1, 2, 3u8];
+/// let sm = Slice::wrap_mut(&mut buf);
+/// ```
+///
+/// ## Deriving
+///
+/// When deriving, the non-wrapped fields must uphold all the normal requirements,
+/// and must also be `Zeroable`.
+///
+#[cfg_attr(feature = "derive", doc = "```")]
+#[cfg_attr(
+ not(feature = "derive"),
+ doc = "```ignore
+// This example requires the `derive` feature."
+)]
+/// use bytemuck::TransparentWrapper;
+/// use std::marker::PhantomData;
+///
+/// #[derive(TransparentWrapper)]
+/// #[repr(transparent)]
+/// #[transparent(usize)]
+/// struct Wrapper<T: ?Sized>(usize, PhantomData<T>); // PhantomData<T> implements Zeroable for all T
+/// ```
+///
+/// Here, an error will occur, because `MyZst` does not implement `Zeroable`.
+///
+#[cfg_attr(feature = "derive", doc = "```compile_fail")]
+#[cfg_attr(
+ not(feature = "derive"),
+ doc = "```ignore
+// This example requires the `derive` feature."
+)]
+/// use bytemuck::TransparentWrapper;
+/// struct MyZst;
+///
+/// #[derive(TransparentWrapper)]
+/// #[repr(transparent)]
+/// #[transparent(usize)]
+/// struct Wrapper(usize, MyZst); // MyZst does not implement Zeroable
+/// ```
+pub unsafe trait TransparentWrapper<Inner: ?Sized> {
+ /// Convert the inner type into the wrapper type.
+ #[inline]
+ fn wrap(s: Inner) -> Self
+ where
+ Self: Sized,
+ Inner: Sized,
+ {
+ // SAFETY: The unsafe contract requires that `Self` and `Inner` have
+ // identical representations.
+ unsafe { transmute!(s) }
+ }
+
+ /// Convert a reference to the inner type into a reference to the wrapper
+ /// type.
+ #[inline]
+ fn wrap_ref(s: &Inner) -> &Self {
+ unsafe {
+ assert!(size_of::<*const Inner>() == size_of::<*const Self>());
+ // A pointer cast doesn't work here because rustc can't tell that
+ // 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 these two have
+ // identical representations.
+ let inner_ptr = s as *const Inner;
+ let wrapper_ptr: *const Self = transmute!(inner_ptr);
+ &*wrapper_ptr
+ }
+ }
+
+ /// Convert a mutable reference to the inner type into a mutable reference to
+ /// the wrapper type.
+ #[inline]
+ fn wrap_mut(s: &mut Inner) -> &mut Self {
+ unsafe {
+ assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
+ // A pointer cast doesn't work here because rustc can't tell that
+ // 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 these two have
+ // identical representations.
+ let inner_ptr = s as *mut Inner;
+ let wrapper_ptr: *mut Self = transmute!(inner_ptr);
+ &mut *wrapper_ptr
+ }
+ }
+
+ /// Convert a slice to the inner type into a slice to the wrapper type.
+ #[inline]
+ fn wrap_slice(s: &[Inner]) -> &[Self]
+ where
+ Self: Sized,
+ Inner: Sized,
+ {
+ unsafe {
+ assert!(size_of::<*const Inner>() == size_of::<*const Self>());
+ assert!(align_of::<*const Inner>() == align_of::<*const Self>());
+ // SAFETY: The unsafe contract requires that these two have
+ // identical representations (size and alignment).
+ core::slice::from_raw_parts(s.as_ptr() as *const Self, s.len())
+ }
+ }
+
+ /// Convert a mutable slice to the inner type into a mutable slice to the
+ /// wrapper type.
+ #[inline]
+ fn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self]
+ where
+ Self: Sized,
+ Inner: Sized,
+ {
+ unsafe {
+ assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
+ assert!(align_of::<*mut Inner>() == align_of::<*mut Self>());
+ // SAFETY: The unsafe contract requires that these two have
+ // identical representations (size and alignment).
+ core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Self, s.len())
+ }
+ }
+
+ /// Convert the wrapper type into the inner type.
+ #[inline]
+ fn peel(s: Self) -> Inner
+ where
+ Self: Sized,
+ Inner: Sized,
+ {
+ unsafe { transmute!(s) }
+ }
+
+ /// Convert a reference to the wrapper type into a reference to the inner
+ /// type.
+ #[inline]
+ fn peel_ref(s: &Self) -> &Inner {
+ unsafe {
+ assert!(size_of::<*const Inner>() == size_of::<*const Self>());
+ // A pointer cast doesn't work here because rustc can't tell that
+ // 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 these two have
+ // identical representations.
+ let wrapper_ptr = s as *const Self;
+ let inner_ptr: *const Inner = transmute!(wrapper_ptr);
+ &*inner_ptr
+ }
+ }
+
+ /// Convert a mutable reference to the wrapper type into a mutable reference
+ /// to the inner type.
+ #[inline]
+ fn peel_mut(s: &mut Self) -> &mut Inner {
+ unsafe {
+ assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
+ // A pointer cast doesn't work here because rustc can't tell that
+ // 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 these two have
+ // identical representations.
+ let wrapper_ptr = s as *mut Self;
+ let inner_ptr: *mut Inner = transmute!(wrapper_ptr);
+ &mut *inner_ptr
+ }
+ }
+
+ /// Convert a slice to the wrapped type into a slice to the inner type.
+ #[inline]
+ fn peel_slice(s: &[Self]) -> &[Inner]
+ where
+ Self: Sized,
+ Inner: Sized,
+ {
+ unsafe {
+ assert!(size_of::<*const Inner>() == size_of::<*const Self>());
+ assert!(align_of::<*const Inner>() == align_of::<*const Self>());
+ // SAFETY: The unsafe contract requires that these two have
+ // identical representations (size and alignment).
+ core::slice::from_raw_parts(s.as_ptr() as *const Inner, s.len())
+ }
+ }
+
+ /// Convert a mutable slice to the wrapped type into a mutable slice to the
+ /// inner type.
+ #[inline]
+ fn peel_slice_mut(s: &mut [Self]) -> &mut [Inner]
+ where
+ Self: Sized,
+ Inner: Sized,
+ {
+ unsafe {
+ assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
+ assert!(align_of::<*mut Inner>() == align_of::<*mut Self>());
+ // SAFETY: The unsafe contract requires that these two have
+ // identical representations (size and alignment).
+ core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Inner, s.len())
+ }
+ }
+}
+
+unsafe impl<T> TransparentWrapper<T> for core::num::Wrapping<T> {}