#![allow(unsafe_code)]
use std::alloc::{self, Layout};
use std::marker::PhantomData;
use std::ptr::{self, NonNull};
pub struct TruenoVec<T> {
ptr: NonNull<T>,
len: usize,
capacity: usize,
_marker: PhantomData<T>,
}
impl<T> TruenoVec<T> {
#[must_use]
pub const fn new() -> Self {
Self { ptr: NonNull::dangling(), len: 0, capacity: 0, _marker: PhantomData }
}
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
if capacity == 0 {
Self::new()
} else {
let layout = Layout::array::<T>(capacity).expect("capacity overflow");
let ptr = unsafe {
let ptr = alloc::alloc(layout).cast::<T>();
NonNull::new(ptr).expect("allocation failed")
};
Self { ptr, len: 0, capacity, _marker: PhantomData }
}
}
#[must_use]
pub const fn len(&self) -> usize {
self.len
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[must_use]
pub const fn capacity(&self) -> usize {
self.capacity
}
pub fn push(&mut self, value: T) {
if self.len == self.capacity {
self.grow();
}
unsafe {
ptr::write(self.ptr.as_ptr().add(self.len), value);
}
self.len += 1;
}
#[allow(clippy::missing_const_for_fn)] pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
self.len -= 1;
unsafe { Some(ptr::read(self.ptr.as_ptr().add(self.len))) }
}
}
#[must_use]
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.len {
unsafe { Some(&*self.ptr.as_ptr().add(index)) }
} else {
None
}
}
#[must_use]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.len {
unsafe { Some(&mut *self.ptr.as_ptr().add(index)) }
} else {
None
}
}
pub fn clear(&mut self) {
while self.pop().is_some() {}
}
pub fn insert(&mut self, index: usize, value: T) {
assert!(index <= self.len, "insertion index out of bounds");
if self.len == self.capacity {
self.grow();
}
unsafe {
let ptr = self.ptr.as_ptr();
if index < self.len {
ptr::copy(ptr.add(index), ptr.add(index + 1), self.len - index);
}
ptr::write(ptr.add(index), value);
}
self.len += 1;
}
pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len, "removal index out of bounds");
unsafe {
let ptr = self.ptr.as_ptr();
let value = ptr::read(ptr.add(index));
if index < self.len - 1 {
ptr::copy(ptr.add(index + 1), ptr.add(index), self.len - index - 1);
}
self.len -= 1;
value
}
}
#[must_use]
pub const fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
}
#[must_use]
pub const fn as_slice_mut(&mut self) -> &mut [T] {
unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
}
fn grow(&mut self) {
let new_capacity = if self.capacity == 0 {
1
} else {
self.capacity.checked_mul(2).expect("capacity overflow")
};
let new_layout = Layout::array::<T>(new_capacity).expect("capacity overflow");
let new_ptr = if self.capacity == 0 {
unsafe {
let ptr = alloc::alloc(new_layout).cast::<T>();
NonNull::new(ptr).expect("allocation failed")
}
} else {
let old_layout = Layout::array::<T>(self.capacity).expect("capacity overflow");
unsafe {
let ptr =
alloc::realloc(self.ptr.as_ptr().cast::<u8>(), old_layout, new_layout.size())
.cast::<T>();
NonNull::new(ptr).expect("allocation failed")
}
};
self.ptr = new_ptr;
self.capacity = new_capacity;
}
}
impl<T> Default for TruenoVec<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Drop for TruenoVec<T> {
fn drop(&mut self) {
while self.pop().is_some() {}
if self.capacity > 0 {
let layout = Layout::array::<T>(self.capacity).expect("capacity overflow");
unsafe {
alloc::dealloc(self.ptr.as_ptr().cast::<u8>(), layout);
}
}
}
}
unsafe impl<T: Send> Send for TruenoVec<T> {}
unsafe impl<T: Sync> Sync for TruenoVec<T> {}
impl<T> From<Vec<T>> for TruenoVec<T> {
fn from(vec: Vec<T>) -> Self {
let mut trueno = Self::with_capacity(vec.len());
for item in vec {
trueno.push(item);
}
trueno
}
}
impl<T: Clone> From<&[T]> for TruenoVec<T> {
fn from(slice: &[T]) -> Self {
let mut trueno = Self::with_capacity(slice.len());
for item in slice {
trueno.push(item.clone());
}
trueno
}
}
impl<T> FromIterator<T> for TruenoVec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (lower_bound, _) = iter.size_hint();
let mut trueno = Self::with_capacity(lower_bound);
for item in iter {
trueno.push(item);
}
trueno
}
}
impl<T> Extend<T> for TruenoVec<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let iter = iter.into_iter();
let (lower_bound, _) = iter.size_hint();
if lower_bound > 0 {
let needed_capacity = self.len.saturating_add(lower_bound);
while self.capacity < needed_capacity {
self.grow();
}
}
for item in iter {
self.push(item);
}
}
}
pub struct Iter<'a, T> {
ptr: *const T,
end: *const T,
_marker: PhantomData<&'a T>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.ptr == self.end {
None
} else {
unsafe {
let item = &*self.ptr;
self.ptr = self.ptr.add(1);
Some(item)
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = std::mem::size_of::<T>();
let len = if size == 0 { 0 } else { (self.end as usize - self.ptr as usize) / size };
(len, Some(len))
}
}
impl<T> ExactSizeIterator for Iter<'_, T> {}
impl<T> DoubleEndedIterator for Iter<'_, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.ptr == self.end {
None
} else {
unsafe {
self.end = self.end.sub(1);
Some(&*self.end)
}
}
}
}
pub struct IterMut<'a, T> {
ptr: *mut T,
end: *mut T,
_marker: PhantomData<&'a mut T>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if self.ptr == self.end {
None
} else {
unsafe {
let item = &mut *self.ptr;
self.ptr = self.ptr.add(1);
Some(item)
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = std::mem::size_of::<T>();
let len = if size == 0 { 0 } else { (self.end as usize - self.ptr as usize) / size };
(len, Some(len))
}
}
impl<T> ExactSizeIterator for IterMut<'_, T> {}
impl<T> DoubleEndedIterator for IterMut<'_, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.ptr == self.end {
None
} else {
unsafe {
self.end = self.end.sub(1);
Some(&mut *self.end)
}
}
}
}
pub struct IntoIter<T> {
vec: TruenoVec<T>,
current: usize,
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.current < self.vec.len {
let index = self.current;
self.current += 1;
unsafe { Some(ptr::read(self.vec.ptr.as_ptr().add(index))) }
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.vec.len - self.current;
(remaining, Some(remaining))
}
}
impl<T> ExactSizeIterator for IntoIter<T> {}
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
while self.current < self.vec.len {
unsafe {
ptr::drop_in_place(self.vec.ptr.as_ptr().add(self.current));
}
self.current += 1;
}
if self.vec.capacity > 0 {
let layout = Layout::array::<T>(self.vec.capacity).expect("capacity overflow");
unsafe {
alloc::dealloc(self.vec.ptr.as_ptr().cast::<u8>(), layout);
}
}
self.vec.capacity = 0;
self.vec.len = 0;
}
}
impl<T> TruenoVec<T> {
#[must_use]
pub const fn iter(&self) -> Iter<'_, T> {
unsafe {
Iter {
ptr: self.ptr.as_ptr(),
end: self.ptr.as_ptr().add(self.len),
_marker: PhantomData,
}
}
}
#[must_use]
pub const fn iter_mut(&mut self) -> IterMut<'_, T> {
unsafe {
IterMut {
ptr: self.ptr.as_ptr(),
end: self.ptr.as_ptr().add(self.len),
_marker: PhantomData,
}
}
}
}
impl<T> IntoIterator for TruenoVec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter { vec: self, current: 0 }
}
}
impl<'a, T> IntoIterator for &'a TruenoVec<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut TruenoVec<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T> std::ops::Index<usize> for TruenoVec<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
let len = self.len;
self.get(index).unwrap_or_else(|| {
panic!("index out of bounds: the len is {len} but the index is {index}")
})
}
}
impl<T> std::ops::IndexMut<usize> for TruenoVec<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
let len = self.len;
self.get_mut(index).unwrap_or_else(|| {
panic!("index out of bounds: the len is {len} but the index is {index}")
})
}
}
impl<T: Clone> Clone for TruenoVec<T> {
fn clone(&self) -> Self {
let mut new_vec = Self::with_capacity(self.len);
for elem in self {
new_vec.push(elem.clone());
}
new_vec
}
}
impl<T: PartialEq> PartialEq for TruenoVec<T> {
fn eq(&self, other: &Self) -> bool {
if self.len != other.len {
return false;
}
for i in 0..self.len {
if self.get(i) != other.get(i) {
return false;
}
}
true
}
}
impl<T: Eq> Eq for TruenoVec<T> {}
impl<T: std::fmt::Debug> std::fmt::Debug for TruenoVec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T> std::ops::Deref for TruenoVec<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T> std::ops::DerefMut for TruenoVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_slice_mut()
}
}
impl<T> AsRef<[T]> for TruenoVec<T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> AsMut<[T]> for TruenoVec<T> {
fn as_mut(&mut self) -> &mut [T] {
self.as_slice_mut()
}
}
impl<T> AsRef<Self> for TruenoVec<T> {
fn as_ref(&self) -> &Self {
self
}
}
impl<T> AsMut<Self> for TruenoVec<T> {
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<T: PartialOrd> PartialOrd for TruenoVec<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
fn lt(&self, other: &Self) -> bool {
self.as_slice() < other.as_slice()
}
fn le(&self, other: &Self) -> bool {
self.as_slice() <= other.as_slice()
}
fn gt(&self, other: &Self) -> bool {
self.as_slice() > other.as_slice()
}
fn ge(&self, other: &Self) -> bool {
self.as_slice() >= other.as_slice()
}
}
impl<T: Ord> Ord for TruenoVec<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<T: std::hash::Hash> std::hash::Hash for TruenoVec<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.len.hash(state);
for elem in self {
elem.hash(state);
}
}
}
impl<T: std::fmt::Display> std::fmt::Display for TruenoVec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[")?;
for (i, elem) in self.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{elem}")?;
}
write!(f, "]")
}
}
impl<T> std::borrow::Borrow<[T]> for TruenoVec<T> {
fn borrow(&self) -> &[T] {
self.as_slice()
}
}
impl<T> std::borrow::BorrowMut<[T]> for TruenoVec<T> {
fn borrow_mut(&mut self) -> &mut [T] {
self.as_slice_mut()
}
}
#[cfg(test)]
#[path = "tests.rs"]
mod vec_tests;
#[cfg(test)]
#[path = "property_tests.rs"]
mod vec_property_tests;