1#![cfg(feature = "extern_crate_alloc")]
2
3//! Stuff to boost things in the `alloc` crate.
4//!
5//! * You must enable the `extern_crate_alloc` feature of `bytemuck` or you will
6//! not be able to use this module! This is generally done by adding the
7//! feature to the dependency in Cargo.toml like so:
8//!
9//! `bytemuck = { version = "VERSION_YOU_ARE_USING", features =
10//! ["extern_crate_alloc"]}`
11
12use super::*;
13#[cfg(target_has_atomic = "ptr")]
14use alloc::sync::Arc;
15use alloc::{
16 alloc::{alloc_zeroed, Layout},
17 boxed::Box,
18 rc::Rc,
19 vec,
20 vec::Vec,
21};
22use core::ops::{Deref, DerefMut};
23
24/// As [`try_cast_box`](try_cast_box), but unwraps for you.
25#[inline]
26pub fn cast_box<A: NoUninit, B: AnyBitPattern>(input: Box<A>) -> Box<B> {
27 try_cast_box(input).map_err(|(e: PodCastError, _v: Box)| e).unwrap()
28}
29
30/// Attempts to cast the content type of a [`Box`](alloc::boxed::Box).
31///
32/// On failure you get back an error along with the starting `Box`.
33///
34/// ## Failure
35///
36/// * The start and end content type of the `Box` must have the exact same
37/// alignment.
38/// * The start and end size of the `Box` must have the exact same size.
39#[inline]
40pub fn try_cast_box<A: NoUninit, B: AnyBitPattern>(
41 input: Box<A>,
42) -> Result<Box<B>, (PodCastError, Box<A>)> {
43 if align_of::<A>() != align_of::<B>() {
44 Err((PodCastError::AlignmentMismatch, input))
45 } else if size_of::<A>() != size_of::<B>() {
46 Err((PodCastError::SizeMismatch, input))
47 } else {
48 // Note(Lokathor): This is much simpler than with the Vec casting!
49 let ptr: *mut B = Box::into_raw(input) as *mut B;
50 Ok(unsafe { Box::from_raw(ptr) })
51 }
52}
53
54/// Allocates a `Box<T>` with all of the contents being zeroed out.
55///
56/// This uses the global allocator to create a zeroed allocation and _then_
57/// turns it into a Box. In other words, it's 100% assured that the zeroed data
58/// won't be put temporarily on the stack. You can make a box of any size
59/// without fear of a stack overflow.
60///
61/// ## Failure
62///
63/// This fails if the allocation fails.
64#[inline]
65pub fn try_zeroed_box<T: Zeroable>() -> Result<Box<T>, ()> {
66 if size_of::<T>() == 0 {
67 // This will not allocate but simply create a dangling pointer.
68 let dangling: *mut T = core::ptr::NonNull::dangling().as_ptr();
69 return Ok(unsafe { Box::from_raw(dangling) });
70 }
71 let layout: Layout = Layout::new::<T>();
72 let ptr: *mut u8 = unsafe { alloc_zeroed(layout) };
73 if ptr.is_null() {
74 // we don't know what the error is because `alloc_zeroed` is a dumb API
75 Err(())
76 } else {
77 Ok(unsafe { Box::<T>::from_raw(ptr as *mut T) })
78 }
79}
80
81/// As [`try_zeroed_box`], but unwraps for you.
82#[inline]
83pub fn zeroed_box<T: Zeroable>() -> Box<T> {
84 try_zeroed_box().unwrap()
85}
86
87/// Allocates a `Vec<T>` of length and capacity exactly equal to `length` and
88/// all elements zeroed.
89///
90/// ## Failure
91///
92/// This fails if the allocation fails, or if a layout cannot be calculated for
93/// the allocation.
94pub fn try_zeroed_vec<T: Zeroable>(length: usize) -> Result<Vec<T>, ()> {
95 if length == 0 {
96 Ok(Vec::new())
97 } else {
98 let boxed_slice: Box<[T]> = try_zeroed_slice_box(length)?;
99 Ok(boxed_slice.into_vec())
100 }
101}
102
103/// As [`try_zeroed_vec`] but unwraps for you
104pub fn zeroed_vec<T: Zeroable>(length: usize) -> Vec<T> {
105 try_zeroed_vec(length).unwrap()
106}
107
108/// Allocates a `Box<[T]>` with all contents being zeroed out.
109///
110/// This uses the global allocator to create a zeroed allocation and _then_
111/// turns it into a Box. In other words, it's 100% assured that the zeroed data
112/// won't be put temporarily on the stack. You can make a box of any size
113/// without fear of a stack overflow.
114///
115/// ## Failure
116///
117/// This fails if the allocation fails, or if a layout cannot be calculated for
118/// the allocation.
119#[inline]
120pub fn try_zeroed_slice_box<T: Zeroable>(
121 length: usize,
122) -> Result<Box<[T]>, ()> {
123 if size_of::<T>() == 0 || length == 0 {
124 // This will not allocate but simply create a dangling slice pointer.
125 let dangling: *mut T = core::ptr::NonNull::dangling().as_ptr();
126 let dangling_slice: *mut [T] = core::ptr::slice_from_raw_parts_mut(data:dangling, len:length);
127 return Ok(unsafe { Box::from_raw(dangling_slice) });
128 }
129 let layout: Layout = core::alloc::Layout::array::<T>(length).map_err(|_| ())?;
130 let ptr: *mut u8 = unsafe { alloc_zeroed(layout) };
131 if ptr.is_null() {
132 // we don't know what the error is because `alloc_zeroed` is a dumb API
133 Err(())
134 } else {
135 let slice: &mut [T] =
136 unsafe { core::slice::from_raw_parts_mut(data:ptr as *mut T, len:length) };
137 Ok(unsafe { Box::<[T]>::from_raw(slice) })
138 }
139}
140
141/// As [`try_zeroed_slice_box`](try_zeroed_slice_box), but unwraps for you.
142pub fn zeroed_slice_box<T: Zeroable>(length: usize) -> Box<[T]> {
143 try_zeroed_slice_box(length).unwrap()
144}
145
146/// As [`try_cast_slice_box`](try_cast_slice_box), but unwraps for you.
147#[inline]
148pub fn cast_slice_box<A: NoUninit, B: AnyBitPattern>(
149 input: Box<[A]>,
150) -> Box<[B]> {
151 try_cast_slice_box(input).map_err(|(e: PodCastError, _v: Box<[A]>)| e).unwrap()
152}
153
154/// Attempts to cast the content type of a `Box<[T]>`.
155///
156/// On failure you get back an error along with the starting `Box<[T]>`.
157///
158/// ## Failure
159///
160/// * The start and end content type of the `Box<[T]>` must have the exact same
161/// alignment.
162/// * The start and end content size in bytes of the `Box<[T]>` must be the
163/// exact same.
164#[inline]
165pub fn try_cast_slice_box<A: NoUninit, B: AnyBitPattern>(
166 input: Box<[A]>,
167) -> Result<Box<[B]>, (PodCastError, Box<[A]>)> {
168 if align_of::<A>() != align_of::<B>() {
169 Err((PodCastError::AlignmentMismatch, input))
170 } else if size_of::<A>() != size_of::<B>() {
171 if size_of::<A>() * input.len() % size_of::<B>() != 0 {
172 // If the size in bytes of the underlying buffer does not match an exact
173 // multiple of the size of B, we cannot cast between them.
174 Err((PodCastError::SizeMismatch, input))
175 } else {
176 // Because the size is an exact multiple, we can now change the length
177 // of the slice and recreate the Box
178 // NOTE: This is a valid operation because according to the docs of
179 // std::alloc::GlobalAlloc::dealloc(), the Layout that was used to alloc
180 // the block must be the same Layout that is used to dealloc the block.
181 // Luckily, Layout only stores two things, the alignment, and the size in
182 // bytes. So as long as both of those stay the same, the Layout will
183 // remain a valid input to dealloc.
184 let length = size_of::<A>() * input.len() / size_of::<B>();
185 let box_ptr: *mut A = Box::into_raw(input) as *mut A;
186 let ptr: *mut [B] =
187 unsafe { core::slice::from_raw_parts_mut(box_ptr as *mut B, length) };
188 Ok(unsafe { Box::<[B]>::from_raw(ptr) })
189 }
190 } else {
191 let box_ptr: *mut [A] = Box::into_raw(input);
192 let ptr: *mut [B] = box_ptr as *mut [B];
193 Ok(unsafe { Box::<[B]>::from_raw(ptr) })
194 }
195}
196
197/// As [`try_cast_vec`](try_cast_vec), but unwraps for you.
198#[inline]
199pub fn cast_vec<A: NoUninit, B: AnyBitPattern>(input: Vec<A>) -> Vec<B> {
200 try_cast_vec(input).map_err(|(e: PodCastError, _v: Vec)| e).unwrap()
201}
202
203/// Attempts to cast the content type of a [`Vec`](alloc::vec::Vec).
204///
205/// On failure you get back an error along with the starting `Vec`.
206///
207/// ## Failure
208///
209/// * The start and end content type of the `Vec` must have the exact same
210/// alignment.
211/// * The start and end content size in bytes of the `Vec` must be the exact
212/// same.
213/// * The start and end capacity in bytes of the `Vec` must be the exact same.
214#[inline]
215pub fn try_cast_vec<A: NoUninit, B: AnyBitPattern>(
216 input: Vec<A>,
217) -> Result<Vec<B>, (PodCastError, Vec<A>)> {
218 if align_of::<A>() != align_of::<B>() {
219 Err((PodCastError::AlignmentMismatch, input))
220 } else if size_of::<A>() != size_of::<B>() {
221 if size_of::<A>() * input.len() % size_of::<B>() != 0
222 || size_of::<A>() * input.capacity() % size_of::<B>() != 0
223 {
224 // If the size in bytes of the underlying buffer does not match an exact
225 // multiple of the size of B, we cannot cast between them.
226 // Note that we have to pay special attention to make sure that both
227 // length and capacity are valid under B, as we do not want to
228 // change which bytes are considered part of the initialized slice
229 // of the Vec
230 Err((PodCastError::SizeMismatch, input))
231 } else {
232 // Because the size is an exact multiple, we can now change the length and
233 // capacity and recreate the Vec
234 // NOTE: This is a valid operation because according to the docs of
235 // std::alloc::GlobalAlloc::dealloc(), the Layout that was used to alloc
236 // the block must be the same Layout that is used to dealloc the block.
237 // Luckily, Layout only stores two things, the alignment, and the size in
238 // bytes. So as long as both of those stay the same, the Layout will
239 // remain a valid input to dealloc.
240
241 // Note(Lokathor): First we record the length and capacity, which don't
242 // have any secret provenance metadata.
243 let length: usize = size_of::<A>() * input.len() / size_of::<B>();
244 let capacity: usize = size_of::<A>() * input.capacity() / size_of::<B>();
245 // Note(Lokathor): Next we "pre-forget" the old Vec by wrapping with
246 // ManuallyDrop, because if we used `core::mem::forget` after taking the
247 // pointer then that would invalidate our pointer. In nightly there's a
248 // "into raw parts" method, which we can switch this too eventually.
249 let mut manual_drop_vec = ManuallyDrop::new(input);
250 let vec_ptr: *mut A = manual_drop_vec.as_mut_ptr();
251 let ptr: *mut B = vec_ptr as *mut B;
252 Ok(unsafe { Vec::from_raw_parts(ptr, length, capacity) })
253 }
254 } else {
255 // Note(Lokathor): First we record the length and capacity, which don't have
256 // any secret provenance metadata.
257 let length: usize = input.len();
258 let capacity: usize = input.capacity();
259 // Note(Lokathor): Next we "pre-forget" the old Vec by wrapping with
260 // ManuallyDrop, because if we used `core::mem::forget` after taking the
261 // pointer then that would invalidate our pointer. In nightly there's a
262 // "into raw parts" method, which we can switch this too eventually.
263 let mut manual_drop_vec = ManuallyDrop::new(input);
264 let vec_ptr: *mut A = manual_drop_vec.as_mut_ptr();
265 let ptr: *mut B = vec_ptr as *mut B;
266 Ok(unsafe { Vec::from_raw_parts(ptr, length, capacity) })
267 }
268}
269
270/// This "collects" a slice of pod data into a vec of a different pod type.
271///
272/// Unlike with [`cast_slice`] and [`cast_slice_mut`], this will always work.
273///
274/// The output vec will be of a minimal size/capacity to hold the slice given.
275///
276/// ```rust
277/// # use bytemuck::*;
278/// let halfwords: [u16; 4] = [5, 6, 7, 8];
279/// let vec_of_words: Vec<u32> = pod_collect_to_vec(&halfwords);
280/// if cfg!(target_endian = "little") {
281/// assert_eq!(&vec_of_words[..], &[0x0006_0005, 0x0008_0007][..])
282/// } else {
283/// assert_eq!(&vec_of_words[..], &[0x0005_0006, 0x0007_0008][..])
284/// }
285/// ```
286pub fn pod_collect_to_vec<A: NoUninit, B: NoUninit + AnyBitPattern>(
287 src: &[A],
288) -> Vec<B> {
289 let src_size: usize = size_of_val(src);
290 // Note(Lokathor): dst_count is rounded up so that the dest will always be at
291 // least as many bytes as the src.
292 let dst_count: usize = src_size / size_of::<B>()
293 + if src_size % size_of::<B>() != 0 { 1 } else { 0 };
294 let mut dst: Vec = vec![B::zeroed(); dst_count];
295
296 let src_bytes: &[u8] = cast_slice(src);
297 let dst_bytes: &mut [u8] = cast_slice_mut(&mut dst[..]);
298 dst_bytes[..src_size].copy_from_slice(src_bytes);
299 dst
300}
301
302/// As [`try_cast_rc`](try_cast_rc), but unwraps for you.
303#[inline]
304pub fn cast_rc<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
305 input: Rc<A>,
306) -> Rc<B> {
307 try_cast_rc(input).map_err(|(e: PodCastError, _v: Rc)| e).unwrap()
308}
309
310/// Attempts to cast the content type of a [`Rc`](alloc::rc::Rc).
311///
312/// On failure you get back an error along with the starting `Rc`.
313///
314/// The bounds on this function are the same as [`cast_mut`], because a user
315/// could call `Rc::get_unchecked_mut` on the output, which could be observable
316/// in the input.
317///
318/// ## Failure
319///
320/// * The start and end content type of the `Rc` must have the exact same
321/// alignment.
322/// * The start and end size of the `Rc` must have the exact same size.
323#[inline]
324pub fn try_cast_rc<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
325 input: Rc<A>,
326) -> Result<Rc<B>, (PodCastError, Rc<A>)> {
327 if align_of::<A>() != align_of::<B>() {
328 Err((PodCastError::AlignmentMismatch, input))
329 } else if size_of::<A>() != size_of::<B>() {
330 Err((PodCastError::SizeMismatch, input))
331 } else {
332 // Safety: Rc::from_raw requires size and alignment match, which is met.
333 let ptr: *const B = Rc::into_raw(this:input) as *const B;
334 Ok(unsafe { Rc::from_raw(ptr) })
335 }
336}
337
338/// As [`try_cast_arc`](try_cast_arc), but unwraps for you.
339#[inline]
340#[cfg(target_has_atomic = "ptr")]
341pub fn cast_arc<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
342 input: Arc<A>,
343) -> Arc<B> {
344 try_cast_arc(input).map_err(|(e: PodCastError, _v: Arc)| e).unwrap()
345}
346
347/// Attempts to cast the content type of a [`Arc`](alloc::sync::Arc).
348///
349/// On failure you get back an error along with the starting `Arc`.
350///
351/// The bounds on this function are the same as [`cast_mut`], because a user
352/// could call `Rc::get_unchecked_mut` on the output, which could be observable
353/// in the input.
354///
355/// ## Failure
356///
357/// * The start and end content type of the `Arc` must have the exact same
358/// alignment.
359/// * The start and end size of the `Arc` must have the exact same size.
360#[inline]
361#[cfg(target_has_atomic = "ptr")]
362pub fn try_cast_arc<
363 A: NoUninit + AnyBitPattern,
364 B: NoUninit + AnyBitPattern,
365>(
366 input: Arc<A>,
367) -> Result<Arc<B>, (PodCastError, Arc<A>)> {
368 if align_of::<A>() != align_of::<B>() {
369 Err((PodCastError::AlignmentMismatch, input))
370 } else if size_of::<A>() != size_of::<B>() {
371 Err((PodCastError::SizeMismatch, input))
372 } else {
373 // Safety: Arc::from_raw requires size and alignment match, which is met.
374 let ptr: *const B = Arc::into_raw(this:input) as *const B;
375 Ok(unsafe { Arc::from_raw(ptr) })
376 }
377}
378
379/// As [`try_cast_slice_rc`](try_cast_slice_rc), but unwraps for you.
380#[inline]
381pub fn cast_slice_rc<
382 A: NoUninit + AnyBitPattern,
383 B: NoUninit + AnyBitPattern,
384>(
385 input: Rc<[A]>,
386) -> Rc<[B]> {
387 try_cast_slice_rc(input).map_err(|(e: PodCastError, _v: Rc<[A]>)| e).unwrap()
388}
389
390/// Attempts to cast the content type of a `Rc<[T]>`.
391///
392/// On failure you get back an error along with the starting `Rc<[T]>`.
393///
394/// The bounds on this function are the same as [`cast_mut`], because a user
395/// could call `Rc::get_unchecked_mut` on the output, which could be observable
396/// in the input.
397///
398/// ## Failure
399///
400/// * The start and end content type of the `Rc<[T]>` must have the exact same
401/// alignment.
402/// * The start and end content size in bytes of the `Rc<[T]>` must be the exact
403/// same.
404#[inline]
405pub fn try_cast_slice_rc<
406 A: NoUninit + AnyBitPattern,
407 B: NoUninit + AnyBitPattern,
408>(
409 input: Rc<[A]>,
410) -> Result<Rc<[B]>, (PodCastError, Rc<[A]>)> {
411 if align_of::<A>() != align_of::<B>() {
412 Err((PodCastError::AlignmentMismatch, input))
413 } else if size_of::<A>() != size_of::<B>() {
414 if size_of::<A>() * input.len() % size_of::<B>() != 0 {
415 // If the size in bytes of the underlying buffer does not match an exact
416 // multiple of the size of B, we cannot cast between them.
417 Err((PodCastError::SizeMismatch, input))
418 } else {
419 // Because the size is an exact multiple, we can now change the length
420 // of the slice and recreate the Rc
421 // NOTE: This is a valid operation because according to the docs of
422 // std::rc::Rc::from_raw(), the type U that was in the original Rc<U>
423 // acquired from Rc::into_raw() must have the same size alignment and
424 // size of the type T in the new Rc<T>. So as long as both the size
425 // and alignment stay the same, the Rc will remain a valid Rc.
426 let length = size_of::<A>() * input.len() / size_of::<B>();
427 let rc_ptr: *const A = Rc::into_raw(input) as *const A;
428 // Must use ptr::slice_from_raw_parts, because we cannot make an
429 // intermediate const reference, because it has mutable provenance,
430 // nor an intermediate mutable reference, because it could be aliased.
431 let ptr = core::ptr::slice_from_raw_parts(rc_ptr as *const B, length);
432 Ok(unsafe { Rc::<[B]>::from_raw(ptr) })
433 }
434 } else {
435 let rc_ptr: *const [A] = Rc::into_raw(input);
436 let ptr: *const [B] = rc_ptr as *const [B];
437 Ok(unsafe { Rc::<[B]>::from_raw(ptr) })
438 }
439}
440
441/// As [`try_cast_slice_arc`](try_cast_slice_arc), but unwraps for you.
442#[inline]
443#[cfg(target_has_atomic = "ptr")]
444pub fn cast_slice_arc<
445 A: NoUninit + AnyBitPattern,
446 B: NoUninit + AnyBitPattern,
447>(
448 input: Arc<[A]>,
449) -> Arc<[B]> {
450 try_cast_slice_arc(input).map_err(|(e: PodCastError, _v: Arc<[A]>)| e).unwrap()
451}
452
453/// Attempts to cast the content type of a `Arc<[T]>`.
454///
455/// On failure you get back an error along with the starting `Arc<[T]>`.
456///
457/// The bounds on this function are the same as [`cast_mut`], because a user
458/// could call `Rc::get_unchecked_mut` on the output, which could be observable
459/// in the input.
460///
461/// ## Failure
462///
463/// * The start and end content type of the `Arc<[T]>` must have the exact same
464/// alignment.
465/// * The start and end content size in bytes of the `Arc<[T]>` must be the
466/// exact same.
467#[inline]
468#[cfg(target_has_atomic = "ptr")]
469pub fn try_cast_slice_arc<
470 A: NoUninit + AnyBitPattern,
471 B: NoUninit + AnyBitPattern,
472>(
473 input: Arc<[A]>,
474) -> Result<Arc<[B]>, (PodCastError, Arc<[A]>)> {
475 if align_of::<A>() != align_of::<B>() {
476 Err((PodCastError::AlignmentMismatch, input))
477 } else if size_of::<A>() != size_of::<B>() {
478 if size_of::<A>() * input.len() % size_of::<B>() != 0 {
479 // If the size in bytes of the underlying buffer does not match an exact
480 // multiple of the size of B, we cannot cast between them.
481 Err((PodCastError::SizeMismatch, input))
482 } else {
483 // Because the size is an exact multiple, we can now change the length
484 // of the slice and recreate the Arc
485 // NOTE: This is a valid operation because according to the docs of
486 // std::sync::Arc::from_raw(), the type U that was in the original Arc<U>
487 // acquired from Arc::into_raw() must have the same size alignment and
488 // size of the type T in the new Arc<T>. So as long as both the size
489 // and alignment stay the same, the Arc will remain a valid Arc.
490 let length = size_of::<A>() * input.len() / size_of::<B>();
491 let arc_ptr: *const A = Arc::into_raw(input) as *const A;
492 // Must use ptr::slice_from_raw_parts, because we cannot make an
493 // intermediate const reference, because it has mutable provenance,
494 // nor an intermediate mutable reference, because it could be aliased.
495 let ptr = core::ptr::slice_from_raw_parts(arc_ptr as *const B, length);
496 Ok(unsafe { Arc::<[B]>::from_raw(ptr) })
497 }
498 } else {
499 let arc_ptr: *const [A] = Arc::into_raw(input);
500 let ptr: *const [B] = arc_ptr as *const [B];
501 Ok(unsafe { Arc::<[B]>::from_raw(ptr) })
502 }
503}
504
505/// An extension trait for `TransparentWrapper` and alloc types.
506pub trait TransparentWrapperAlloc<Inner: ?Sized>:
507 TransparentWrapper<Inner>
508{
509 /// Convert a vec of the inner type into a vec of the wrapper type.
510 fn wrap_vec(s: Vec<Inner>) -> Vec<Self>
511 where
512 Self: Sized,
513 Inner: Sized,
514 {
515 let mut s = core::mem::ManuallyDrop::new(s);
516
517 let length = s.len();
518 let capacity = s.capacity();
519 let ptr = s.as_mut_ptr();
520
521 unsafe {
522 // SAFETY:
523 // * ptr comes from Vec (and will not be double-dropped)
524 // * the two types have the identical representation
525 // * the len and capacity fields are valid
526 Vec::from_raw_parts(ptr as *mut Self, length, capacity)
527 }
528 }
529
530 /// Convert a box to the inner type into a box to the wrapper
531 /// type.
532 #[inline]
533 fn wrap_box(s: Box<Inner>) -> Box<Self> {
534 assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
535
536 unsafe {
537 // A pointer cast doesn't work here because rustc can't tell that
538 // the vtables match (because of the `?Sized` restriction relaxation).
539 // A `transmute` doesn't work because the sizes are unspecified.
540 //
541 // SAFETY:
542 // * The unsafe contract requires that pointers to Inner and Self have
543 // identical representations
544 // * Box is guaranteed to have representation identical to a (non-null)
545 // pointer
546 // * The pointer comes from a box (and thus satisfies all safety
547 // requirements of Box)
548 let inner_ptr: *mut Inner = Box::into_raw(s);
549 let wrapper_ptr: *mut Self = transmute!(inner_ptr);
550 Box::from_raw(wrapper_ptr)
551 }
552 }
553
554 /// Convert an [`Rc`](alloc::rc::Rc) to the inner type into an `Rc` to the
555 /// wrapper type.
556 #[inline]
557 fn wrap_rc(s: Rc<Inner>) -> Rc<Self> {
558 assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
559
560 unsafe {
561 // A pointer cast doesn't work here because rustc can't tell that
562 // the vtables match (because of the `?Sized` restriction relaxation).
563 // A `transmute` doesn't work because the layout of Rc is unspecified.
564 //
565 // SAFETY:
566 // * The unsafe contract requires that pointers to Inner and Self have
567 // identical representations, and that the size and alignment of Inner
568 // and Self are the same, which meets the safety requirements of
569 // Rc::from_raw
570 let inner_ptr: *const Inner = Rc::into_raw(s);
571 let wrapper_ptr: *const Self = transmute!(inner_ptr);
572 Rc::from_raw(wrapper_ptr)
573 }
574 }
575
576 /// Convert an [`Arc`](alloc::sync::Arc) to the inner type into an `Arc` to
577 /// the wrapper type.
578 #[inline]
579 #[cfg(target_has_atomic = "ptr")]
580 fn wrap_arc(s: Arc<Inner>) -> Arc<Self> {
581 assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
582
583 unsafe {
584 // A pointer cast doesn't work here because rustc can't tell that
585 // the vtables match (because of the `?Sized` restriction relaxation).
586 // A `transmute` doesn't work because the layout of Arc is unspecified.
587 //
588 // SAFETY:
589 // * The unsafe contract requires that pointers to Inner and Self have
590 // identical representations, and that the size and alignment of Inner
591 // and Self are the same, which meets the safety requirements of
592 // Arc::from_raw
593 let inner_ptr: *const Inner = Arc::into_raw(s);
594 let wrapper_ptr: *const Self = transmute!(inner_ptr);
595 Arc::from_raw(wrapper_ptr)
596 }
597 }
598
599 /// Convert a vec of the wrapper type into a vec of the inner type.
600 fn peel_vec(s: Vec<Self>) -> Vec<Inner>
601 where
602 Self: Sized,
603 Inner: Sized,
604 {
605 let mut s = core::mem::ManuallyDrop::new(s);
606
607 let length = s.len();
608 let capacity = s.capacity();
609 let ptr = s.as_mut_ptr();
610
611 unsafe {
612 // SAFETY:
613 // * ptr comes from Vec (and will not be double-dropped)
614 // * the two types have the identical representation
615 // * the len and capacity fields are valid
616 Vec::from_raw_parts(ptr as *mut Inner, length, capacity)
617 }
618 }
619
620 /// Convert a box to the wrapper type into a box to the inner
621 /// type.
622 #[inline]
623 fn peel_box(s: Box<Self>) -> Box<Inner> {
624 assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
625
626 unsafe {
627 // A pointer cast doesn't work here because rustc can't tell that
628 // the vtables match (because of the `?Sized` restriction relaxation).
629 // A `transmute` doesn't work because the sizes are unspecified.
630 //
631 // SAFETY:
632 // * The unsafe contract requires that pointers to Inner and Self have
633 // identical representations
634 // * Box is guaranteed to have representation identical to a (non-null)
635 // pointer
636 // * The pointer comes from a box (and thus satisfies all safety
637 // requirements of Box)
638 let wrapper_ptr: *mut Self = Box::into_raw(s);
639 let inner_ptr: *mut Inner = transmute!(wrapper_ptr);
640 Box::from_raw(inner_ptr)
641 }
642 }
643
644 /// Convert an [`Rc`](alloc::rc::Rc) to the wrapper type into an `Rc` to the
645 /// inner type.
646 #[inline]
647 fn peel_rc(s: Rc<Self>) -> Rc<Inner> {
648 assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
649
650 unsafe {
651 // A pointer cast doesn't work here because rustc can't tell that
652 // the vtables match (because of the `?Sized` restriction relaxation).
653 // A `transmute` doesn't work because the layout of Rc is unspecified.
654 //
655 // SAFETY:
656 // * The unsafe contract requires that pointers to Inner and Self have
657 // identical representations, and that the size and alignment of Inner
658 // and Self are the same, which meets the safety requirements of
659 // Rc::from_raw
660 let wrapper_ptr: *const Self = Rc::into_raw(s);
661 let inner_ptr: *const Inner = transmute!(wrapper_ptr);
662 Rc::from_raw(inner_ptr)
663 }
664 }
665
666 /// Convert an [`Arc`](alloc::sync::Arc) to the wrapper type into an `Arc` to
667 /// the inner type.
668 #[inline]
669 #[cfg(target_has_atomic = "ptr")]
670 fn peel_arc(s: Arc<Self>) -> Arc<Inner> {
671 assert!(size_of::<*mut Inner>() == size_of::<*mut Self>());
672
673 unsafe {
674 // A pointer cast doesn't work here because rustc can't tell that
675 // the vtables match (because of the `?Sized` restriction relaxation).
676 // A `transmute` doesn't work because the layout of Arc is unspecified.
677 //
678 // SAFETY:
679 // * The unsafe contract requires that pointers to Inner and Self have
680 // identical representations, and that the size and alignment of Inner
681 // and Self are the same, which meets the safety requirements of
682 // Arc::from_raw
683 let wrapper_ptr: *const Self = Arc::into_raw(s);
684 let inner_ptr: *const Inner = transmute!(wrapper_ptr);
685 Arc::from_raw(inner_ptr)
686 }
687 }
688}
689
690impl<I: ?Sized, T: ?Sized + TransparentWrapper<I>> TransparentWrapperAlloc<I>
691 for T
692{
693}
694
695/// As `Box<[u8]>`, but remembers the original alignment.
696pub struct BoxBytes {
697 // SAFETY: `ptr` is owned, was allocated with `layout`, and points to
698 // `layout.size()` initialized bytes.
699 ptr: NonNull<u8>,
700 layout: Layout,
701}
702
703impl Deref for BoxBytes {
704 type Target = [u8];
705
706 fn deref(&self) -> &Self::Target {
707 // SAFETY: See type invariant.
708 unsafe {
709 core::slice::from_raw_parts(self.ptr.as_ptr(), self.layout.size())
710 }
711 }
712}
713
714impl DerefMut for BoxBytes {
715 fn deref_mut(&mut self) -> &mut Self::Target {
716 // SAFETY: See type invariant.
717 unsafe {
718 core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.layout.size())
719 }
720 }
721}
722
723impl Drop for BoxBytes {
724 fn drop(&mut self) {
725 // SAFETY: See type invariant.
726 unsafe { alloc::alloc::dealloc(self.ptr.as_ptr(), self.layout) };
727 }
728}
729
730impl<T: ?Sized + sealed::BoxBytesOf> From<Box<T>> for BoxBytes {
731 fn from(value: Box<T>) -> Self {
732 value.box_bytes_of()
733 }
734}
735
736mod sealed {
737 use crate::{BoxBytes, PodCastError};
738 use alloc::boxed::Box;
739
740 pub trait BoxBytesOf {
741 fn box_bytes_of(self: Box<Self>) -> BoxBytes;
742 }
743
744 pub trait FromBoxBytes {
745 fn try_from_box_bytes(
746 bytes: BoxBytes,
747 ) -> Result<Box<Self>, (PodCastError, BoxBytes)>;
748 }
749}
750
751impl<T: NoUninit> sealed::BoxBytesOf for T {
752 fn box_bytes_of(self: Box<Self>) -> BoxBytes {
753 let layout: Layout = Layout::new::<T>();
754 let ptr: *mut u8 = Box::into_raw(self) as *mut u8;
755 // SAFETY: Box::into_raw() returns a non-null pointer.
756 let ptr: NonNull = unsafe { NonNull::new_unchecked(ptr) };
757 BoxBytes { ptr, layout }
758 }
759}
760
761impl<T: NoUninit> sealed::BoxBytesOf for [T] {
762 fn box_bytes_of(self: Box<Self>) -> BoxBytes {
763 let layout: Layout = Layout::for_value::<[T]>(&self);
764 let ptr: *mut u8 = Box::into_raw(self) as *mut u8;
765 // SAFETY: Box::into_raw() returns a non-null pointer.
766 let ptr: NonNull = unsafe { NonNull::new_unchecked(ptr) };
767 BoxBytes { ptr, layout }
768 }
769}
770
771impl sealed::BoxBytesOf for str {
772 fn box_bytes_of(self: Box<Self>) -> BoxBytes {
773 self.into_boxed_bytes().box_bytes_of()
774 }
775}
776
777impl<T: AnyBitPattern> sealed::FromBoxBytes for T {
778 fn try_from_box_bytes(
779 bytes: BoxBytes,
780 ) -> Result<Box<Self>, (PodCastError, BoxBytes)> {
781 let layout: Layout = Layout::new::<T>();
782 if bytes.layout.align() != layout.align() {
783 Err((PodCastError::AlignmentMismatch, bytes))
784 } else if bytes.layout.size() != layout.size() {
785 Err((PodCastError::SizeMismatch, bytes))
786 } else {
787 let (ptr: NonNull, _) = bytes.into_raw_parts();
788 // SAFETY: See BoxBytes type invariant.
789 Ok(unsafe { Box::from_raw(ptr.as_ptr() as *mut T) })
790 }
791 }
792}
793
794impl<T: AnyBitPattern> sealed::FromBoxBytes for [T] {
795 fn try_from_box_bytes(
796 bytes: BoxBytes,
797 ) -> Result<Box<Self>, (PodCastError, BoxBytes)> {
798 let single_layout: Layout = Layout::new::<T>();
799 if bytes.layout.align() != single_layout.align() {
800 Err((PodCastError::AlignmentMismatch, bytes))
801 } else if single_layout.size() == 0 {
802 Err((PodCastError::SizeMismatch, bytes))
803 } else if bytes.layout.size() % single_layout.size() != 0 {
804 Err((PodCastError::OutputSliceWouldHaveSlop, bytes))
805 } else {
806 let (ptr: NonNull, layout: Layout) = bytes.into_raw_parts();
807 let length: usize = layout.size() / single_layout.size();
808 let ptr: *mut [T] =
809 core::ptr::slice_from_raw_parts_mut(data:ptr.as_ptr() as *mut T, len:length);
810 // SAFETY: See BoxBytes type invariant.
811 Ok(unsafe { Box::from_raw(ptr) })
812 }
813 }
814}
815
816/// Re-interprets `Box<T>` as `BoxBytes`.
817///
818/// `T` must be either [`Sized`] and [`NoUninit`],
819/// [`[U]`](slice) where `U: NoUninit`, or [`str`].
820#[inline]
821pub fn box_bytes_of<T: sealed::BoxBytesOf + ?Sized>(input: Box<T>) -> BoxBytes {
822 input.box_bytes_of()
823}
824
825/// Re-interprets `BoxBytes` as `Box<T>`.
826///
827/// `T` must be either [`Sized`] + [`AnyBitPattern`], or
828/// [`[U]`](slice) where `U: AnyBitPattern`.
829///
830/// ## Panics
831///
832/// This is [`try_from_box_bytes`] but will panic on error and the input will be
833/// dropped.
834#[inline]
835pub fn from_box_bytes<T: sealed::FromBoxBytes + ?Sized>(
836 input: BoxBytes,
837) -> Box<T> {
838 try_from_box_bytes(input).map_err(|(error: PodCastError, _)| error).unwrap()
839}
840
841/// Re-interprets `BoxBytes` as `Box<T>`.
842///
843/// `T` must be either [`Sized`] + [`AnyBitPattern`], or
844/// [`[U]`](slice) where `U: AnyBitPattern`.
845///
846/// Returns `Err`:
847/// * If the input isn't aligned for `T`.
848/// * If `T: Sized` and the input's length isn't exactly the size of `T`.
849/// * If `T = [U]` and the input's length isn't exactly a multiple of the size
850/// of `U`.
851#[inline]
852pub fn try_from_box_bytes<T: sealed::FromBoxBytes + ?Sized>(
853 input: BoxBytes,
854) -> Result<Box<T>, (PodCastError, BoxBytes)> {
855 T::try_from_box_bytes(input)
856}
857
858impl BoxBytes {
859 /// Constructs a `BoxBytes` from its raw parts.
860 ///
861 /// # Safety
862 ///
863 /// The pointer is owned, has been allocated with the provided layout, and
864 /// points to `layout.size()` initialized bytes.
865 pub unsafe fn from_raw_parts(ptr: NonNull<u8>, layout: Layout) -> Self {
866 BoxBytes { ptr, layout }
867 }
868
869 /// Deconstructs a `BoxBytes` into its raw parts.
870 ///
871 /// The pointer is owned, has been allocated with the provided layout, and
872 /// points to `layout.size()` initialized bytes.
873 pub fn into_raw_parts(self) -> (NonNull<u8>, Layout) {
874 let me = ManuallyDrop::new(self);
875 (me.ptr, me.layout)
876 }
877
878 /// Returns the original layout.
879 pub fn layout(&self) -> Layout {
880 self.layout
881 }
882}
883