use core::cmp::{Ordering, PartialOrd};
use core::intrinsics::{assume, ptr_offset_from};
use core::mem::{ size_of, MaybeUninit};
use crate::StaticVec;
#[inline(always)]
pub(crate) const fn distance_between<T>(dest: *const T, origin: *const T) -> usize {
match size_of::<T>() {
0 => unsafe { (dest as usize).wrapping_sub(origin as usize) },
_ => unsafe { ptr_offset_from(dest, origin) as usize },
}
}
#[inline(always)]
pub(crate) const fn const_min(lhs: usize, rhs: usize) -> usize {
if lhs < rhs {
lhs
} else {
rhs
}
}
#[inline]
pub(crate) const fn reverse_copy<T, const N: usize>(
length: usize,
this: &MaybeUninit<[T; N]>,
) -> MaybeUninit<[T; N]>
where
T: Copy,
{
let mut i = length;
let src = StaticVec::first_ptr(this);
let mut res = StaticVec::new_data_uninit();
let mut dest = StaticVec::first_ptr_mut(&mut res);
unsafe {
assume(!src.is_null());
assume(!(dest as *mut T).is_null());
}
while i > 0 {
unsafe {
src.add(i - 1).copy_to_nonoverlapping(dest, 1);
dest = dest.offset(1);
i -= 1;
}
}
res
}
#[inline(always)]
pub fn new_from_value<T, const COUNT: usize>(value: T) -> StaticVec<T, COUNT>
where T: Copy {
StaticVec {
data: {
unsafe {
let mut data = StaticVec::new_data_uninit();
for i in 0..COUNT {
(data.as_mut_ptr() as *mut T).add(i).write(value);
}
data
}
},
length: COUNT,
}
}
pub(crate) const fn zst_ptr_add_mut<T>(ptr: *mut T, offset: usize) -> *mut T {
unsafe { (ptr as usize + offset) as *mut T }
}
pub(crate) const fn zst_ptr_add<T>(ptr: *const T, offset: usize) -> *const T {
unsafe { (ptr as usize + offset) as *const T }
}
#[inline]
pub(crate) fn partial_compare<T1, T2: PartialOrd<T1>>(
this: &[T2],
other: &[T1],
) -> Option<Ordering> {
let min_length = this.len().min(other.len());
unsafe {
let left = this.get_unchecked(0..min_length);
let right = other.get_unchecked(0..min_length);
for i in 0..min_length {
match left.get_unchecked(i).partial_cmp(right.get_unchecked(i)) {
Some(Ordering::Equal) => (),
non_eq => return non_eq,
}
}
}
this.len().partial_cmp(&other.len())
}
#[inline]
pub(crate) const fn quicksort_internal<T: Copy + PartialOrd>(
values: *mut T,
mut low: isize,
mut high: isize,
) {
unsafe { assume(!values.is_null()) };
loop {
let mut i = low;
let mut j = high;
unsafe {
let p = *values.offset(low + ((high - low) >> 1));
loop {
while *values.offset(i) < p {
i += 1;
}
while *values.offset(j) > p {
j -= 1;
}
if i <= j {
if i != j {
let q = *values.offset(i);
*values.offset(i) = *values.offset(j);
*values.offset(j) = q;
}
i += 1;
j -= 1;
}
if i > j {
break;
}
}
}
if j - low < high - i {
if low < j {
quicksort_internal(values, low, j);
}
low = i;
} else {
if i < high {
quicksort_internal(values, i, high)
}
high = j;
}
if low >= high {
break;
}
}
}
#[inline(always)]
pub(crate) const fn slice_from_raw_parts<'a, T>(data: *const T, length: usize) -> &'a [T] {
debug_assert!(
!data.is_null(),
"Attempted to create a null slice!"
);
debug_assert!(
size_of::<T>().saturating_mul(length) <= isize::MAX as usize,
"Attempted to create a slice covering at least half of the address space!"
);
unsafe { &*core::ptr::slice_from_raw_parts(data, length) }
}
#[inline(always)]
pub(crate) const fn slice_from_raw_parts_mut<'a, T>(data: *mut T, length: usize) -> &'a mut [T] {
debug_assert!(
!data.is_null(),
"Attempted to create a null slice!"
);
debug_assert!(
size_of::<T>().saturating_mul(length) <= isize::MAX as usize,
"Attempted to create a slice covering at least half of the address space!"
);
unsafe { &mut *core::ptr::slice_from_raw_parts_mut(data, length) }
}