bytemuck/
transparent.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
use super::*;

/// A trait which indicates that a type is a `#[repr(transparent)]` wrapper
/// around the `Inner` value.
///
/// This allows safely copy transmuting between the `Inner` type and the
/// `TransparentWrapper` type. Functions like `wrap_{}` convert from the inner
/// type to the wrapper type and `peel_{}` functions do the inverse conversion
/// from the wrapper type to the inner type. We deliberately do not call the
/// wrapper-removing methods "unwrap" because at this point that word is too
/// strongly tied to the Option/ Result methods.
///
/// # Safety
///
/// The safety contract of `TransparentWrapper` is relatively simple:
///
/// For a given `Wrapper` which implements `TransparentWrapper<Inner>`:
///
/// 1. `Wrapper` must be a wrapper around `Inner` with an identical data
///    representations. This    either means that it must be a
///    `#[repr(transparent)]` struct which    contains a either a field of type
///    `Inner` (or a field of some other    transparent wrapper for `Inner`) as
///    the only non-ZST field.
///
/// 2. Any fields *other* than the `Inner` field must be trivially constructable
///    ZSTs, for example `PhantomData`, `PhantomPinned`, etc. (When deriving
///    `TransparentWrapper` on a type with ZST fields, the ZST fields must be
///    [`Zeroable`]).
///
/// 3. The `Wrapper` may not impose additional alignment requirements over
///    `Inner`.
///     - Note: this is currently guaranteed by `repr(transparent)`, but there
///       have been discussions of lifting it, so it's stated here explicitly.
///
/// 4. All functions on `TransparentWrapper` **may not** be overridden.
///
/// ## Caveats
///
/// If the wrapper imposes additional constraints upon the inner type which are
/// required for safety, it's responsible for ensuring those still hold -- this
/// generally requires preventing access to instances of the inner type, as
/// implementing `TransparentWrapper<U> for T` means anybody can call
/// `T::cast_ref(any_instance_of_u)`.
///
/// For example, it would be invalid to implement TransparentWrapper for `str`
/// to implement `TransparentWrapper` around `[u8]` because of this.
///
/// # Examples
///
/// ## Basic
///
/// ```
/// use bytemuck::TransparentWrapper;
/// # #[derive(Default)]
/// # struct SomeStruct(u32);
///
/// #[repr(transparent)]
/// struct MyWrapper(SomeStruct);
///
/// unsafe impl TransparentWrapper<SomeStruct> for MyWrapper {}
///
/// // interpret a reference to &SomeStruct as a &MyWrapper
/// let thing = SomeStruct::default();
/// let inner_ref: &MyWrapper = MyWrapper::wrap_ref(&thing);
///
/// // Works with &mut too.
/// let mut mut_thing = SomeStruct::default();
/// let inner_mut: &mut MyWrapper = MyWrapper::wrap_mut(&mut mut_thing);
///
/// # let _ = (inner_ref, inner_mut); // silence warnings
/// ```
///
/// ## Use with dynamically sized types
///
/// ```
/// use bytemuck::TransparentWrapper;
///
/// #[repr(transparent)]
/// struct Slice<T>([T]);
///
/// unsafe impl<T> TransparentWrapper<[T]> for Slice<T> {}
///
/// let s = Slice::wrap_ref(&[1u32, 2, 3]);
/// assert_eq!(&s.0, &[1, 2, 3]);
///
/// let mut buf = [1, 2, 3u8];
/// let sm = Slice::wrap_mut(&mut buf);
/// ```
///
/// ## Deriving
///
/// When deriving, the non-wrapped fields must uphold all the normal
/// requirements, and must also be `Zeroable`.
#[cfg_attr(feature = "derive", doc = "```")]
#[cfg_attr(
  not(feature = "derive"),
  doc = "```ignore
