use std::any::{TypeId, Any};
use crate::anon::Anon;
use crate::iter::{
AnonIter,
AnonIterMut
};
pub struct AnonVec {
inner: Vec<u8>,
size: usize,
len: usize,
typeid: TypeId,
}
impl AnonVec {
pub fn new<T>() -> Self
where
T: Any + 'static,
{
Self {
inner: Vec::new(),
size: std::mem::size_of::<T>(),
len: 0,
typeid: TypeId::of::<T>(),
}
}
pub fn from_size(size: usize, typeid: TypeId) -> Self {
Self {
inner: Vec::new(),
size,
len: 0,
typeid,
}
}
pub fn uninit() -> Self {
Self {
inner: Vec::new(),
size: 0,
len: 0,
typeid: TypeId::of::<i32>(),
}
}
pub fn init<T>(&mut self)
where
T: Any + 'static,
{
self.size = std::mem::size_of::<T>();
self.typeid = TypeId::of::<T>();
}
pub fn init_size(&mut self, size: usize, typeid: TypeId) {
self.size = size;
self.typeid = typeid;
}
pub fn typeid(&self) -> TypeId {
self.typeid
}
pub fn size(&self) -> usize {
self.size
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn is_uninit(&self) -> bool {
self.size == 0
}
pub fn get_ref<T>(&self, index: usize) -> &T
where
T: Any + 'static,
{
let ptr = self.inner.as_ptr() as *const T;
unsafe { &*(ptr.add(index)) }
}
pub fn get_mut<T>(&mut self, index: usize) -> &mut T
where
T: Any + 'static,
{
let ptr = self.inner.as_mut_ptr() as *mut T;
unsafe { &mut *(ptr.add(index)) }
}
pub fn reserve_bytes(&mut self, additional: usize) {
self.inner.reserve(additional);
}
pub fn reserve(&mut self, additional: usize) {
if !self.is_uninit() {
self.inner.reserve(additional * self.size);
}
}
pub fn push<T>(&mut self, val: T)
where
T: Any + 'static,
{
let v = &val as *const T as *const u8;
for i in 0..self.size {
unsafe {
self.inner.push(*(v.add(i)))
}
}
self.len += 1;
}
pub fn push_anon(&mut self, anon: Anon) {
let v = anon.inner();
for _ in 0..self.size {
self.inner.extend(v.iter());
}
self.len += 1;
}
pub fn insert<T>(&mut self, val: T, index: usize) {
let v = &val as *const T as *const u8;
let index = index * self.size;
for i in (0..self.size).rev() {
unsafe {
self.inner.insert(index, *(v.add(i)))
}
}
self.len += 1;
}
pub fn insert_anon(&mut self, anon: Anon, index: usize) {
let v = anon.inner();
let index = index * self.size;
for i in (0..self.size).rev() {
self.inner.insert(index, v[i])
}
self.len += 1;
}
pub fn remove(&mut self, index: usize) {
let index = index * self.size;
for i in (index..index + self.size).rev() {
self.inner.remove(i);
}
self.len -= 1;
}
pub fn remove_get<T>(&mut self, index: usize) -> T
where
T: Any + Clone + 'static,
{
let ptr = self.inner.as_mut_ptr() as *mut T;
let out = unsafe { &*(ptr.add(index)) }.clone();
let index = index * self.size;
for i in (index..index + self.size).rev() {
self.inner.remove(i);
}
self.len -= 1;
out
}
pub fn remove_get_anon(&mut self, index: usize) -> Anon {
let ptr = self.inner.as_ptr();
let out = Anon::from_ptr(ptr, self.size, self.typeid);
let index = index * self.size;
for i in (index..index + self.size).rev() {
self.inner.remove(i);
}
self.len -= 1;
out
}
pub fn pop<T>(&mut self) -> Option<T>
where
T: Any + Clone + 'static,
{
if self.len == 0 {
None
} else {
self.len -= 1;
Some(self.remove_get::<T>(self.len() - 1))
}
}
pub fn pop_anon(&mut self) -> Option<Anon> {
if self.len == 0 {
None
} else {
self.len -= 1;
Some(self.remove_get_anon(self.len() - 1))
}
}
pub fn remove_swap(&mut self, index: usize) {
if index == self.len - 1 {
for _ in 0..self.size {
self.inner.pop();
}
} else {
let index = self.size * index;
for i in (0..self.size).rev() {
self.inner[index + i] = self.inner.pop().unwrap()
}
}
self.len -= 1;
}
pub fn iter<T>(&self) -> AnonIter<T> {
AnonIter {
data: self.inner.as_ptr() as *const T,
curr: 0,
len: self.inner.len(),
}
}
pub fn iter_mut<T>(&mut self) -> AnonIterMut<T> {
AnonIterMut {
data: self.inner.as_mut_ptr() as *mut T,
curr: 0,
len: self.inner.len(),
}
}
}
#[cfg(test)]
mod tests {
use std::any::TypeId;
use crate::vec::AnonVec;
const THING: Thing = Thing { a: 1, b: 2, c: 3 };
#[repr(C)]
#[derive(PartialEq, Debug, Clone)]
struct Thing {
pub a: i32,
pub b: i32,
pub c: i32,
}
impl Thing {
fn sum(&self) -> i32 {
self.a + self.b + self.c
}
}
#[test]
fn new() {
let mut anon = AnonVec::new::<Thing>();
{
anon.push::<Thing>(THING);
anon.push::<Thing>(THING);
anon.push::<Thing>(THING);
}
let t1 = anon.get_ref::<Thing>(0);
let t2 = anon.get_ref::<Thing>(1);
let t3 = anon.get_ref::<Thing>(2);
let v = t1.sum() + t2.sum() + t3.sum();
assert_eq!(v, 18);
}
#[test]
fn from_size() {
let mut anon = AnonVec::from_size(std::mem::size_of::<Thing>(), TypeId::of::<Thing>());
{
anon.push::<Thing>(THING);
anon.push::<Thing>(THING);
anon.push::<Thing>(THING);
}
let t1 = anon.get_ref::<Thing>(0);
let t2 = anon.get_ref::<Thing>(1);
let t3 = anon.get_ref::<Thing>(2);
let v = t1.sum() + t2.sum() + t3.sum();
assert_eq!(v, 18);
}
#[test]
fn uninit_init() {
let mut anon = AnonVec::uninit();
{
anon.init::<Thing>();
anon.push::<Thing>(THING);
anon.push::<Thing>(THING);
anon.push::<Thing>(THING);
}
let t1 = anon.get_ref::<Thing>(0);
let t2 = anon.get_ref::<Thing>(1);
let t3 = anon.get_ref::<Thing>(2);
let v = t1.sum() + t2.sum() + t3.sum();
assert_eq!(v, 18);
}
}