use core::{cmp, mem, ptr};
use core::alloc::Layout;
use core::any::TypeId;
use core::mem::size_of;
use crate::any_value::{AnyValue, Unknown, AnyValueSizeless};
use crate::assert_types_equal;
use crate::clone_type::CloneFn;
use crate::mem::{Mem, MemBuilder, MemResizable};
pub type DropFn = unsafe fn(ptr: *mut u8, len: usize);
pub struct AnyVecRaw<M: MemBuilder> {
pub(crate) mem_builder: M, pub(crate) mem: M::Mem,
pub(crate) len: usize, pub(crate) type_id: TypeId, pub(crate) drop_fn: Option<DropFn>
}
impl<M: MemBuilder> AnyVecRaw<M> {
#[inline]
pub fn new<T: 'static>(mem_builder: M, mem: M::Mem) -> Self {
Self{
mem_builder,
mem,
len: 0,
type_id: TypeId::of::<T>(),
drop_fn:
if !mem::needs_drop::<T>(){
None
} else{
Some(|mut ptr: *mut u8, len: usize|{
for _ in 0..len{
unsafe{
ptr::drop_in_place(ptr as *mut T);
ptr = ptr.add(mem::size_of::<T>());
}
}
})
}
}
}
#[inline]
pub(crate) fn clone_empty(&self) -> Self {
self.clone_empty_in(self.mem_builder.clone())
}
#[inline]
pub(crate) fn clone_empty_in<NewM: MemBuilder>(&self, mut mem_builder: NewM) -> AnyVecRaw<NewM>{
let mem = mem_builder.build(self.element_layout());
AnyVecRaw{
mem_builder,
mem,
len: 0,
type_id: self.type_id,
drop_fn: self.drop_fn,
}
}
pub(crate) unsafe fn clone(&self, clone_fn: CloneFn) -> Self {
let mut cloned = self.clone_empty();
cloned.mem.expand(self.len);
{
let src = self.mem.as_ptr();
let dst = cloned.mem.as_mut_ptr();
(clone_fn)(src, dst, self.len);
}
cloned.len = self.len;
cloned
}
#[inline]
pub(crate) fn index_check(&self, index: usize){
assert!(index < self.len, "Index out of range!");
}
#[inline]
pub(crate) fn type_check<V: AnyValue>(&self, value: &V){
assert_types_equal(value.value_typeid(), self.type_id);
}
#[inline]
pub unsafe fn get_unchecked(&self, index: usize) -> *const u8{
self.mem.as_ptr().add(self.element_layout().size() * index)
}
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> *mut u8{
self.mem.as_mut_ptr().add(self.element_layout().size() * index)
}
#[cold]
#[inline(never)]
fn expand_one(&mut self){
self.mem.expand(1);
}
#[inline]
fn reserve_one(&mut self){
if self.len == self.capacity(){
self.expand_one();
}
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
let new_len = self.len + additional;
if self.capacity() < new_len{
self.mem.expand(new_len - self.capacity());
}
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize)
where M::Mem: MemResizable
{
let new_len = self.len + additional;
if self.capacity() < new_len{
self.mem.expand_exact(new_len - self.capacity());
}
}
pub fn shrink_to_fit(&mut self)
where M::Mem: MemResizable
{
self.mem.resize(self.len);
}
pub fn shrink_to(&mut self, min_capacity: usize)
where M::Mem: MemResizable
{
let new_len = cmp::max(self.len, min_capacity);
self.mem.resize(new_len);
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= self.capacity());
self.len = new_len;
}
pub unsafe fn insert_unchecked<V: AnyValueSizeless>(&mut self, index: usize, value: V) {
assert!(index <= self.len, "Index out of range!");
self.reserve_one();
if !Unknown::is::<V::Type>(){
let element = self.mem.as_mut_ptr().cast::<V::Type>().add(index);
ptr::copy(
element,
element.add(1),
self.len - index
);
value.move_into::<V::Type>(element as *mut u8, size_of::<V::Type>());
} else {
let element_size = self.element_layout().size();
let element = self.mem.as_mut_ptr().add(element_size * index);
crate::copy_bytes(
element,
element.add(element_size),
element_size * (self.len - index)
);
value.move_into::<V::Type>(element, element_size);
}
self.len += 1;
}
#[inline]
pub unsafe fn push_unchecked<V: AnyValueSizeless>(&mut self, value: V) {
self.reserve_one();
if !Unknown::is::<V::Type>(){
let element = self.mem.as_mut_ptr().cast::<V::Type>().add(self.len) as *mut u8;
value.move_into::<V::Type>(element, size_of::<V::Type>());
} else {
let element_size = self.element_layout().size();
let element = self.mem.as_mut_ptr().add(element_size * self.len);
value.move_into::<V::Type>(element, element_size);
};
self.len += 1;
}
pub unsafe fn append_unchecked<T: 'static, OtherM: MemBuilder>(
&mut self, other: &mut AnyVecRaw<OtherM>
) {
self.reserve(other.len);
unsafe {
if !Unknown::is::<T>(){
ptr::copy_nonoverlapping(
other.mem.as_ptr().cast::<T>(),
self.mem.as_mut_ptr().cast::<T>().add(self.len),
other.len
);
} else {
let element_size = self.element_layout().size();
ptr::copy_nonoverlapping(
other.mem.as_ptr(),
self.mem.as_mut_ptr().add(self.len*element_size),
other.len*element_size
);
}
}
self.len += other.len;
other.len = 0;
}
#[inline]
pub fn clear(&mut self){
let len = self.len;
self.len = 0;
if let Some(drop_fn) = self.drop_fn{
unsafe{
(drop_fn)(self.mem.as_mut_ptr(), len);
}
}
}
#[inline]
pub fn element_layout(&self) -> Layout {
self.mem.element_layout()
}
#[inline]
pub fn capacity(&self) -> usize {
self.mem.size()
}
}
impl<M: MemBuilder> Drop for AnyVecRaw<M> {
#[inline]
fn drop(&mut self) {
self.clear();
}
}