1 use 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 /// ```
124 pub unsafe trait TransparentWrapper<Inner: ?Sized> {
125   /// Convert the inner type into the wrapper type.
126   #[inline]
wrap(s: Inner) -> Self where Self: Sized, Inner: Sized,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]
wrap_ref(s: &Inner) -> &Self142   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]
wrap_mut(s: &mut Inner) -> &mut Self165   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]
wrap_slice(s: &[Inner]) -> &[Self] where Self: Sized, Inner: Sized,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]
wrap_slice_mut(s: &mut [Inner]) -> &mut [Self] where Self: Sized, Inner: Sized,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]
peel(s: Self) -> Inner where Self: Sized, Inner: Sized,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]
peel_ref(s: &Self) -> &Inner232   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]
peel_mut(s: &mut Self) -> &mut Inner254   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]
peel_slice(s: &[Self]) -> &[Inner] where Self: Sized, Inner: Sized,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]
peel_slice_mut(s: &mut [Self]) -> &mut [Inner] where Self: Sized, Inner: Sized,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 
305 unsafe impl<T> TransparentWrapper<T> for core::num::Wrapping<T> {}
306