use core::cmp::Ordering; use core::fmt::{Debug, Formatter}; use crate::upcast::IntoUsize; //noinspection SpellCheckingInspection /// Converts reference of struct to binary slice pub fn slicify(value: &T) -> &[u8] { let ptr = value as *const T as *const u8; unsafe { core::slice::from_raw_parts(ptr, core::mem::size_of::()) } } /// Converts reference of struct to binary slice pub unsafe fn slicify_mut(value: &mut T) -> &mut [u8] { let ptr = value as *mut T as *mut u8; core::slice::from_raw_parts_mut(ptr, core::mem::size_of::()) } /// converts a non mutable reference into a mutable one #[allow(invalid_reference_casting)] pub unsafe fn mutify(nr: &T) -> &mut T { &mut *(nr as *const T as *mut T) } /// converts a reference of any lifetime to 'static pub unsafe fn statify<'a, T>(nr: &'a T) -> &'static T { &*(nr as *const T) } /// converts mutable a reference of any lifetime to 'static pub unsafe fn statify_mut<'a, T>(nr: &'a mut T) -> &'static mut T { &mut *(nr as *mut T) } /// gets the distance between two references pub fn distance(p1: impl IntoUsize, p2: impl IntoUsize) -> usize { let (p1, p2) = (p1.into_usize(), p2.into_usize()); match p1.cmp(&p2) { Ordering::Less => p2 - p1, Ordering::Greater => p1 - p2, Ordering::Equal => 0, } } mod pointer_iterator { pub trait Pointer { type IterType; fn into_iter(self) -> Self::IterType; } pub struct PIter(*const T); pub struct PIterMut(*mut T); impl Iterator for PIter { type Item = &'static T; fn next(&mut self) -> Option { unsafe { let r = Some(&*self.0); self.0 = self.0.offset(1isize); r } } } impl Iterator for PIterMut { type Item = &'static mut T; fn next(&mut self) -> Option { unsafe { let r = Some(&mut *self.0); self.0 = self.0.offset(1isize); r } } } impl Pointer for *const T { type IterType = PIter; fn into_iter(self) -> Self::IterType { PIter(self) } } impl Pointer for *mut T { type IterType = PIterMut; fn into_iter(self) -> Self::IterType { PIterMut(self) } } } pub fn iterate(pointer: T) -> T::IterType { pointer.into_iter() } pub fn fill_with T>(slice: &mut [T], mut func: F) { slice.iter_mut().enumerate().for_each(|(i,v)|*v = func(i)) } pub struct FixedVec { length: usize, buffer: [core::mem::MaybeUninit;MAX_LEN], } impl FixedVec { pub fn push(&mut self, value: T) -> Option<()> { if self.length >= MAX_LEN { return None } unsafe { *self.buffer[self.length].as_mut_ptr() = value }; self.length += 1; Some(()) } pub fn pop(&mut self) -> Option { if self.length == 0 { return None } self.length -= 1; Some(unsafe { self.buffer[self.length].assume_init_read() }) } pub fn extend>(&mut self, mut iter: Iter) -> Result { let mut count = 0; loop { if self.length == MAX_LEN { return Err(count); } match iter.next() { None => return Ok(count), Some(value) => { unsafe { *self.buffer[self.length].as_mut_ptr() = value }; self.length += 1; count += 1; } } } } pub fn as_slice(&self) -> &[T] { // length can't be larger than MaxLen, use unsafe to dodge the panic unsafe { core::slice::from_raw_parts(self.buffer.as_ptr() as *const T, self.length) } } } impl Debug for FixedVec { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { Debug::fmt(self.as_slice(), f) } } impl Drop for FixedVec { fn drop(&mut self) { for e in &mut self.buffer[..self.length] { unsafe { e.assume_init_drop() } } } }