// This example requires the `derive` feature."
)]
/// use bytemuck::TransparentWrapper;
/// use std::marker::PhantomData;
///
/// #[derive(TransparentWrapper)]
/// #[repr(transparent)]
/// #[transparent(usize)]
/// struct Wrapper<T: ?Sized>(usize, PhantomData<T>); // PhantomData<T> implements Zeroable for all T
/// ```
///
/// Here, an error will occur, because `MyZst` does not implement `Zeroable`.
#[cfg_attr(feature = "derive", doc = "```compile_fail")]
#[cfg_attr(
  not(feature = "derive"),
  doc = "```ignore
// This example requires the `derive` feature."
)]
/// use bytemuck::TransparentWrapper;
/// struct MyZst;
///
/// #[derive(TransparentWrapper)]
/// #[repr(transparent)]
/// #[transparent(usize)]
/// struct Wrapper(usize, MyZst); // MyZst does not implement Zeroable
/// ```
pub unsafe trait TransparentWrapper<Inner: ?Sized> {
  /// Convert the inner type into the wrapper type.
  #[inline]
  fn wrap(s: Inner) -> Self
  where
    Self: Sized,
    Inner: Sized,
  {
    assert!(size_of::<Inner>() == size_of::<Self>());
    assert!(align_of::<Inner>() == align_of::<Self>());
    // SAFETY: The unsafe contract requires that `Self` and `Inner` have
    // identical representations.
    unsafe { transmute!(s) }
  }

  /// Convert a reference to the inner type into a reference to the wrapper
  /// type.
  #[inline]
  fn wrap_ref(s: &Inner) -> &Self {
    // The unsafe contract requires that these two have
    // identical representations, and thus identical pointer metadata.
    // Assert that Self and Inner have the same pointer size,
    // which is the best we can do to assert their metadata is the same type
    // on stable.
    assert!(size_of::<*const Inner>() == size_of::<*const Self>());
    unsafe {
      // A pointer cast doesn't work here because rustc can't tell that
      // the vtables match (because of the `?Sized` restriction relaxation).
      // A `transmute` doesn't work because the sizes are unspecified.
      //
      // SAFETY: The unsafe contract requires that these two have
      // identical representations.
      let inner_ptr = s as *const Inner;
      let wrapper_ptr: *const Self = transmute!(inner_ptr);
      &*wrapper_ptr
    }
  }

  /// Convert a mutable reference to the inner type into a mutable reference to
  /// the wrapper type.
  #[inline]
  fn wrap_mut(s: &mut Inner) -> &mut Self {
    // The unsafe contract requires that these two have
    // identical representations, and thus identical pointer metadata.
    // Assert that Self and Inner have the same pointer size,
    // which is about the best we can do on stable.
    assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
    unsafe {
      // A pointer cast doesn't work here because rustc can't tell that
      // the vtables match (because of the `?Sized` restriction relaxation).
      // A `transmute` doesn't work because the sizes are unspecified.
      //
      // SAFETY: The unsafe contract requires that these two have
      // identical representations.
      let inner_ptr = s as *mut Inner;
      let wrapper_ptr: *mut Self = transmute!(inner_ptr);
      &mut *wrapper_ptr
    }
  }

