use std::{
fmt::Debug,
marker::PhantomData,
ops::{Deref, DerefMut},
};
use crate::allocator::{Allocator, DefaultAllocator};
pub type DefaultVector<V> = Vector<V, DefaultAllocator>;
#[repr(C)]
pub struct Vector<T: Sized, A: Allocator> {
pub(crate) begin_ptr: *mut T,
pub(crate) end_ptr: *mut T,
pub(crate) capacity_ptr: *mut T,
pub(crate) allocator: A,
pub(crate) _holds_data: PhantomData<T>,
}
impl<T: Sized, A: Allocator + Default> Vector<T, A> {
pub fn new() -> Self {
unsafe { Self::new_in(A::default()) }
}
pub fn with_capacity(capacity: usize) -> Self {
let mut v = Vector::new();
v.reserve(capacity);
v
}
}
impl<T: Sized, A: Allocator> Vector<T, A> {
pub unsafe fn new_in(allocator: A) -> Self {
Self {
begin_ptr: std::ptr::null_mut(),
end_ptr: std::ptr::null_mut(),
capacity_ptr: std::ptr::null_mut(),
allocator,
_holds_data: PhantomData,
}
}
pub fn as_slice(&self) -> &[T] {
if let Some(begin_ptr) = unsafe { self.begin_ptr.as_ref() } {
unsafe { std::slice::from_raw_parts(begin_ptr, self.len()) }
} else {
&[]
}
}
pub fn as_slice_mut(&mut self) -> &mut [T] {
if let Some(begin_ptr) = unsafe { self.begin_ptr.as_mut() } {
unsafe { std::slice::from_raw_parts_mut(begin_ptr, self.len()) }
} else {
&mut []
}
}
pub fn capacity(&self) -> usize {
(unsafe { self.capacity_ptr.offset_from(self.begin_ptr) }) as usize
}
pub fn clear(&mut self) {
if !self.begin_ptr.is_null() {
unsafe {
std::ptr::drop_in_place(self.as_slice_mut());
self.allocator.deallocate::<T>(self.begin_ptr, self.len())
}
}
self.begin_ptr = std::ptr::null_mut();
self.end_ptr = std::ptr::null_mut();
self.capacity_ptr = std::ptr::null_mut();
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn is_full(&self) -> bool {
self.len() == self.capacity()
}
pub fn len(&self) -> usize {
(unsafe { self.end_ptr.offset_from(self.begin_ptr) }) as usize
}
pub fn push(&mut self, elem: T) {
if self.is_full() {
self.grow();
}
unsafe {
self.end_ptr.write(elem);
self.increment_size();
}
}
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
unsafe {
self.decrement_size();
Some(self.end_ptr.read())
}
}
}
pub fn insert(&mut self, index: usize, elem: T) {
assert!(index <= self.len(), "index out of bounds");
if self.is_full() {
self.grow();
}
unsafe {
self.begin_ptr
.add(index)
.copy_to(self.begin_ptr.add(index + 1), self.len() - index);
self.begin_ptr.add(index).write(elem);
self.increment_size();
}
}
pub fn remove(&mut self, index: usize) -> Option<T> {
if index >= self.len() {
None
} else {
unsafe {
let res = self.begin_ptr.add(index).read();
self.decrement_size();
self.begin_ptr
.add(index)
.copy_from(self.begin_ptr.add(index + 1), self.len() - index);
Some(res)
}
}
}
pub fn reserve(&mut self, additional: usize) {
if additional == 0 {
return;
}
let size = self.len();
let new_capacity = self.capacity() + additional;
let new_begin_ptr = self.allocator.allocate::<T>(new_capacity);
if !self.begin_ptr.is_null() {
unsafe {
new_begin_ptr.copy_from(self.begin_ptr, size);
self.allocator.deallocate(self.begin_ptr, self.capacity());
}
}
self.begin_ptr = new_begin_ptr;
self.end_ptr = unsafe { new_begin_ptr.add(size) };
self.capacity_ptr = unsafe { new_begin_ptr.add(new_capacity) }
}
unsafe fn decrement_size(&mut self) {
self.end_ptr = self.end_ptr.sub(1);
}
unsafe fn increment_size(&mut self) {
self.end_ptr = self.end_ptr.add(1);
}
fn calculate_grow_capacity(old_capacity: usize) -> usize {
if old_capacity == 0 {
1
} else {
old_capacity * 2
}
}
fn grow(&mut self) {
let new_capacity = Self::calculate_grow_capacity(self.capacity());
self.reserve(new_capacity - self.capacity());
}
}
impl<T: Sized + Clone, A: Allocator> Vector<T, A> {
pub unsafe fn from_in(buf: &[T], allocator: A) -> Self {
let mut this = Self::new_in(allocator);
this.assign(buf);
this
}
pub fn append(&mut self, buf: &[T]) {
let old_len = self.len();
let new_len = old_len + buf.len();
if new_len > self.capacity() {
self.reserve(new_len - self.capacity());
}
unsafe {
self.end_ptr = self.end_ptr.add(buf.len());
self.as_slice_mut()[old_len..old_len + buf.len()].clone_from_slice(buf);
}
}
pub fn assign(&mut self, buf: &[T]) {
if buf.len() > self.capacity() {
self.reserve(buf.len() - self.capacity());
}
unsafe {
self.end_ptr = self.begin_ptr.add(buf.len());
self.as_slice_mut().clone_from_slice(buf);
}
}
}
impl<T, A: Allocator> AsRef<[T]> for Vector<T, A> {
fn as_ref(&self) -> &[T] {
self
}
}
impl<T: Clone, A: Allocator + Clone> Clone for Vector<T, A> {
fn clone(&self) -> Self {
unsafe { Self::from_in(self.as_slice(), self.allocator.clone()) }
}
}
impl<T: Debug, A: Allocator> Debug for Vector<T, A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:?}", &self.as_ref()))
}
}
impl<T, A> Drop for Vector<T, A>
where
A: Allocator,
{
fn drop(&mut self) {
self.clear()
}
}
impl<T, A: Allocator + Default> Default for Vector<T, A> {
fn default() -> Self {
unsafe { Vector::new_in(A::default()) }
}
}
impl<T, A: Allocator> Deref for Vector<T, A> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T, A: Allocator> DerefMut for Vector<T, A> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_slice_mut()
}
}
impl<T: Sized + Clone, A: Allocator + Default> From<&[T]> for Vector<T, A> {
fn from(buf: &[T]) -> Self {
let mut v = Vector::new();
v.assign(buf);
v
}
}
impl<T: Sized + Clone, A: Allocator + Default> From<&mut [T]> for Vector<T, A> {
fn from(buf: &mut [T]) -> Self {
let mut v = Vector::new();
v.assign(buf);
v
}
}
impl<T: Sized, const N: usize, A: Allocator + Default> From<[T; N]> for Vector<T, A> {
fn from(buf: [T; N]) -> Self {
let mut v = Vector::with_capacity(buf.len());
for val in buf {
v.push(val);
}
v
}
}
impl<T: Sized + Clone, const N: usize, A: Allocator + Default> From<&[T; N]> for Vector<T, A> {
fn from(buf: &[T; N]) -> Self {
let mut v = Vector::new();
v.assign(buf);
v
}
}
impl<T, A: Allocator + Default> FromIterator<T> for Vector<T, A> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (lower_bound, _) = iter.size_hint();
let mut v = Vector::with_capacity(lower_bound);
for elem in iter {
v.push(elem);
}
v
}
}
unsafe impl<T: Send, A: Allocator + Send> Send for Vector<T, A> {}
unsafe impl<T: Sync, A: Allocator + Sync> Sync for Vector<T, A> {}
#[cfg(test)]
mod test {
use crate::vector::DefaultVector;
use memoffset::offset_of;
#[test]
fn layout() {
assert_eq!(offset_of!(DefaultVector<u32>, begin_ptr), 0);
assert_eq!(
offset_of!(DefaultVector<u32>, end_ptr),
std::mem::size_of::<usize>()
);
assert_eq!(
offset_of!(DefaultVector<u32>, capacity_ptr),
std::mem::size_of::<usize>() * 2
);
assert_eq!(
offset_of!(DefaultVector<u32>, allocator),
std::mem::size_of::<usize>() * 3
);
assert_eq!(
std::mem::size_of::<DefaultVector<u32>>(),
std::mem::size_of::<usize>() * 4
);
}
#[test]
fn empty_vec() {
let v: DefaultVector<u32> = DefaultVector::new();
assert!(v.begin_ptr.is_null());
assert!(v.end_ptr.is_null());
assert!(v.capacity_ptr.is_null());
assert_eq!(v.capacity(), 0);
assert_eq!(v.len(), 0);
assert!(v.is_empty());
}
#[test]
fn push_one() {
let mut v = DefaultVector::new();
v.push(20);
assert_eq!(v.capacity(), 1);
assert_eq!(v.len(), 1);
assert!(!v.is_empty());
let arr = &*v;
assert_eq!(arr.len(), 1);
assert_eq!(arr[0], 20);
assert_eq!(v.pop(), Some(20));
assert_eq!(v.capacity(), 1);
assert_eq!(v.len(), 0);
assert!(v.is_empty());
}
#[test]
fn push_two() {
let mut v = DefaultVector::new();
v.push(20);
v.push(25);
assert_eq!(v.capacity(), 2);
assert_eq!(v.len(), 2);
assert!(!v.is_empty());
let arr = &mut *v;
assert_eq!(arr.len(), 2);
assert_eq!(arr[0], 20);
arr[1] = 30;
assert_eq!(v.pop(), Some(30));
assert_eq!(v.len(), 1);
assert_eq!(v.pop(), Some(20));
assert_eq!(v.capacity(), 2);
assert_eq!(v.len(), 0);
assert!(v.is_empty());
}
#[test]
fn push_three() {
let mut v = DefaultVector::new();
v.push(20);
v.push(25);
v.push(30);
assert_eq!(v.capacity(), 4);
assert_eq!(v.len(), 3);
assert!(!v.is_empty());
assert_eq!(v.pop(), Some(30));
assert_eq!(v.len(), 2);
assert_eq!(v.pop(), Some(25));
assert_eq!(v.len(), 1);
assert_eq!(v.pop(), Some(20));
assert_eq!(v.capacity(), 4);
assert_eq!(v.len(), 0);
assert!(v.is_empty());
}
#[test]
fn insert() {
let mut v = DefaultVector::new();
v.push(1);
v.push(2);
v.push(3);
v.push(4);
v.insert(2, 5);
assert_eq!(&*v, &[1, 2, 5, 3, 4]);
assert_eq!(v.capacity(), 8);
}
#[test]
fn remove() {
let mut v = DefaultVector::new();
v.push(1);
v.push(2);
v.push(3);
v.push(4);
assert_eq!(v.remove(2), Some(3));
assert_eq!(&*v, &[1, 2, 4]);
}
#[test]
fn iter() {
let mut v = DefaultVector::new();
v.push(1);
v.push(2);
v.push(3);
assert_eq!(v.iter().sum::<i32>(), 6);
}
#[test]
fn from() {
let v = DefaultVector::from(&[1, 2, 3]);
assert_eq!(v.capacity(), 3);
assert_eq!(v.len(), 3);
assert_eq!(&*v, &[1, 2, 3]);
}
#[test]
fn from_iter() {
let v = (1..4).collect::<DefaultVector<_>>();
assert_eq!(v.capacity(), 3);
assert_eq!(v.len(), 3);
assert_eq!(&*v, &[1, 2, 3]);
}
struct Test<'a> {
r: &'a mut u32,
}
impl<'a> Drop for Test<'a> {
fn drop(&mut self) {
*self.r *= 2;
}
}
#[test]
fn drop() {
let mut foo = 1;
let mut bar = 1;
{
let _ = DefaultVector::from([Test { r: &mut foo }, Test { r: &mut bar }]);
}
assert_eq!(foo, 2);
assert_eq!(bar, 2);
}
#[test]
fn clear() {
let mut v = DefaultVector::from(&[1, 2, 3]);
assert_eq!(v.capacity(), 3);
assert_eq!(v.len(), 3);
assert_eq!(&*v, &[1, 2, 3]);
v.clear();
assert!(v.is_empty());
assert_eq!(v.capacity(), 0);
}
#[test]
fn ensure_clone() {
struct A {
a: *mut u32,
}
impl A {
fn new(a: &mut u32) -> Self {
*a += 1;
Self { a }
}
}
impl Clone for A {
fn clone(&self) -> Self {
Self::new(unsafe { &mut *self.a })
}
}
let mut i = 0;
let a = [A::new(&mut i)];
let _ = DefaultVector::from(&a);
assert_eq!(i, 2);
}
#[test]
fn append() {
let mut v = DefaultVector::from(&[1, 2, 3]);
v.append(&[4, 5, 6]);
assert_eq!(v.len(), 6);
assert_eq!(v.capacity(), 6);
assert_eq!(&*v, &[1, 2, 3, 4, 5, 6]);
}
}