anylist 0.5.4

a list type for any type
Documentation
use std::{alloc::Layout, any::{Any, TypeId}, ptr::{self, copy}};

use std::alloc;
use std::mem;

pub struct AnyList {
    data:*mut u8,
    len: usize,
    current_layout: Layout,
    capacity: usize,
    past_capacity: usize,
    item_size: usize,
    type_id: TypeId
}

impl AnyList {
    fn alloc<T: Any>(size: usize) -> *mut u8 {
        let layout = alloc::Layout::array::<T>(size).unwrap();
        unsafe { alloc::alloc_zeroed(layout) }
    }
    fn dealloc<T: Any>(size: usize, data: *mut u8) {
        let layout = alloc::Layout::array::<T>(size).unwrap();
        unsafe { alloc::dealloc(data, layout) }
    }
    pub fn new<T: Any>() -> AnyList {
        AnyList {
            data: Self::alloc::<T>(1),
            len: 0,
            capacity: 1,
            past_capacity: 1,
            current_layout: Layout::array::<T>(1).unwrap(),
            item_size: mem::size_of::<T>(),
            type_id: TypeId::of::<T>()
        }
    }
    pub fn panic_if_wrong_type<T: Any>(&self) {
        if self.type_id != TypeId::of::<T>() {
            panic!("tried to use anylist with an incorrect type\n expected: {:?}, got: {:?}",
            self.type_id, TypeId::of::<T>());
        }
    }
    pub fn reserve<T: Any>(&mut self, capacity: usize) {
        self.panic_if_wrong_type::<T>();
        if self.capacity > capacity {
            return
        }
        
        let new_data = Self::alloc::<T>(capacity);

        unsafe { copy(self.data, new_data, self.capacity * mem::size_of::<T>()); }
        Self::dealloc::<T>(self.capacity, self.data);
        
        self.capacity = capacity;
        self.data = new_data;
        self.current_layout = Layout::array::<T>(self.capacity).unwrap();
    }
    pub fn index<T: Any>(&self, index: usize) -> &T {
        self.panic_if_wrong_type::<T>();
        assert!(index < self.len);
        unsafe { mem::transmute::<*mut u8, *mut T>(self.data).add(index).as_ref().unwrap() }
    }
    pub fn index_mut<T: Any>(&mut self, index: usize) -> &mut T {
        self.panic_if_wrong_type::<T>();
        assert!(index < self.len);
        unsafe { mem::transmute::<*mut u8, *mut T>(self.data).add(index).as_mut().unwrap() }
    }
    pub fn index_unchecked<T: Any>(&self, index: usize) -> &T {
        unsafe { mem::transmute::<*mut u8, *mut T>(self.data).add(index).as_ref().unwrap() }
    }
    pub fn index_mut_unchecked<T: Any>(&mut self, index: usize) -> &mut T {
        unsafe { mem::transmute::<*mut u8, *mut T>(self.data).add(index).as_mut().unwrap() }
    }
    pub fn push<T: Any>(&mut self, item: T) {
        self.panic_if_wrong_type::<T>();
        if self.len + 1 > self.capacity {
            let past_capacity = self.capacity;
            let new_capacity = self.capacity + self.past_capacity;
            self.reserve::<T>(new_capacity);
            self.past_capacity = past_capacity;
        }

        unsafe { self.data.cast::<T>().add(self.len).write(item) };
        self.len += 1;
    }
    pub fn pop(&mut self) {
        unsafe { self.data.add((self.len - 1) * self.item_size).write_bytes(0, self.item_size) }
        self.len -= 1;
    }
    pub fn remove(&mut self, index: usize) {
        assert!(self.len > 0);
        
        let bytes_moved = (self.len - index) * self.item_size;

        unsafe {
            ptr::copy(
                self.data.add((index + 1) * self.item_size),
                self.data.add(index * self.item_size),
                bytes_moved
            );
        }
        self.len -= 1;
    }
    pub fn insert<T: Any>(&mut self, index: usize, item: T) {
        self.panic_if_wrong_type::<T>();
        if self.len + 1 > self.capacity {
            let past_capacity = self.capacity;
            let new_capacity = self.capacity + self.past_capacity;
            self.reserve::<T>(new_capacity);
            self.past_capacity = past_capacity;
        }

        self.len += 1;
        let casted = self.data.cast::<T>();
        let bytes_moved = self.len - index - 1;
        unsafe {
            ptr::copy(
                casted.add(index),
                casted.add(index + 1),
                bytes_moved
            );
            casted.add(index).write(item);
        }
        
    }
    pub const fn len(&self) -> usize {
        self.len
    }
    pub const fn capacity(&self) -> usize {
        self.capacity
    }
}

impl Drop for AnyList {
    fn drop(&mut self) {
        unsafe { alloc::dealloc(self.data, self.current_layout); }
    }
}

#[cfg(test)]
mod tests;