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 requirements,
|
93 | /// and must also be `Zeroable`.
|
94 | ///
|
95 | #[cfg_attr (feature = "derive" , doc = "```" )]
|
96 | #[cfg_attr (
|
97 | not(feature = "derive" ),
|
98 | doc = "```ignore
|
99 | // This example requires the `derive` feature."
|
100 | )]
|
101 | /// use bytemuck::TransparentWrapper;
|
102 | /// use std::marker::PhantomData;
|
103 | ///
|
104 | /// #[derive(TransparentWrapper)]
|
105 | /// #[repr(transparent)]
|
106 | /// #[transparent(usize)]
|
107 | /// struct Wrapper<T: ?Sized>(usize, PhantomData<T>); // PhantomData<T> implements Zeroable for all T
|
108 | /// ```
|
109 | ///
|
110 | /// Here, an error will occur, because `MyZst` does not implement `Zeroable`.
|
111 | ///
|
112 | #[cfg_attr (feature = "derive" , doc = "```compile_fail" )]
|
113 | #[cfg_attr (
|
114 | not(feature = "derive" ),
|
115 | doc = "```ignore
|
116 | // This example requires the `derive` feature."
|
117 | )]
|
118 | /// use bytemuck::TransparentWrapper;
|
119 | /// struct MyZst;
|
120 | ///
|
121 | /// #[derive(TransparentWrapper)]
|
122 | /// #[repr(transparent)]
|
123 | /// #[transparent(usize)]
|
124 | /// struct Wrapper(usize, MyZst); // MyZst does not implement Zeroable
|
125 | /// ```
|
126 | pub unsafe trait TransparentWrapper<Inner: ?Sized> {
|
127 | /// Convert the inner type into the wrapper type.
|
128 | #[inline ]
|
129 | fn wrap(s: Inner) -> Self
|
130 | where
|
131 | Self: Sized,
|
132 | Inner: Sized,
|
133 | {
|
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 | unsafe {
|
144 | assert!(size_of::<*const Inner>() == size_of::<*const Self>());
|
145 | // A pointer cast doesn't work here because rustc can't tell that
|
146 | // the vtables match (because of the `?Sized` restriction relaxation).
|
147 | // A `transmute` doesn't work because the sizes are unspecified.
|
148 | //
|
149 | // SAFETY: The unsafe contract requires that these two have
|
150 | // identical representations.
|
151 | let inner_ptr = s as *const Inner;
|
152 | let wrapper_ptr: *const Self = transmute!(inner_ptr);
|
153 | &*wrapper_ptr
|
154 | }
|
155 | }
|
156 |
|
157 | /// Convert a mutable reference to the inner type into a mutable reference to
|
158 | /// the wrapper type.
|
159 | #[inline ]
|
160 | fn wrap_mut(s: &mut Inner) -> &mut Self {
|
161 | unsafe {
|
162 | assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
|
163 | // A pointer cast doesn't work here because rustc can't tell that
|
164 | // the vtables match (because of the `?Sized` restriction relaxation).
|
165 | // A `transmute` doesn't work because the sizes are unspecified.
|
166 | //
|
167 | // SAFETY: The unsafe contract requires that these two have
|
168 | // identical representations.
|
169 | let inner_ptr = s as *mut Inner;
|
170 | let wrapper_ptr: *mut Self = transmute!(inner_ptr);
|
171 | &mut *wrapper_ptr
|
172 | }
|
173 | }
|
174 |
|
175 | /// Convert a slice to the inner type into a slice to the wrapper type.
|
176 | #[inline ]
|
177 | fn wrap_slice(s: &[Inner]) -> &[Self]
|
178 | where
|
179 | Self: Sized,
|
180 | Inner: Sized,
|
181 | {
|
182 | unsafe {
|
183 | assert!(size_of::<*const Inner>() == size_of::<*const Self>());
|
184 | assert!(align_of::<*const Inner>() == align_of::<*const Self>());
|
185 | // SAFETY: The unsafe contract requires that these two have
|
186 | // identical representations (size and alignment).
|
187 | core::slice::from_raw_parts(s.as_ptr() as *const Self, s.len())
|
188 | }
|
189 | }
|
190 |
|
191 | /// Convert a mutable slice to the inner type into a mutable slice to the
|
192 | /// wrapper type.
|
193 | #[inline ]
|
194 | fn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self]
|
195 | where
|
196 | Self: Sized,
|
197 | Inner: Sized,
|
198 | {
|
199 | unsafe {
|
200 | assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
|
201 | assert!(align_of::<*mut Inner>() == align_of::<*mut Self>());
|
202 | // SAFETY: The unsafe contract requires that these two have
|
203 | // identical representations (size and alignment).
|
204 | core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Self, s.len())
|
205 | }
|
206 | }
|
207 |
|
208 | /// Convert the wrapper type into the inner type.
|
209 | #[inline ]
|
210 | fn peel(s: Self) -> Inner
|
211 | where
|
212 | Self: Sized,
|
213 | Inner: Sized,
|
214 | {
|
215 | unsafe { transmute!(s) }
|
216 | }
|
217 |
|
218 | /// Convert a reference to the wrapper type into a reference to the inner
|
219 | /// type.
|
220 | #[inline ]
|
221 | fn peel_ref(s: &Self) -> &Inner {
|
222 | unsafe {
|
223 | assert!(size_of::<*const Inner>() == size_of::<*const Self>());
|
224 | // A pointer cast doesn't work here because rustc can't tell that
|
225 | // the vtables match (because of the `?Sized` restriction relaxation).
|
226 | // A `transmute` doesn't work because the sizes are unspecified.
|
227 | //
|
228 | // SAFETY: The unsafe contract requires that these two have
|
229 | // identical representations.
|
230 | let wrapper_ptr = s as *const Self;
|
231 | let inner_ptr: *const Inner = transmute!(wrapper_ptr);
|
232 | &*inner_ptr
|
233 | }
|
234 | }
|
235 |
|
236 | /// Convert a mutable reference to the wrapper type into a mutable reference
|
237 | /// to the inner type.
|
238 | #[inline ]
|
239 | fn peel_mut(s: &mut Self) -> &mut Inner {
|
240 | unsafe {
|
241 | assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
|
242 | // A pointer cast doesn't work here because rustc can't tell that
|
243 | // the vtables match (because of the `?Sized` restriction relaxation).
|
244 | // A `transmute` doesn't work because the sizes are unspecified.
|
245 | //
|
246 | // SAFETY: The unsafe contract requires that these two have
|
247 | // identical representations.
|
248 | let wrapper_ptr = s as *mut Self;
|
249 | let inner_ptr: *mut Inner = transmute!(wrapper_ptr);
|
250 | &mut *inner_ptr
|
251 | }
|
252 | }
|
253 |
|
254 | /// Convert a slice to the wrapped type into a slice to the inner type.
|
255 | #[inline ]
|
256 | fn peel_slice(s: &[Self]) -> &[Inner]
|
257 | where
|
258 | Self: Sized,
|
259 | Inner: Sized,
|
260 | {
|
261 | unsafe {
|
262 | assert!(size_of::<*const Inner>() == size_of::<*const Self>());
|
263 | assert!(align_of::<*const Inner>() == align_of::<*const Self>());
|
264 | // SAFETY: The unsafe contract requires that these two have
|
265 | // identical representations (size and alignment).
|
266 | core::slice::from_raw_parts(s.as_ptr() as *const Inner, s.len())
|
267 | }
|
268 | }
|
269 |
|
270 | /// Convert a mutable slice to the wrapped type into a mutable slice to the
|
271 | /// inner type.
|
272 | #[inline ]
|
273 | fn peel_slice_mut(s: &mut [Self]) -> &mut [Inner]
|
274 | where
|
275 | Self: Sized,
|
276 | Inner: Sized,
|
277 | {
|
278 | unsafe {
|
279 | assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
|
280 | assert!(align_of::<*mut Inner>() == align_of::<*mut Self>());
|
281 | // SAFETY: The unsafe contract requires that these two have
|
282 | // identical representations (size and alignment).
|
283 | core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Inner, s.len())
|
284 | }
|
285 | }
|
286 | }
|
287 |
|
288 | unsafe impl<T> TransparentWrapper<T> for core::num::Wrapping<T> {}
|
289 | |