vsimd/
tools.rs

1#[cfg(feature = "alloc")]
2item_group! {
3    use core::mem::MaybeUninit;
4    use alloc::boxed::Box;
5}
6
7/// Allocates uninit bytes
8///
9/// # Safety
10/// This function requires:
11///
12/// + `len > 0`
13/// + `len <= isize::MAX`
14///
15#[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}