  /// Convert a slice to the inner type into a slice to the wrapper type.
  #[inline]
  fn wrap_slice(s: &[Inner]) -> &[Self]
  where
    Self: Sized,
    Inner: Sized,
  {
    assert!(size_of::<Inner>() == size_of::<Self>());
    assert!(align_of::<Inner>() == align_of::<Self>());
    // SAFETY: The unsafe contract requires that these two have
    // identical representations (size and alignment).
    unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Self, s.len()) }
  }

  /// Convert a mutable slice to the inner type into a mutable slice to the
  /// wrapper type.
  #[inline]
  fn wrap_slice_mut(s: &mut [Inner]) -> &mut [Self]
  where
    Self: Sized,
    Inner: Sized,
  {
    assert!(size_of::<Inner>() == size_of::<Self>());
    assert!(align_of::<Inner>() == align_of::<Self>());
    // SAFETY: The unsafe contract requires that these two have
    // identical representations (size and alignment).
    unsafe {
      core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Self, s.len())
    }
  }

  /// Convert the wrapper type into the inner type.
  #[inline]
  fn peel(s: Self) -> Inner
  where
    Self: Sized,
    Inner: Sized,
  {
    assert!(size_of::<Inner>() == size_of::<Self>());
    assert!(align_of::<Inner>() == align_of::<Self>());
    // SAFETY: The unsafe contract requires that `Self` and `Inner` have
    // identical representations.
    unsafe { transmute!(s) }
  }

  /// Convert a reference to the wrapper type into a reference to the inner
  /// type.
  #[inline]
  fn peel_ref(s: &Self) -> &Inner {
    // The unsafe contract requires that these two have
    // identical representations, and thus identical pointer metadata.
    // Assert that Self and Inner have the same pointer size,
    // which is about the best we can do on stable.
    assert!(size_of::<*const Inner>() == size_of::<*const Self>());
    unsafe {
      // A pointer cast doesn't work here because rustc can't tell that
      // the vtables match (because of the `?Sized` restriction relaxation).
      // A `transmute` doesn't work because the sizes are unspecified.
      //
      // SAFETY: The unsafe contract requires that these two have
      // identical representations.
      let wrapper_ptr = s as *const Self;
      let inner_ptr: *const Inner = transmute!(wrapper_ptr);
      &*inner_ptr
    }
  }

  /// Convert a mutable reference to the wrapper type into a mutable reference
  /// to the inner type.
  #[inline]
  fn peel_mut(s: &mut Self) -> &mut Inner {
    // The unsafe contract requires that these two have
    // identical representations, and thus identical pointer metadata.
    // Assert that Self and Inner have the same pointer size,
    // which is about the best we can do on stable.
    assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
    unsafe {
      // A pointer cast doesn't work here because rustc can't tell that
      // the vtables match (because of the `?Sized` restriction relaxation).
      // A `transmute` doesn't work because the sizes are unspecified.
      //
      // SAFETY: The unsafe contract requires that these two have
      // identical representations.
      let wrapper_ptr = s as *mut Self;
      let inner_ptr: *mut Inner = transmute!(wrapper_ptr);
      &mut *inner_ptr
    }
  }

  /// Convert a slice to the wrapped type into a slice to the inner type.
  #[inline]
  fn peel_slice(s: &[Self]) -> &[Inner]
  where
    Self: Sized,
    Inner: Sized,
  {
    assert!(size_of::<Inner>() == size_of::<Self>());
    assert!(align_of::<Inner>() == align_of::<Self>());
    // SAFETY: The unsafe contract requires that these two have
    // identical representations (size and alignment).
    unsafe { core::slice::from_raw_parts(s.as_ptr() as *const Inner, s.len()) }
  }

  /// Convert a mutable slice to the wrapped type into a mutable slice to the
  /// inner type.
  #[inline]
  fn peel_slice_mut(s: &mut [Self]) -> &mut [Inner]
  where
    Self: Sized,
    Inner: Sized,
  {
    assert!(size_of::<Inner>() == size_of::<Self>());
    assert!(align_of::<Inner>() == align_of::<Self>());
    // SAFETY: The unsafe contract requires that these two have
    // identical representations (size and alignment).
    unsafe {
      core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut Inner, s.len())
    }
  }
}

unsafe impl<T> TransparentWrapper<T> for core::num::Wrapping<T> {}
#[cfg(feature = "transparentwrapper_extra")]
#[cfg_attr(
  feature = "nightly_docs",
  doc(cfg(feature = "transparentwrapper_extra"))
)]
unsafe impl<T> TransparentWrapper<T> for core::num::Saturating<T> {}

// Note that `Reverse` existed since Rust 1.19.0, but was only made `#[repr(transparent)]`
// in Rust 1.52.0 (PR: https://github.com/rust-lang/rust/pull/81879), so we have it under
// the same feature as `Saturating`, which was stabilized in Rust 1.74.0, so that this
// impl cannot be used on a version before 1.52.0 where it would be unsound.
#[cfg(feature = "transparentwrapper_extra")]
#[cfg_attr(
  feature = "nightly_docs",
  doc(cfg(feature = "transparentwrapper_extra"))
)]
unsafe impl<T> TransparentWrapper<T> for core::cmp::Reverse<T> {}