bytemuck/
transparent.rs

1use super::*;
2
3/// A trait which indicates that a type is a `#[repr(transparent)]` wrapper
4/// around the `Inner` value.
5///
6/// This allows safely copy transmuting between the `Inner` type and the
7/// `TransparentWrapper` type. Functions like `wrap_{}` convert from the inner
8/// type to the wrapper type and `peel_{}` functions do the inverse conversion
9/// from the wrapper type to the inner type. We deliberately do not call the
10/// wrapper-removing methods "unwrap" because at this point that word is too
11/// strongly tied to the Option/ Result methods.
12///
13/// # Safety
14///
15/// The safety contract of `TransparentWrapper` is relatively simple:
16///
17/// For a given `Wrapper` which implements `TransparentWrapper<Inner>`:
18///
19/// 1. `Wrapper` must be a wrapper around `Inner` with an identical data
20///    representations. This    either means that it must be a
21///    `#[repr(transparent)]` struct which    contains a either a field of type
22///    `Inner` (or a field of some other    transparent wrapper for `Inner`) as
23///    the only non-ZST field.
24///
25/// 2. Any fields *other* than the `Inner` field must be trivially constructable
26///    ZSTs, for example `PhantomData`, `PhantomPinned`, etc. (When deriving
27///    `TransparentWrapper` on a type with ZST fields, the ZST fields must be
28///    [`Zeroable`]).
29///
30/// 3. The `Wrapper` may not impose additional alignment requirements over
31///    `Inner`.
32///     - Note: this is currently guaranteed by `repr(transparent)`, but there
33///       have been discussions of lifting it, so it's stated here explicitly.
34///
35/// 4. All functions on `TransparentWrapper` **may not** be overridden.
36///
37/// ## Caveats
38///
39/// If the wrapper imposes additional constraints upon the inner type which are
40/// required for safety, it's responsible for ensuring those still hold -- this
41/// generally requires preventing access to instances of the inner type, as
42/// implementing `TransparentWrapper<U> for T` means anybody can call
43/// `T::cast_ref(any_instance_of_u)`.
44///
45/// For example, it would be invalid to implement TransparentWrapper for `str`
46/// to implement `TransparentWrapper` around `[u8]` because of this.
47///
48/// # Examples
49///
50/// ## Basic
51///
52/// ```
53/// use bytemuck::TransparentWrapper;
54/// # #[derive(Default)]
55/// # struct SomeStruct(u32);
56///
57/// #[repr(transparent)]
58/// struct MyWrapper(SomeStruct);
59///
60/// unsafe impl TransparentWrapper<SomeStruct> for MyWrapper {}
61///
62/// // interpret a reference to &SomeStruct as a &MyWrapper
63/// let thing = SomeStruct::default();
64/// let inner_ref: &MyWrapper = MyWrapper::wrap_ref(&thing);
65///
66/// // Works with &mut too.
67/// let mut mut_thing = SomeStruct::default();
68/// let inner_mut: &mut MyWrapper = MyWrapper::wrap_mut(&mut mut_thing);
69///
70/// # let _ = (inner_ref, inner_mut); // silence warnings
71/// ```
72///
73/// ## Use with dynamically sized types
74///
75/// ```
76/// use bytemuck::TransparentWrapper;
77///
78/// #[repr(transparent)]
79/// struct Slice<T>([T]);
80///
81/// unsafe impl<T> TransparentWrapper<[T]> for Slice<T> {}
82///
83/// let s = Slice::wrap_ref(&[1u32, 2, 3]);
84/// assert_eq!(&s.0, &[1, 2, 3]);
85///
86/// let mut buf = [1, 2, 3u8];
87/// let sm = Slice::wrap_mut(&mut buf);
88/// ```
89///
90/// ## Deriving
91///
92/// When deriving, the non-wrapped fields must uphold all the normal
93/// requirements, and must also be `Zeroable`.
94#[cfg_attr(feature = "derive", doc = "```")]
95#[cfg_attr(
96  not(feature = "derive"),
97  doc = "```ignore
98// This example requires the `derive` feature."
99)]
100/// use bytemuck::TransparentWrapper;
101/// use std::marker::PhantomData;
102///
103/// #[derive(TransparentWrapper)]
104/// #[repr(transparent)]
105/// #[transparent(usize)]
106/// struct Wrapper<T: ?Sized>(usize, PhantomData<T>); // PhantomData<T> implements Zeroable for all T
107/// ```
108///
109/// Here, an error will occur, because `MyZst` does not implement `Zeroable`.
110#[cfg_attr(feature = "derive", doc = "```compile_fail")]
111#[cfg_attr(
112  not(feature = "derive"),
113  doc = "```ignore
114// This example requires the `derive` feature."
115)]
116/// use bytemuck::TransparentWrapper;
117/// struct MyZst;
118///
119/// #[derive(TransparentWrapper)]
120/// #[repr(transparent)]
121/// #[transparent(usize)]
122/// struct Wrapper(usize, MyZst); // MyZst does not implement Zeroable
123/// ```
124pub unsafe trait TransparentWrapper<Inner: ?Sized> {
125  /// Convert the inner type into the wrapper type.
126  #[inline]
127  fn wrap(s: Inner) -> Self
128  where
129    Self: Sized,
130    Inner: Sized,
131  {
132    assert!(size_of::<Inner>() == size_of::<Self>());
133    assert!(align_of::<Inner>() == align_of::<Self>());
134    // SAFETY: The unsafe contract requires that `Self` and `Inner` have
135    // identical representations.
136    unsafe { transmute!(s) }
137  }
138
139  /// Convert a reference to the inner type into a reference to the wrapper
140  /// type.
141  #[inline]
142  fn wrap_ref(s: &Inner) -> &Self {
143    // The unsafe contract requires that these two have
144    // identical representations, and thus identical pointer metadata.
145    // Assert that Self and Inner have the same pointer size,
146    // which is the best we can do to assert their metadata is the same type
147    // on stable.
148    assert!(size_of::<*const Inner>() == size_of::<*const Self>());
149    unsafe {
150      // A pointer cast doesn't work here because rustc can't tell that
151      // the vtables match (because of the `?Sized` restriction relaxation).
152      // A `transmute` doesn't work because the sizes are unspecified.
153      //
154      // SAFETY: The unsafe contract requires that these two have
155      // identical representations.
156      let inner_ptr = s as *const Inner;
157      let wrapper_ptr: *const Self = transmute!(inner_ptr);
158      &*wrapper_ptr
159    }
160  }
161
162  /// Convert a mutable reference to the inner type into a mutable reference to
163  /// the wrapper type.
164  #[inline]
165  fn wrap_mut(s: &mut Inner) -> &mut Self {
166    // The unsafe contract requires that these two have
167    // identical representations, and thus identical pointer metadata.
168    // Assert that Self and Inner have the same pointer size,
169    // which is about the best we can do on stable.
170    assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
171    unsafe {
172      // A pointer cast doesn't work here because rustc can't tell that
173      // the vtables match (because of the `?Sized` restriction relaxation).
174      // A `transmute` doesn't work because the sizes are unspecified.
175      //
176      // SAFETY: The unsafe contract requires that these two have
177      // identical representations.
178      let inner_ptr = s as *mut Inner;
179      let wrapper_ptr: *mut Self = transmute!(inner_ptr);
180      &mut *wrapper_ptr
181    }
182  }
183
184  /// Convert a slice to the inner type into a slice to the wrapper type.
185  #[inline]
186  fn wrap_slice(s: &[Inner]) -> &[Self]
187  where
188    Self: Sized,
189    Inner: Sized,
190  {
191    assert!(size_of::<Inner>() == size_of::<Self>());
192    assert!(align_of::<Inner>() == align_of::<Self>());
193    // SAFETY: The unsafe contract requires that these two have
194    // identical representations (size and alignment).
195    unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Self, s.len()) }
196  }
197
198  /// Convert a mutable slice to the inner type into a mutable slice to the
199  /// wrapper type.
200  #[inline]
201  fn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self]
202  where
203    Self: Sized,
204    Inner: Sized,
205  {
206    assert!(size_of::<Inner>() == size_of::<Self>());
207    assert!(align_of::<Inner>() == align_of::<Self>());
208    // SAFETY: The unsafe contract requires that these two have
209    // identical representations (size and alignment).
210    unsafe {
211      core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Self, s.len())
212    }
213  }
214
215  /// Convert the wrapper type into the inner type.
216  #[inline]
217  fn peel(s: Self) -> Inner
218  where
219    Self: Sized,
220    Inner: Sized,
221  {
222    assert!(size_of::<Inner>() == size_of::<Self>());
223    assert!(align_of::<Inner>() == align_of::<Self>());
224    // SAFETY: The unsafe contract requires that `Self` and `Inner` have
225    // identical representations.
226    unsafe { transmute!(s) }
227  }
228
229  /// Convert a reference to the wrapper type into a reference to the inner
230  /// type.
231  #[inline]
232  fn peel_ref(s: &Self) -> &Inner {
233    // The unsafe contract requires that these two have
234    // identical representations, and thus identical pointer metadata.
235    // Assert that Self and Inner have the same pointer size,
236    // which is about the best we can do on stable.
237    assert!(size_of::<*const Inner>() == size_of::<*const Self>());
238    unsafe {
239      // A pointer cast doesn't work here because rustc can't tell that
240      // the vtables match (because of the `?Sized` restriction relaxation).
241      // A `transmute` doesn't work because the sizes are unspecified.
242      //
243      // SAFETY: The unsafe contract requires that these two have
244      // identical representations.
245      let wrapper_ptr = s as *const Self;
246      let inner_ptr: *const Inner = transmute!(wrapper_ptr);
247      &*inner_ptr
248    }
249  }
250
251  /// Convert a mutable reference to the wrapper type into a mutable reference
252  /// to the inner type.
253  #[inline]
254  fn peel_mut(s: &mut Self) -> &mut Inner {
255    // The unsafe contract requires that these two have
256    // identical representations, and thus identical pointer metadata.
257    // Assert that Self and Inner have the same pointer size,
258    // which is about the best we can do on stable.
259    assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
260    unsafe {
261      // A pointer cast doesn't work here because rustc can't tell that
262      // the vtables match (because of the `?Sized` restriction relaxation).
263      // A `transmute` doesn't work because the sizes are unspecified.
264      //
265      // SAFETY: The unsafe contract requires that these two have
266      // identical representations.
267      let wrapper_ptr = s as *mut Self;
268      let inner_ptr: *mut Inner = transmute!(wrapper_ptr);
269      &mut *inner_ptr
270    }
271  }
272
273  /// Convert a slice to the wrapped type into a slice to the inner type.
274  #[inline]
275  fn peel_slice(s: &[Self]) -> &[Inner]
276  where
277    Self: Sized,
278    Inner: Sized,
279  {
280    assert!(size_of::<Inner>() == size_of::<Self>());
281    assert!(align_of::<Inner>() == align_of::<Self>());
282    // SAFETY: The unsafe contract requires that these two have
283    // identical representations (size and alignment).
284    unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Inner, s.len()) }
285  }
286
287  /// Convert a mutable slice to the wrapped type into a mutable slice to the
288  /// inner type.
289  #[inline]
290  fn peel_slice_mut(s: &mut [Self]) -> &mut [Inner]
291  where
292    Self: Sized,
293    Inner: Sized,
294  {
295    assert!(size_of::<Inner>() == size_of::<Self>());
296    assert!(align_of::<Inner>() == align_of::<Self>());
297    // SAFETY: The unsafe contract requires that these two have
298    // identical representations (size and alignment).
299    unsafe {
300      core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Inner, s.len())
301    }
302  }
303}
304
305unsafe impl<T> TransparentWrapper<T> for core::num::Wrapping<T> {}
306#[cfg(feature = "transparentwrapper_extra")]
307#[cfg_attr(
308  feature = "nightly_docs",
309  doc(cfg(feature = "transparentwrapper_extra"))
310)]
311unsafe impl<T> TransparentWrapper<T> for core::num::Saturating<T> {}
312
313// Note that `Reverse` existed since Rust 1.19.0, but was only made `#[repr(transparent)]`
314// in Rust 1.52.0 (PR: https://github.com/rust-lang/rust/pull/81879), so we have it under
315// the same feature as `Saturating`, which was stabilized in Rust 1.74.0, so that this
316// impl cannot be used on a version before 1.52.0 where it would be unsound.
317#[cfg(feature = "transparentwrapper_extra")]
318#[cfg_attr(
319  feature = "nightly_docs",
320  doc(cfg(feature = "transparentwrapper_extra"))
321)]
322unsafe impl<T> TransparentWrapper<T> for core::cmp::Reverse<T> {}