/rust/registry/src/index.crates.io-6f17d22bba15001f/bytemuck-1.23.1/src/transparent.rs
Line | Count | Source (jump to first uncovered line) |
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 | 0 | fn wrap(s: Inner) -> Self |
128 | 0 | where |
129 | 0 | Self: Sized, |
130 | 0 | Inner: Sized, |
131 | 0 | { |
132 | 0 | assert!(size_of::<Inner>() == size_of::<Self>()); |
133 | 0 | assert!(align_of::<Inner>() == align_of::<Self>()); |
134 | | // SAFETY: The unsafe contract requires that `Self` and `Inner` have |
135 | | // identical representations. |
136 | 0 | unsafe { transmute!(s) } |
137 | 0 | } |
138 | | |
139 | | /// Convert a reference to the inner type into a reference to the wrapper |
140 | | /// type. |
141 | | #[inline] |
142 | 0 | fn wrap_ref(s: &Inner) -> &Self { |
143 | 0 | // The unsafe contract requires that these two have |
144 | 0 | // identical representations, and thus identical pointer metadata. |
145 | 0 | // Assert that Self and Inner have the same pointer size, |
146 | 0 | // which is the best we can do to assert their metadata is the same type |
147 | 0 | // on stable. |
148 | 0 | 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 | 0 | let inner_ptr = s as *const Inner; |
157 | 0 | let wrapper_ptr: *const Self = transmute!(inner_ptr); |
158 | 0 | &*wrapper_ptr |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | | /// Convert a mutable reference to the inner type into a mutable reference to |
163 | | /// the wrapper type. |
164 | | #[inline] |
165 | 0 | fn wrap_mut(s: &mut Inner) -> &mut Self { |
166 | 0 | // The unsafe contract requires that these two have |
167 | 0 | // identical representations, and thus identical pointer metadata. |
168 | 0 | // Assert that Self and Inner have the same pointer size, |
169 | 0 | // which is about the best we can do on stable. |
170 | 0 | assert!(size_of::<*mut Inner>() == size_of::<*mut Self>()); |
171 | 0 | unsafe { |
172 | 0 | // A pointer cast doesn't work here because rustc can't tell that |
173 | 0 | // the vtables match (because of the `?Sized` restriction relaxation). |
174 | 0 | // A `transmute` doesn't work because the sizes are unspecified. |
175 | 0 | // |
176 | 0 | // SAFETY: The unsafe contract requires that these two have |
177 | 0 | // identical representations. |
178 | 0 | let inner_ptr = s as *mut Inner; |
179 | 0 | let wrapper_ptr: *mut Self = transmute!(inner_ptr); |
180 | 0 | &mut *wrapper_ptr |
181 | 0 | } |
182 | 0 | } |
183 | | |
184 | | /// Convert a slice to the inner type into a slice to the wrapper type. |
185 | | #[inline] |
186 | 0 | fn wrap_slice(s: &[Inner]) -> &[Self] |
187 | 0 | where |
188 | 0 | Self: Sized, |
189 | 0 | Inner: Sized, |
190 | 0 | { |
191 | 0 | assert!(size_of::<Inner>() == size_of::<Self>()); |
192 | 0 | assert!(align_of::<Inner>() == align_of::<Self>()); |
193 | | // SAFETY: The unsafe contract requires that these two have |
194 | | // identical representations (size and alignment). |
195 | 0 | unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Self, s.len()) } |
196 | 0 | } |
197 | | |
198 | | /// Convert a mutable slice to the inner type into a mutable slice to the |
199 | | /// wrapper type. |
200 | | #[inline] |
201 | 0 | fn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self] |
202 | 0 | where |
203 | 0 | Self: Sized, |
204 | 0 | Inner: Sized, |
205 | 0 | { |
206 | 0 | assert!(size_of::<Inner>() == size_of::<Self>()); |
207 | 0 | assert!(align_of::<Inner>() == align_of::<Self>()); |
208 | | // SAFETY: The unsafe contract requires that these two have |
209 | | // identical representations (size and alignment). |
210 | 0 | unsafe { |
211 | 0 | core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Self, s.len()) |
212 | 0 | } |
213 | 0 | } |
214 | | |
215 | | /// Convert the wrapper type into the inner type. |
216 | | #[inline] |
217 | 0 | fn peel(s: Self) -> Inner |
218 | 0 | where |
219 | 0 | Self: Sized, |
220 | 0 | Inner: Sized, |
221 | 0 | { |
222 | 0 | assert!(size_of::<Inner>() == size_of::<Self>()); |
223 | 0 | assert!(align_of::<Inner>() == align_of::<Self>()); |
224 | | // SAFETY: The unsafe contract requires that `Self` and `Inner` have |
225 | | // identical representations. |
226 | 0 | unsafe { transmute!(s) } |
227 | 0 | } |
228 | | |
229 | | /// Convert a reference to the wrapper type into a reference to the inner |
230 | | /// type. |
231 | | #[inline] |
232 | 0 | fn peel_ref(s: &Self) -> &Inner { |
233 | 0 | // The unsafe contract requires that these two have |
234 | 0 | // identical representations, and thus identical pointer metadata. |
235 | 0 | // Assert that Self and Inner have the same pointer size, |
236 | 0 | // which is about the best we can do on stable. |
237 | 0 | 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 | 0 | let wrapper_ptr = s as *const Self; |
246 | 0 | let inner_ptr: *const Inner = transmute!(wrapper_ptr); |
247 | 0 | &*inner_ptr |
248 | 0 | } |
249 | 0 | } |
250 | | |
251 | | /// Convert a mutable reference to the wrapper type into a mutable reference |
252 | | /// to the inner type. |
253 | | #[inline] |
254 | 0 | fn peel_mut(s: &mut Self) -> &mut Inner { |
255 | 0 | // The unsafe contract requires that these two have |
256 | 0 | // identical representations, and thus identical pointer metadata. |
257 | 0 | // Assert that Self and Inner have the same pointer size, |
258 | 0 | // which is about the best we can do on stable. |
259 | 0 | assert!(size_of::<*mut Inner>() == size_of::<*mut Self>()); |
260 | 0 | unsafe { |
261 | 0 | // A pointer cast doesn't work here because rustc can't tell that |
262 | 0 | // the vtables match (because of the `?Sized` restriction relaxation). |
263 | 0 | // A `transmute` doesn't work because the sizes are unspecified. |
264 | 0 | // |
265 | 0 | // SAFETY: The unsafe contract requires that these two have |
266 | 0 | // identical representations. |
267 | 0 | let wrapper_ptr = s as *mut Self; |
268 | 0 | let inner_ptr: *mut Inner = transmute!(wrapper_ptr); |
269 | 0 | &mut *inner_ptr |
270 | 0 | } |
271 | 0 | } |
272 | | |
273 | | /// Convert a slice to the wrapped type into a slice to the inner type. |
274 | | #[inline] |
275 | 0 | fn peel_slice(s: &[Self]) -> &[Inner] |
276 | 0 | where |
277 | 0 | Self: Sized, |
278 | 0 | Inner: Sized, |
279 | 0 | { |
280 | 0 | assert!(size_of::<Inner>() == size_of::<Self>()); |
281 | 0 | assert!(align_of::<Inner>() == align_of::<Self>()); |
282 | | // SAFETY: The unsafe contract requires that these two have |
283 | | // identical representations (size and alignment). |
284 | 0 | unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Inner, s.len()) } |
285 | 0 | } |
286 | | |
287 | | /// Convert a mutable slice to the wrapped type into a mutable slice to the |
288 | | /// inner type. |
289 | | #[inline] |
290 | 0 | fn peel_slice_mut(s: &mut [Self]) -> &mut [Inner] |
291 | 0 | where |
292 | 0 | Self: Sized, |
293 | 0 | Inner: Sized, |
294 | 0 | { |
295 | 0 | assert!(size_of::<Inner>() == size_of::<Self>()); |
296 | 0 | assert!(align_of::<Inner>() == align_of::<Self>()); |
297 | | // SAFETY: The unsafe contract requires that these two have |
298 | | // identical representations (size and alignment). |
299 | 0 | unsafe { |
300 | 0 | core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Inner, s.len()) |
301 | 0 | } |
302 | 0 | } |
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> {} |