use std::{
fmt::Debug,
hash::Hash,
io::Write,
iter::{FromIterator, FusedIterator},
mem::{size_of, ManuallyDrop},
ops::{Deref, DerefMut},
};
use crate::{
alloc::{Allocator, Layout, XLangAlloc},
ptr::Unique,
};
#[repr(C)]
pub struct Vec<T, A: Allocator = XLangAlloc> {
ptr: Unique<T>,
cap: usize,
len: usize,
alloc: A,
}
impl<T> Vec<T, XLangAlloc> {
#[must_use]
pub fn new() -> Self {
Self::new_in(XLangAlloc::new())
}
#[must_use]
pub fn with_capacity(cap: usize) -> Self {
Self::with_capacity_in(cap, XLangAlloc::new())
}
pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize, len: usize) -> Self {
Self::from_raw_parts_in(ptr, cap, len, XLangAlloc::new())
}
}
impl<T, A: Allocator> Drop for Vec<T, A> {
fn drop(&mut self) {
if core::mem::needs_drop::<T>() {
let ptr = self.ptr.as_ptr();
for i in 0..self.len {
unsafe { core::ptr::drop_in_place(ptr.add(i)) }
}
}
let layout = unsafe {
Layout::from_size_align_unchecked(
self.cap.checked_mul(core::mem::size_of::<T>()).unwrap(),
core::mem::align_of::<T>(),
)
};
if layout.size() != 0 {
unsafe {
self.alloc.deallocate(self.ptr.as_nonnull().cast(), layout);
}
}
}
}
impl<T, A: Allocator> Vec<T, A> {
pub fn new_in(alloc: A) -> Self {
Self {
ptr: Unique::dangling(),
cap: 0,
len: 0,
alloc,
}
}
pub fn with_capacity_in(cap: usize, alloc: A) -> Self {
let cap = cap.checked_next_power_of_two().unwrap();
let raw_cap = cap.checked_mul(core::mem::size_of::<T>()).unwrap();
if raw_cap == 0 {
Self {
ptr: Unique::dangling(),
cap,
len: 0,
alloc,
}
} else {
let ptr = alloc
.allocate(unsafe {
Layout::from_size_align_unchecked(raw_cap, core::mem::align_of::<T>())
})
.unwrap_or_else(|| {
crate::alloc::handle_alloc_error(unsafe {
Layout::from_size_align_unchecked(raw_cap, core::mem::align_of::<T>())
})
})
.cast();
Self {
ptr: unsafe { Unique::new_nonnull_unchecked(ptr) },
cap,
len: 0,
alloc,
}
}
}
pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, len: usize, alloc: A) -> Self {
Self {
ptr: Unique::new_unchecked(ptr),
cap,
len,
alloc,
}
}
pub fn allocator(&self) -> &A {
&self.alloc
}
pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
let this = ManuallyDrop::new(self);
let ptr = this.ptr.as_ptr();
let cap = this.cap;
let len = this.len;
(ptr, cap, len)
}
pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) {
let this = ManuallyDrop::new(self);
let ptr = this.ptr.as_ptr();
let cap = this.cap;
let len = this.len;
let alloc = unsafe { core::ptr::read(&this.alloc) };
(ptr, cap, len, alloc)
}
fn reallocate(&mut self, ncap: usize) {
if ncap > self.cap {
let raw_cap = ncap.checked_mul(core::mem::size_of::<T>()).unwrap();
if raw_cap == 0 {
return;
}
let ptr = unsafe {
self.alloc.grow(
self.ptr.as_nonnull().cast(),
Layout::from_size_align_unchecked(
self.cap * core::mem::size_of::<T>(),
core::mem::align_of::<T>(),
),
Layout::from_size_align_unchecked(raw_cap, core::mem::align_of::<T>()),
)
}
.unwrap_or_else(|| {
crate::alloc::handle_alloc_error(unsafe {
Layout::from_size_align_unchecked(
self.cap * core::mem::size_of::<T>(),
core::mem::align_of::<T>(),
)
})
});
self.cap = ncap;
self.ptr = unsafe { Unique::new_nonnull_unchecked(ptr.cast()) };
}
}
pub unsafe fn set_len(&mut self, len: usize) {
self.len = len;
}
#[inline]
pub fn push(&mut self, val: T) {
if self.len == self.cap {
let ncap = (self.cap + 1).checked_next_power_of_two().unwrap();
self.reallocate(ncap);
}
let ptr = self.ptr.as_ptr();
unsafe {
ptr.add(self.len).write(val);
}
self.len += 1;
}
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
self.len -= 1;
let ptr = self.ptr.as_ptr();
unsafe { Some(ptr.add(self.len).read()) }
}
}
pub fn reserve(&mut self, additional: usize) {
let ncap = self
.len
.checked_add(additional)
.unwrap()
.checked_next_power_of_two()
.unwrap();
if self.cap < ncap {
self.reallocate(ncap);
}
}
pub fn leak<'a>(self) -> &'a mut [T]
where
A: 'a,
{
let this = ManuallyDrop::new(self);
let ptr = this.ptr.as_ptr();
let len = this.len;
unsafe { core::slice::from_raw_parts_mut(ptr, len) }
}
pub fn capacity(&self) -> usize {
self.cap
}
pub fn clear(&mut self) {
let len = self.len;
self.len = 0;
if core::mem::needs_drop::<T>() {
let ptr = self.ptr.as_ptr();
for i in 0..len {
unsafe { core::ptr::drop_in_place(ptr.add(i)) }
}
}
}
pub fn extend_from_slice(&mut self, x: &[T])
where
T: Clone,
{
self.reserve(x.len());
for v in x {
self.push(v.clone());
}
}
pub fn as_mut_ptr(&mut self) -> *mut T {
self.ptr.as_ptr()
}
pub fn as_ptr(&self) -> *const T {
self.ptr.as_ptr()
}
#[must_use = "If you don't need the split off elements use `Self::shrink` instead"]
pub fn split_off(&mut self, n: usize) -> Self
where
A: Clone,
{
assert!(n <= self.len);
let nlen = self.len - n;
let mut new = Self::with_capacity_in(nlen, self.alloc.clone());
unsafe {
self.set_len(n);
}
let src = unsafe { self.ptr.as_ptr().add(n) };
let dst = new.ptr.as_ptr();
for i in 0..nlen {
unsafe { dst.add(i).write(src.add(i).read()) }
}
unsafe {
new.set_len(nlen);
}
new
}
#[must_use = "If you don't need the split off elements use `Self::shrink` instead"]
pub fn split_off_back(&mut self, n: usize) -> Self
where
A: Clone,
{
assert!(n <= self.len);
let nlen = self.len - n;
let mut new = Self::with_capacity_in(n, self.alloc.clone());
unsafe {
self.set_len(nlen);
}
let src = unsafe { self.ptr.as_ptr().add(nlen) };
let dst = new.ptr.as_ptr();
for i in 0..n {
unsafe { dst.add(i).write(src.add(i).read()) }
}
unsafe {
new.set_len(n);
}
new
}
pub fn shrink(&mut self, new_len: usize) {
assert!(new_len <= self.len);
let old_len = self.len;
unsafe {
self.set_len(new_len);
}
if core::mem::needs_drop::<T>() {
let ptr = self.ptr.as_ptr();
for i in new_len..old_len {
unsafe { core::ptr::drop_in_place(ptr.add(i)) }
}
}
}
}
impl<T, A: Allocator + Default> FromIterator<T> for Vec<T, A> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (size, _) = iter.size_hint();
let mut ret = Self::with_capacity_in(size, Default::default());
for v in iter {
ret.push(v);
}
ret
}
}
impl<T, A: Allocator> Extend<T> for Vec<T, A> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let iter = iter.into_iter();
let (size, _) = iter.size_hint();
self.reserve(size);
for v in iter {
self.push(v);
}
}
}
impl<T, A: Allocator> Deref for Vec<T, A> {
type Target = [T];
fn deref(&self) -> &Self::Target {
let ptr = self.ptr.as_ptr();
unsafe { core::slice::from_raw_parts(ptr, self.len) }
}
}
impl<T, A: Allocator> DerefMut for Vec<T, A> {
fn deref_mut(&mut self) -> &mut Self::Target {
let ptr = self.ptr.as_ptr();
unsafe { core::slice::from_raw_parts_mut(ptr, self.len) }
}
}
impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
fn clone(&self) -> Self {
let nalloc = self.alloc.clone();
let mut nvec = Self::with_capacity_in(self.len, nalloc);
let ptr = nvec.ptr.as_ptr();
for i in 0..self.len {
unsafe {
core::ptr::write(ptr.add(i), self[i].clone());
}
}
unsafe {
nvec.set_len(self.len);
}
nvec
}
}
impl<'a, T, A: Allocator> IntoIterator for &'a Vec<T, A> {
type IntoIter = core::slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec<T, A> {
type IntoIter = core::slice::IterMut<'a, T>;
type Item = &'a mut T;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T: Hash, A: Allocator> Hash for Vec<T, A> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
for i in 0..self.len() {
self[i].hash(state);
}
}
}
impl<U, T: PartialEq<U>, A: Allocator, A1: Allocator> PartialEq<Vec<U, A1>> for Vec<T, A> {
fn eq(&self, other: &Vec<U, A1>) -> bool {
self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.eq(b))
}
}
impl<T: Eq, A: Allocator> Eq for Vec<T, A> {}
impl<T, A: Allocator + Default> Default for Vec<T, A> {
fn default() -> Self {
Self::new_in(Default::default())
}
}
impl<T: Debug, A: Allocator> Debug for Vec<T, A> {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
<[T]>::fmt(self, fmt)
}
}
impl<A: Allocator> Write for Vec<u8, A> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.reserve(buf.len());
unsafe {
core::ptr::copy_nonoverlapping(
buf.as_ptr(),
self.ptr.as_ptr().add(self.len),
buf.len(),
);
}
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl<T: Clone, A: Allocator + Default, S: AsRef<[T]> + ?Sized> From<&S> for Vec<T, A> {
fn from(s: &S) -> Self {
let s = s.as_ref();
if s.is_empty() {
Self::new_in(Default::default())
} else {
let mut v = Self::with_capacity_in(s.len(), Default::default());
v.extend_from_slice(s);
v
}
}
}
impl<T, A: Allocator + Default> From<std::vec::Vec<T>> for Vec<T, A> {
fn from(s: std::vec::Vec<T>) -> Self {
if s.is_empty() {
Self::new_in(Default::default())
} else {
let mut s = ManuallyDrop::new(s);
let mut v = Self::with_capacity_in(s.len(), Default::default());
let len = s.len();
let dst = v.as_mut_ptr();
let src = s.as_ptr();
unsafe {
core::ptr::copy_nonoverlapping(src, dst, len);
}
unsafe {
v.set_len(len);
}
unsafe {
s.set_len(0);
}
drop(ManuallyDrop::into_inner(s));
v
}
}
}
pub struct IntoIter<T, A: Allocator> {
ptr: Unique<T>,
len: usize,
cap: usize,
consumed: usize,
alloc: A,
}
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.consumed == self.len {
None
} else {
let ptr = unsafe { self.ptr.as_ptr().add(self.consumed) };
self.consumed += 1;
Some(unsafe { core::ptr::read(ptr) })
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len - self.consumed, Some(self.len - self.consumed))
}
}
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {}
impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}
impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.consumed == self.len {
None
} else {
self.len -= 1;
let ptr = unsafe { self.ptr.as_ptr().add(self.len) };
Some(unsafe { core::ptr::read(ptr) })
}
}
}
impl<T, A: Allocator> Drop for IntoIter<T, A> {
fn drop(&mut self) {
if core::mem::needs_drop::<T>() {
for i in self.consumed..self.len {
unsafe { core::ptr::drop_in_place(self.ptr.as_ptr().add(i)) }
}
}
let raw_cap = self.cap * size_of::<T>();
if raw_cap != 0 {
let layout =
unsafe { Layout::from_size_align_unchecked(raw_cap, core::mem::align_of::<T>()) };
unsafe { self.alloc.deallocate(self.ptr.as_nonnull().cast(), layout) };
}
}
}
impl<T, A: Allocator> IntoIterator for Vec<T, A> {
type Item = T;
type IntoIter = IntoIter<T, A>;
fn into_iter(self) -> Self::IntoIter {
let (ptr, cap, len, alloc) = self.into_raw_parts_with_alloc();
IntoIter {
ptr: unsafe { Unique::new_unchecked(ptr) },
cap,
len,
alloc,
consumed: 0,
}
}
}
#[macro_export]
macro_rules! vec{
[$($elems:expr),* $(,)?] => {
{
let s = ::core::mem::ManuallyDrop::new([$($elems),*]);
let mut vec = $crate::vec::Vec::with_capacity(s.len());
let ptr = vec.as_mut_ptr();
unsafe{core::ptr::copy_nonoverlapping(s.as_ptr(),ptr,s.len());}
unsafe{vec.set_len(s.len())}
vec
}
};
[$elem:expr ; $repeat:expr] => {
{
let __repeat: ::core::primitive::usize = $repeat;
fn __check<T: ::core::clone::Clone>(_: &T) {}
let val = $elem;
__check(&val);
let mut vec = $crate::vec::Vec::with_capacity(__repeat);
for _ in 0..($repeat){
vec.push(val.clone());
}
vec
}
}
}
#[cfg(test)]
mod test {
use super::Vec;
#[test]
fn test_vec_new() {
let vec = Vec::<u32>::new();
assert_eq!(vec.len(), 0);
}
#[test]
fn test_vec_empty() {
let vec: Vec<u32> = vec![];
assert_eq!(vec.len(), 0);
}
#[test]
fn test_vec_with_data() {
let vec: Vec<u32> = vec![314, 159, 265];
assert_eq!(vec.len(), 3);
assert_eq!(vec[0], 314);
assert_eq!(vec[1], 159);
assert_eq!(vec[2], 265);
}
#[test]
fn test_vec_with_len() {
let vec: Vec<u32> = vec![42; 7];
assert_eq!(vec.len(), 7);
assert_eq!(vec[0], 42);
assert_eq!(vec[1], 42);
assert_eq!(vec[5], 42);
}
#[test]
fn test_vec_push() {
let mut vec = Vec::new();
vec.push(0);
assert_eq!(vec.len(), 1);
}
#[test]
fn test_vec_deref() {
let mut vec = Vec::new();
vec.push(0);
assert!(matches!(*vec, [0]));
}
#[test]
fn test_vec_iter() {
let mut vec = Vec::new();
vec.push(1);
let mut iter = vec.iter();
assert_eq!(iter.next(), Some(&1));
}
#[test]
fn test_vec_subscript() {
let mut vec = Vec::new();
vec.push(1);
assert_eq!(vec[0], 1);
}
#[test]
#[should_panic]
fn test_vec_subscript_oob() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
let _ = vec[2];
}
#[test]
fn test_vec_get() {
let mut vec = Vec::new();
vec.push(1);
assert_eq!(vec.get(0), Some(&1));
}
#[test]
fn test_vec_get_oob() {
let mut vec = Vec::new();
vec.push(1);
assert_eq!(vec.get(1), None);
}
#[test]
fn test_vec_get_unchecked() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
assert_eq!(unsafe { vec.get_unchecked(1) }, &2);
}
#[test]
fn test_vec_slice() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);
assert!(matches!(vec[..2], [1, 2]));
}
#[test]
fn test_vec_slice_inclusive_bound() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);
assert!(matches!(vec[..=2], [1, 2, 3]));
}
#[test]
fn test_vec_slice_full() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);
assert!(matches!(vec[..], [1, 2, 3]));
}
#[test]
fn test_vec_iter_mut() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
let mut iter_mut = vec.iter_mut();
*iter_mut.next().unwrap() += 3;
*iter_mut.next().unwrap() += 3;
assert_eq!(vec[0], 4);
assert_eq!(vec[1], 5);
}
}