mirror of
https://git.intege.rs/xlib/x.git
synced 2025-12-05 20:35:01 +00:00
149 lines
4.2 KiB
Rust
149 lines
4.2 KiB
Rust
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<T>(value: &T) -> &[u8] {
|
|
let ptr = value as *const T as *const u8;
|
|
unsafe { core::slice::from_raw_parts(ptr, core::mem::size_of::<T>()) }
|
|
}
|
|
|
|
/// Converts reference of struct to binary slice
|
|
pub unsafe fn slicify_mut<T>(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::<T>())
|
|
}
|
|
|
|
/// converts a non mutable reference into a mutable one
|
|
#[allow(invalid_reference_casting)]
|
|
pub unsafe fn mutify<T>(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<T>(*const T);
|
|
pub struct PIterMut<T>(*mut T);
|
|
|
|
impl<T: 'static> Iterator for PIter<T> {
|
|
type Item = &'static T;
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
unsafe {
|
|
let r = Some(&*self.0);
|
|
self.0 = self.0.offset(1isize);
|
|
r
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: 'static> Iterator for PIterMut<T> {
|
|
type Item = &'static mut T;
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
unsafe {
|
|
let r = Some(&mut *self.0);
|
|
self.0 = self.0.offset(1isize);
|
|
r
|
|
}
|
|
}
|
|
}
|
|
impl<T> Pointer for *const T {
|
|
type IterType = PIter<T>;
|
|
fn into_iter(self) -> Self::IterType { PIter(self) }
|
|
}
|
|
impl<T> Pointer for *mut T {
|
|
type IterType = PIterMut<T>;
|
|
fn into_iter(self) -> Self::IterType { PIterMut(self) }
|
|
}
|
|
}
|
|
|
|
pub fn iterate<T: pointer_iterator::Pointer>(pointer: T) -> T::IterType {
|
|
pointer.into_iter()
|
|
}
|
|
|
|
pub fn fill_with<T, F: FnMut(usize) -> T>(slice: &mut [T], mut func: F) {
|
|
slice.iter_mut().enumerate().for_each(|(i,v)|*v = func(i))
|
|
}
|
|
|
|
pub struct FixedVec<const MAX_LEN: usize, T> {
|
|
length: usize,
|
|
buffer: [core::mem::MaybeUninit<T>;MAX_LEN],
|
|
}
|
|
|
|
impl<const MAX_LEN: usize, T: Sized> FixedVec<MAX_LEN, T> {
|
|
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<T> {
|
|
if self.length == 0 { return None }
|
|
self.length -= 1;
|
|
Some(unsafe { self.buffer[self.length].assume_init_read() })
|
|
}
|
|
|
|
pub fn extend<Iter: Iterator<Item=T>>(&mut self, mut iter: Iter) -> Result<usize, usize> {
|
|
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<const MAX_LEN: usize, T: Debug> Debug for FixedVec<MAX_LEN, T> {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
|
Debug::fmt(self.as_slice(), f)
|
|
}
|
|
}
|
|
|
|
impl<const MAX_LEN: usize, T> Drop for FixedVec<MAX_LEN, T> {
|
|
fn drop(&mut self) {
|
|
for e in &mut self.buffer[..self.length] {
|
|
unsafe { e.assume_init_drop() }
|
|
}
|
|
}
|
|
} |