Coverage Report

Created: 2025-07-18 06:49

/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> {}