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 ]
|
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 |
|
305 | unsafe 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 | )]
|
311 | unsafe 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 | )]
|
322 | unsafe impl<T> TransparentWrapper<T> for core::cmp::Reverse<T> {}
|
323 | |