use super::mem_block::*;
use super::traits::*;
use core::marker::PhantomData;
use core::ptr::NonNull;
use core::{mem, ptr};
#[repr(transparent)]
pub struct BaseArray<E, L, P = NonNull<MemBlock<E, L>>>
where
P: BaseArrayPtr<E, L>,
{
data: P,
phantom: PhantomData<(E, L, *mut u8)>,
}
pub struct BaseArrayIter<E, L, P = NonNull<MemBlock<E, L>>>
where
P: BaseArrayPtr<E, L>,
{
array: BaseArray<E, L, P>,
current: *mut E,
end: *mut E,
}
impl<E, L, P> BaseArray<E, L, P>
where
P: BaseArrayPtr<E, L>,
{
pub unsafe fn from_ptr(ptr: P) -> Self {
Self {
data: ptr,
phantom: PhantomData,
}
}
pub fn as_ptr(&self) -> &P {
&self.data
}
pub fn as_ptr_mut(&mut self) -> &mut P {
&mut self.data
}
pub unsafe fn alloc(len: usize) -> Self {
let mut array = Self::from_ptr(P::alloc(len));
array.data._init();
array
}
pub unsafe fn new_lazy(label: L, len: usize) -> Self {
let mut array = Self::alloc(len);
ptr::write(array.get_label_mut(), label);
array
}
pub fn new<F>(label: L, len: usize, mut func: F) -> Self
where
F: FnMut(&mut L, usize) -> E,
{
let array = unsafe { Self::new_lazy(label, len) };
for i in 0..len {
unsafe {
ptr::write(array.data.elem_ptr(i), func(&mut *array.data.lbl_ptr(), i));
}
}
array
}
pub unsafe fn drop(&mut self, len: usize) {
ptr::drop_in_place(self.get_label_mut());
for i in 0..len {
ptr::drop_in_place(self.data.elem_ptr(i));
}
self.drop_lazy(len);
}
pub unsafe fn drop_lazy(&mut self, len: usize) {
self.data._drop();
self.data.dealloc(len);
}
pub unsafe fn cast_into<T, Q>(self) -> BaseArray<T, L, Q>
where
Q: BaseArrayPtr<T, L>,
{
BaseArray::<T, L, Q>::from_ptr(self.data.cast::<T, L, Q>())
}
pub unsafe fn cast_ref<T, Q>(&self) -> &BaseArray<T, L, Q>
where
Q: BaseArrayPtr<T, L>,
{
&*(self as *const BaseArray<E, L, P> as *const BaseArray<T, L, Q>)
}
pub unsafe fn cast_mut<T, Q>(&mut self) -> &mut BaseArray<T, L, Q>
where
Q: BaseArrayPtr<T, L>,
{
&mut *(self as *mut BaseArray<E, L, P> as *mut BaseArray<T, L, Q>)
}
pub fn get_ptr(&self, idx: usize) -> *const E {
self.data.elem_ptr(idx)
}
pub fn get_ptr_mut(&mut self, idx: usize) -> *mut E {
self.data.elem_ptr(idx)
}
pub fn is_null(&self) -> bool {
self.data.is_null()
}
pub unsafe fn get(&self, idx: usize) -> &E {
&*self.get_ptr(idx)
}
pub unsafe fn get_mut(&mut self, idx: usize) -> &mut E {
&mut *self.get_ptr_mut(idx)
}
pub fn get_label(&self) -> &L {
unsafe { &*self.data.lbl_ptr() }
}
pub fn get_label_mut(&mut self) -> &mut L {
unsafe { &mut *self.data.lbl_ptr() }
}
pub unsafe fn as_slice(&self, len: usize) -> &[E] {
core::slice::from_raw_parts(self.get(0), len)
}
pub unsafe fn as_slice_mut(&mut self, len: usize) -> &mut [E] {
core::slice::from_raw_parts_mut(self.get_mut(0), len)
}
pub unsafe fn into_iter(mut self, len: usize) -> BaseArrayIter<E, L, P> {
let current = self.get_mut(0) as *mut E;
let end = current.add(len);
BaseArrayIter {
array: self,
current,
end,
}
}
}
impl<E, L, P> BaseArray<E, L, P>
where
E: Clone,
L: Clone,
P: BaseArrayPtr<E, L>,
{
pub unsafe fn clone(&self, len: usize) -> Self {
Self::new(self.get_label().clone(), len, |_, i| self.get(i).clone())
}
}
impl<E, L, P> Iterator for BaseArrayIter<E, L, P>
where
P: BaseArrayPtr<E, L>,
{
type Item = E;
fn next(&mut self) -> Option<E> {
if self.current == self.end {
None
} else {
unsafe {
let out = Some(ptr::read(self.current));
self.current = self.current.add(1);
out
}
}
}
}
impl<E, L, P> Drop for BaseArrayIter<E, L, P>
where
P: BaseArrayPtr<E, L>,
{
fn drop(&mut self) {
let begin = self.array.get_ptr_mut(0) as usize;
let len = ((self.end as usize) - begin) / mem::size_of::<E>();
unsafe { self.array.drop(len) }
}
}