#![cfg_attr(feature = "unsize", feature(unsize))] #![cfg_attr(
feature = "full_const_generics",
feature(generic_const_exprs)
)]
#![cfg_attr(feature = "full_const_generics", allow(incomplete_features))]
#![no_std]
#![deny(missing_docs)]
use core::{mem, ptr, slice};
#[cfg(feature = "alloc")]
extern crate alloc;
mod data_buf;
pub use self::data_buf::DataBuf;
pub use self::data_buf::Pod;
pub use list::FifoA;
pub use stack::StackA;
pub use value::ValueA;
pub mod list;
pub mod stack;
pub mod value;
#[cfg(feature = "const_generics")]
pub type Stack<T , const N: usize > = StackA<T, [usize; N]>;
#[cfg(feature = "const_generics")]
pub type Value<T , const N: usize > = ValueA<T, [usize; N]>;
#[cfg(feature = "const_generics")]
pub type Fifo<T , const N: usize > = FifoA<T, [usize; N]>;
fn ptr_as_slice<T: ?Sized>(ptr: &mut *const T) -> &mut [usize] {
let addr = *ptr as *const u8 as usize;
let rv = mem_as_slice(ptr);
assert!(
rv[0] == addr,
"BUG: Pointer layout is not (data_ptr, info...)"
);
rv
}
fn mem_as_slice<T>(ptr: &mut T) -> &mut [usize] {
assert!(mem::size_of::<T>() % mem::size_of::<usize>() == 0);
let words = mem::size_of::<T>() / mem::size_of::<usize>();
unsafe { slice::from_raw_parts_mut(ptr as *mut _ as *mut usize, words) }
}
unsafe fn make_fat_ptr<T: ?Sized, W: Copy>(data_ptr: usize, meta_vals: &[W]) -> *mut T {
let mut rv = mem::MaybeUninit::<*mut T>::uninit();
{
let s = mem_as_slice(&mut rv);
s[0] = data_ptr;
ptr::copy(
meta_vals.as_ptr() as *const u8,
s[1..].as_mut_ptr() as *mut u8,
(s.len() - 1) * mem::size_of::<usize>(),
);
}
let rv = rv.assume_init();
assert_eq!(rv as *const (), data_ptr as *const ());
rv
}
fn store_metadata<W: Copy>(dst: &mut [W], meta_words: &[usize]) {
let n_bytes = meta_words.len() * mem::size_of::<usize>();
assert!(n_bytes <= dst.len() * mem::size_of::<W>());
unsafe {
ptr::copy(
meta_words.as_ptr() as *const u8,
dst.as_mut_ptr() as *mut u8,
n_bytes,
);
}
}
fn round_to_words<T>(len: usize) -> usize {
(len + mem::size_of::<T>() - 1) / mem::size_of::<T>()
}
fn check_fat_pointer<U, T: ?Sized>(v: &U, get_ref: impl FnOnce(&U) -> &T) -> &T {
let ptr: &T = get_ref(v);
assert_eq!(
ptr as *const _ as *const u8, v as *const _ as *const u8,
"MISUSE: Closure returned different pointer"
);
assert_eq!(
mem::size_of_val(ptr),
mem::size_of::<U>(),
"MISUSE: Closure returned a subset pointer"
);
ptr
}
unsafe fn list_push_cloned<T: Clone, W: Copy + Default>(meta: &mut [W], data: &mut [W], v: &[T]) {
assert!(mem::size_of_val(v) <= mem::size_of_val(data));
crate::store_metadata(meta, &[0]);
for v in data.iter_mut() {
*v = Default::default();
}
let mut ptr = data.as_mut_ptr() as *mut T;
for (i, val) in v.iter().enumerate() {
ptr::write(ptr, val.clone());
crate::store_metadata(meta, &[1 + i]);
ptr = ptr.offset(1);
}
}
pub unsafe trait AlignmentValid {
#[doc(hidden)]
fn check();
}
#[cfg(feature = "full_const_generics")]
unsafe impl<S, L> AlignmentValid for (S, L)
where
[(); mem::align_of::<L>() - mem::align_of::<S>()]: Sized,
{
fn check() {}
}
#[cfg(not(feature = "full_const_generics"))]
unsafe impl<S, L> AlignmentValid for (S, L) {
fn check() {
assert!(
mem::align_of::<S>() <= mem::align_of::<L>(),
"TODO: Enforce alignment >{} (requires {})",
mem::align_of::<L>(),
mem::align_of::<S>()
);
}
}