#![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};
use ::core::mem::MaybeUninit;
type BufSlice<T> = [MaybeUninit<T>];
#[cfg(miri)]
#[macro_use]
extern crate std;
#[cfg(feature = "alloc")]
extern crate alloc;
extern crate generic_array;
mod data_buf;
pub use self::data_buf::DataBuf;
pub use self::data_buf::Pod;
pub use fifo::Fifo;
pub use stack::Stack;
pub use value::Value;
#[macro_export]
macro_rules! array_buf {
($t:ty; $n:ident) => { $crate::buffers::ArrayBuf<$t, $crate::buffers::n::$n> }
}
pub mod buffers {
pub use ::generic_array::typenum as n;
pub use self::array_buf::ArrayBuf;
#[cfg(feature="const_generics")]
pub use self::cg_array_buf::ArrayBuf as ConstArrayBuf;
mod array_buf {
use ::core::mem::MaybeUninit;
pub struct ArrayBuf<T, N>
where
N: ::generic_array::ArrayLength<MaybeUninit<T>>,
{
inner: ::generic_array::GenericArray<MaybeUninit<T>, N>,
}
impl<T, N> ::core::default::Default for ArrayBuf<T, N>
where
N: ::generic_array::ArrayLength<MaybeUninit<T>>,
{
fn default() -> Self {
ArrayBuf {
inner: ::generic_array::GenericArray::from_exact_iter( (0 .. N::USIZE).map(|_| MaybeUninit::uninit()) ).unwrap(),
}
}
}
unsafe impl<T,N> crate::DataBuf for ArrayBuf<T, N>
where
T: crate::Pod,
N: ::generic_array::ArrayLength<MaybeUninit<T>>,
{
type Inner = T;
fn as_ref(&self) -> &[MaybeUninit<Self::Inner>] {
&self.inner
}
fn as_mut(&mut self) -> &mut [MaybeUninit<Self::Inner>] {
&mut self.inner
}
fn extend(&mut self, len: usize) -> Result<(), ()> {
if len > N::USIZE {
Err( () )
}
else {
Ok( () )
}
}
}
}
#[cfg(feature="const_generics")]
mod cg_array_buf {
pub struct ArrayBuf<T, const N: usize>
{
inner: [::core::mem::MaybeUninit<T>; N],
}
impl<T:, const N: usize> ::core::default::Default for ArrayBuf<T, N>
where
T: crate::Pod,
{
fn default() -> Self {
ArrayBuf {
inner: [::core::mem::MaybeUninit::uninit(); N],
}
}
}
unsafe impl<T,const N: usize> crate::DataBuf for ArrayBuf<T, N>
where
T: crate::Pod,
{
type Inner = T;
fn as_ref(&self) -> &[::core::mem::MaybeUninit<Self::Inner>] {
&self.inner
}
fn as_mut(&mut self) -> &mut [::core::mem::MaybeUninit<Self::Inner>] {
&mut self.inner
}
fn extend(&mut self, len: usize) -> Result<(), ()> {
if len > N {
Err( () )
}
else {
Ok( () )
}
}
}
}
pub type Ptr8 = ArrayBuf<*const (), n::U8>;
pub type U64_8 = ArrayBuf<u64, n::U8>;
pub type U8_32 = ArrayBuf<u8, n::U32>;
pub type U64_2 = ArrayBuf<u64, n::U2>;
pub type Ptr16 = ArrayBuf<*const (), n::U16>;
pub type Ptr2 = ArrayBuf<*const (), n::U2>;
pub type Ptr1 = ArrayBuf<*const (), n::U1>;
#[cfg(feature="alloc")]
pub type U64Vec = ::alloc::vec::Vec<::core::mem::MaybeUninit<u64>>;
#[cfg(feature="alloc")]
pub type U8Vec = ::alloc::vec::Vec<::core::mem::MaybeUninit<u8>>;
#[cfg(feature="alloc")]
pub type PtrVec = ::alloc::vec::Vec<::core::mem::MaybeUninit<*const ()>>;
}
pub mod fifo;
pub mod stack;
pub mod value;
#[cfg(feature = "const_generics")]
pub type ValueU<T , const N: usize > = Value<T, buffers::ConstArrayBuf<usize, N>>;
#[cfg(feature = "const_generics")]
pub type StackU<T , const N: usize > = Stack<T, buffers::ConstArrayBuf<usize, N>>;
#[cfg(feature = "const_generics")]
pub type FifoU<T , const N: usize > = Fifo<T, buffers::ConstArrayBuf<usize, N>>;
fn decompose_pointer<T: ?Sized>(mut ptr: *const T) -> (*const (), usize, [usize; 3]) {
let addr = ptr as *const ();
let rv = mem_as_slice(&mut ptr);
let mut vals = [0; 3];
assert!(
rv[0] == addr as usize,
"BUG: Pointer layout is not (data_ptr, info...)"
);
vals[..rv.len()-1].copy_from_slice(&rv[1..]);
(addr, rv.len()-1, vals,)
}
fn mem_as_slice<T>(ptr: &mut T) -> &mut [usize] {
assert!(mem::size_of::<T>() % mem::size_of::<usize>() == 0);
assert!(mem::align_of::<T>() % mem::align_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: Pod>(data_ptr: *mut (), meta_vals: &BufSlice<W>) -> *mut T {
#[repr(C)]
#[derive(Copy,Clone)]
struct Raw {
ptr: *const (),
meta: [usize; 4],
}
union Inner<T: ?Sized> {
ptr: *mut T,
raw: Raw,
}
let mut rv = Inner { raw: Raw { ptr: data_ptr, meta: [0; 4] } };
assert!(meta_vals.len() * mem::size_of::<W>() % mem::size_of::<usize>() == 0);
assert!(meta_vals.len() * mem::size_of::<W>() <= 4 * mem::size_of::<usize>());
ptr::copy(
meta_vals.as_ptr() as *const u8,
rv.raw.meta.as_mut_ptr() as *mut u8,
meta_vals.len() * mem::size_of::<W>()
);
let rv = rv.ptr;
assert_eq!(rv as *const (), data_ptr as *const ());
rv
}
fn store_metadata<W: Pod>(dst: &mut BufSlice<W>, meta_words: &[usize]) {
let n_bytes = meta_words.len() * mem::size_of::<usize>();
assert!(n_bytes <= dst.len() * mem::size_of::<W>(),
"nbytes [{}] <= dst.len() [{}] * sizeof [{}]", 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_gen<T, W: Pod>(meta: &mut BufSlice<W>, data: &mut BufSlice<W>, count: usize, mut gen: impl FnMut(usize)->T, reset_slot: &mut usize, reset_value: usize)
{
struct PanicState<'a, T>(*mut T, usize, &'a mut usize, usize);
impl<'a, T> ::core::ops::Drop for PanicState<'a, T> {
fn drop(&mut self) {
if self.0.is_null() {
return ;
}
*self.2 = self.3;
unsafe {
while self.1 != 0 {
ptr::drop_in_place(&mut *self.0);
ptr::write_bytes(self.0 as *mut u8, 0, mem::size_of::<T>());
self.0 = self.0.offset(1);
self.1 -= 1;
}
}
}
}
let mut ptr = data.as_mut_ptr() as *mut T;
let mut clr = PanicState(ptr, 0, reset_slot, reset_value);
for i in 0 .. count {
let val = gen(i);
ptr::write(ptr, val);
ptr = ptr.offset(1);
clr.1 += 1;
}
clr.0 = ptr::null_mut(); crate::store_metadata(meta, &[count]);
}
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>()
);
}
}