1#[cfg(feature = "alloc")]
2item_group! {
3 use core::mem::MaybeUninit;
4 use alloc::boxed::Box;
5}
6
7#[cfg(feature = "alloc")]
16#[inline]
17#[must_use]
18pub unsafe fn alloc_uninit_bytes(len: usize) -> Box<[MaybeUninit<u8>]> {
19 #[allow(clippy::checked_conversions)]
20 #[cfg(any(debug_assertions, miri))]
21 {
22 assert!(len > 0 && len <= (isize::MAX as usize));
23 }
24 use alloc::alloc::{alloc, handle_alloc_error, Layout};
25 let layout = Layout::from_size_align_unchecked(len, 1);
26 let p = alloc(layout);
27 if p.is_null() {
28 handle_alloc_error(layout)
29 }
30 let ptr = p.cast();
31 Box::from_raw(core::ptr::slice_from_raw_parts_mut(ptr, len))
32}
33
34#[cfg(feature = "alloc")]
35#[inline]
36#[must_use]
37pub unsafe fn assume_init(b: Box<[MaybeUninit<u8>]>) -> Box<[u8]> {
38 let len = b.len();
39 let ptr = Box::into_raw(b).cast::<u8>();
40 Box::from_raw(core::ptr::slice_from_raw_parts_mut(ptr, len))
41}
42
43#[inline(always)]
44pub unsafe fn read<T>(base: *const T, offset: usize) -> T {
45 base.add(offset).read()
46}
47
48#[inline(always)]
49pub unsafe fn write<T>(base: *mut T, offset: usize, value: T) {
50 base.add(offset).write(value);
51}
52
53#[inline(always)]
54pub unsafe fn slice<'a, T>(data: *const T, len: usize) -> &'a [T] {
55 core::slice::from_raw_parts(data, len)
56}
57
58#[inline(always)]
59pub unsafe fn slice_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
60 core::slice::from_raw_parts_mut(data, len)
61}
62
63#[inline(always)]
64pub fn unroll<T>(slice: &[T], chunk_size: usize, mut f: impl FnMut(&T)) {
65 let mut iter = slice.chunks_exact(chunk_size);
66 for chunk in &mut iter {
67 chunk.iter().for_each(&mut f);
68 }
69 iter.remainder().iter().for_each(&mut f);
70}
71
72#[inline(always)]
73#[must_use]
74pub fn is_same_type<A, B>() -> bool
75where
76 A: 'static,
77 B: 'static,
78{
79 use core::any::TypeId;
80 TypeId::of::<A>() == TypeId::of::<B>()
81}
82
83#[inline(always)]
84pub fn slice_parts<T>(slice: &[T]) -> (*const T, usize) {
85 let len = slice.len();
86 let ptr = slice.as_ptr();
87 (ptr, len)
88}
89
90#[cfg(feature = "alloc")]
91#[inline(always)]
92#[must_use]
93pub unsafe fn boxed_str(b: Box<[u8]>) -> Box<str> {
94 let ptr = Box::into_raw(b);
95 Box::from_raw(core::str::from_utf8_unchecked_mut(&mut *ptr))
96}
97
98#[allow(clippy::ptr_as_ptr)]
99#[inline(always)]
100#[cfg_attr(debug_assertions, track_caller)]
101pub unsafe fn transmute_copy<A: Copy, B: Copy>(a: &A) -> B {
102 debug_assert!(core::mem::size_of::<A>() == core::mem::size_of::<B>());
103 *(a as *const A as *const B)
104}