Trait bytemuck::TransparentWrapper
source · pub unsafe trait TransparentWrapper<Inner: ?Sized> {
// Provided methods
fn wrap(s: Inner) -> Self
where Self: Sized,
Inner: Sized { ... }
fn wrap_ref(s: &Inner) -> &Self { ... }
fn wrap_mut(s: &mut Inner) -> &mut Self { ... }
fn wrap_slice(s: &[Inner]) -> &[Self]
where Self: Sized,
Inner: Sized { ... }
fn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self]
where Self: Sized,
Inner: Sized { ... }
fn peel(s: Self) -> Inner
where Self: Sized,
Inner: Sized { ... }
fn peel_ref(s: &Self) -> &Inner { ... }
fn peel_mut(s: &mut Self) -> &mut Inner { ... }
fn peel_slice(s: &[Self]) -> &[Inner]
where Self: Sized,
Inner: Sized { ... }
fn peel_slice_mut(s: &mut [Self]) -> &mut [Inner]
where Self: Sized,
Inner: Sized { ... }
}
Expand description
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>
:
-
Wrapper
must be a wrapper aroundInner
with an identical data representations. This either means that it must be a#[repr(transparent)]
struct which contains a either a field of typeInner
(or a field of some other transparent wrapper forInner
) as the only non-ZST field. -
Any fields other than the
Inner
field must be trivially constructable ZSTs, for examplePhantomData
,PhantomPinned
, etc. (When derivingTransparentWrapper
on a type with ZST fields, the ZST fields must beZeroable
). -
The
Wrapper
may not impose additional alignment requirements overInner
.- Note: this is currently guaranteed by
repr(transparent)
, but there have been discussions of lifting it, so it’s stated here explicitly.
- Note: this is currently guaranteed by
-
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;
#[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);
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
.
// 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
.
// 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
Provided Methods§
sourcefn wrap(s: Inner) -> Selfwhere
Self: Sized,
Inner: Sized,
fn wrap(s: Inner) -> Selfwhere Self: Sized, Inner: Sized,
Convert the inner type into the wrapper type.
sourcefn wrap_ref(s: &Inner) -> &Self
fn wrap_ref(s: &Inner) -> &Self
Convert a reference to the inner type into a reference to the wrapper type.
sourcefn wrap_mut(s: &mut Inner) -> &mut Self
fn wrap_mut(s: &mut Inner) -> &mut Self
Convert a mutable reference to the inner type into a mutable reference to the wrapper type.
sourcefn wrap_slice(s: &[Inner]) -> &[Self]where
Self: Sized,
Inner: Sized,
fn wrap_slice(s: &[Inner]) -> &[Self]where Self: Sized, Inner: Sized,
Convert a slice to the inner type into a slice to the wrapper type.
sourcefn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self]where
Self: Sized,
Inner: Sized,
fn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self]where Self: Sized, Inner: Sized,
Convert a mutable slice to the inner type into a mutable slice to the wrapper type.
sourcefn peel(s: Self) -> Innerwhere
Self: Sized,
Inner: Sized,
fn peel(s: Self) -> Innerwhere Self: Sized, Inner: Sized,
Convert the wrapper type into the inner type.
sourcefn peel_ref(s: &Self) -> &Inner
fn peel_ref(s: &Self) -> &Inner
Convert a reference to the wrapper type into a reference to the inner type.
sourcefn peel_mut(s: &mut Self) -> &mut Inner
fn peel_mut(s: &mut Self) -> &mut Inner
Convert a mutable reference to the wrapper type into a mutable reference to the inner type.