use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::slice;
use crate::{CSlice, CSliceMut};
pub struct CVecIter<'a, T: 'a> {
inner: &'a CVec<T>,
pos: usize,
}
impl<'a, T> Iterator for CVecIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.pos >= self.inner.len() {
None
} else {
self.pos += 1;
Some(unsafe { self.inner.get_unchecked(self.pos - 1) })
}
}
}
pub struct CVecIterMut<'a, T: 'a> {
inner: &'a mut CVec<T>,
pos: usize,
}
impl<'a, T> Iterator for CVecIterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if self.pos >= self.inner.len() {
None
} else {
self.pos += 1;
Some(unsafe { &mut *self.inner.base.add(self.pos - 1) })
}
}
}
pub struct CVec<T> {
base: *mut T,
len: usize,
dtor: Option<Box<dyn FnOnce(*mut T)>>,
}
impl<T> Drop for CVec<T> {
fn drop(&mut self) {
if let Some(f) = self.dtor.take() {
f(self.base);
}
}
}
impl<T> CVec<T> {
pub unsafe fn new(base: *mut T, len: usize) -> CVec<T> {
assert!(!base.is_null());
CVec {
base,
len,
dtor: None,
}
}
pub unsafe fn new_with_dtor<F>(base: *mut T, len: usize, dtor: F) -> CVec<T>
where
F: FnOnce(*mut T) + 'static,
{
assert!(!base.is_null());
let dtor = Box::new(dtor);
CVec {
base,
len,
dtor: Some(dtor),
}
}
pub fn get(&self, ofs: usize) -> Option<&T> {
if ofs < self.len {
Some(unsafe { &*self.base.add(ofs) })
} else {
None
}
}
pub unsafe fn get_unchecked(&self, ofs: usize) -> &T {
&*self.base.add(ofs)
}
pub fn get_mut(&mut self, ofs: usize) -> Option<&mut T> {
if ofs < self.len {
Some(unsafe { &mut *self.base.add(ofs) })
} else {
None
}
}
pub unsafe fn get_unchecked_mut<'a>(&'a mut self, ofs: usize) -> &mut T {
&mut *self.base.add(ofs)
}
pub unsafe fn into_inner(mut self) -> *mut T {
self.dtor = None;
self.base
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn as_cslice<'a>(&'a self) -> CSlice<'a, T> {
CSlice {
base: self.base,
len: self.len,
_phantom: PhantomData,
}
}
pub fn as_cslice_mut<'a>(&'a mut self) -> CSliceMut<'a, T> {
CSliceMut {
base: self.base,
len: self.len,
_phantom: PhantomData,
}
}
pub fn iter<'a>(&'a self) -> CVecIter<'a, T> {
CVecIter {
inner: self,
pos: 0,
}
}
pub fn iter_mut<'a>(&'a mut self) -> CVecIterMut<'a, T> {
CVecIterMut {
inner: self,
pos: 0,
}
}
}
impl<T> AsRef<[T]> for CVec<T> {
fn as_ref(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.base as *const T, self.len) }
}
}
impl<T> AsMut<[T]> for CVec<T> {
fn as_mut(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.base, self.len) }
}
}
impl<T> Index<usize> for CVec<T> {
type Output = T;
fn index(&self, index: usize) -> &T {
assert!(index < self.len);
unsafe { &*self.base.add(index) }
}
}
impl<T> IndexMut<usize> for CVec<T> {
fn index_mut(&mut self, index: usize) -> &mut T {
assert!(index < self.len);
unsafe { &mut *self.base.add(index) }
}
}
impl<T: Clone> Into<Vec<T>> for CVec<T> {
fn into(self: CVec<T>) -> Vec<T> {
self.as_cslice().into()
}
}