use core::alloc::Layout;
use core::array;
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt::{self, Debug, Formatter};
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::mem;
use core::ops::Deref;
use core::ptr::{self, NonNull};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use crate::sync::atomic::{self, AtomicUsize, Ordering::*};
#[macro_export]
macro_rules! eco_vec {
() => { $crate::EcoVec::new() };
($elem:expr; $n:expr) => { $crate::EcoVec::from_elem($elem, $n) };
($($value:expr),+ $(,)?) => { $crate::EcoVec::from([$($value),+]) };
}
#[repr(C)]
pub struct EcoVec<T> {
ptr: NonNull<T>,
len: usize,
phantom: PhantomData<T>,
}
#[derive(Debug)]
struct Header {
refs: AtomicUsize,
capacity: usize,
}
impl<T> EcoVec<T> {
#[inline]
pub const fn new() -> Self {
Self {
ptr: Self::dangling(),
len: 0,
phantom: PhantomData,
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
let mut vec = Self::new();
if capacity > 0 {
unsafe {
vec.grow(capacity);
}
}
vec
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub const fn len(&self) -> usize {
self.len
}
#[inline]
pub fn capacity(&self) -> usize {
self.header().map_or(0, |header| header.capacity)
}
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.data(), self.len) }
}
pub fn clear(&mut self) {
if self.is_empty() {
return;
}
if !self.is_unique() {
*self = Self::new();
return;
}
unsafe {
let prev = self.len;
self.len = 0;
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.data_mut(), prev));
}
}
}
impl<T: Clone> EcoVec<T> {
pub fn from_elem(value: T, n: usize) -> Self {
let mut vec = Self::with_capacity(n);
for _ in 0..n {
unsafe { vec.push_unchecked(value.clone()) }
}
vec
}
pub fn make_mut(&mut self) -> &mut [T] {
self.make_unique();
unsafe { core::slice::from_raw_parts_mut(self.data_mut(), self.len) }
}
#[inline]
pub fn push(&mut self, value: T) {
self.reserve((self.len == self.capacity()) as usize);
unsafe {
self.push_unchecked(value);
}
}
#[inline]
unsafe fn push_unchecked(&mut self, value: T) {
debug_assert!(self.is_unique());
debug_assert!(self.len < self.capacity());
unsafe {
ptr::write(self.data_mut().add(self.len), value);
self.len += 1;
}
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
self.make_unique();
unsafe {
self.len -= 1;
Some(ptr::read(self.data().add(self.len)))
}
}
pub fn insert(&mut self, index: usize, value: T) {
if index > self.len {
out_of_bounds(index, self.len);
}
self.reserve((self.len == self.capacity()) as usize);
unsafe {
let at = self.data_mut().add(index);
ptr::copy(at, at.add(1), self.len - index);
ptr::write(at, value);
self.len += 1;
}
}
pub fn remove(&mut self, index: usize) -> T {
if index >= self.len {
out_of_bounds(index, self.len);
}
self.make_unique();
unsafe {
let at = self.data_mut().add(index);
let value = ptr::read(at);
ptr::copy(at.add(1), at, self.len - index - 1);
self.len -= 1;
value
}
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
let len = self.len;
let values = self.make_mut();
let mut del = 0;
for i in 0..len {
if !f(&mut values[i]) {
del += 1;
} else if del > 0 {
values.swap(i - del, i);
}
}
if del > 0 {
self.truncate(len - del);
}
}
pub fn truncate(&mut self, target: usize) {
if target >= self.len {
return;
}
if !self.is_unique() {
*self = Self::from(unsafe { self.get_unchecked(..target) });
return;
}
let rest = self.len - target;
unsafe {
self.len = target;
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
self.data_mut().add(target),
rest,
));
}
}
pub fn reserve(&mut self, additional: usize) {
let capacity = self.capacity();
let mut target = capacity;
if additional > capacity - self.len {
target = self
.len
.checked_add(additional)
.unwrap_or_else(|| capacity_overflow())
.max(2 * capacity)
.max(Self::min_cap());
}
if !self.is_unique() {
let mut vec = Self::with_capacity(target);
vec.extend(self.iter().cloned());
*self = vec;
} else if target > capacity {
unsafe {
self.grow(target);
}
}
}
pub fn extend_from_slice(&mut self, slice: &[T]) {
if slice.is_empty() {
return;
}
self.reserve(slice.len());
for value in slice {
unsafe {
self.push_unchecked(value.clone());
}
}
}
pub unsafe fn extend_from_trusted<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
{
let iter = iter.into_iter();
let count = iter.len();
if count == 0 {
return;
}
self.reserve(count);
for value in iter {
unsafe {
self.push_unchecked(value);
}
}
}
}
impl<T> EcoVec<T> {
unsafe fn grow(&mut self, mut target: usize) {
debug_assert!(self.is_unique());
debug_assert!(target > self.capacity());
if target > isize::MAX as usize {
capacity_overflow();
}
if mem::size_of::<T>() == 0 {
target = isize::MAX as usize;
}
let layout = Self::layout(target);
let allocation = if !self.is_allocated() {
alloc::alloc::alloc(layout)
} else {
alloc::alloc::realloc(
self.allocation_mut(),
Self::layout(self.capacity()),
Self::size(target),
)
};
if allocation.is_null() {
alloc::alloc::handle_alloc_error(layout);
}
self.ptr = NonNull::new_unchecked(allocation.add(Self::offset()).cast());
debug_assert_ne!(self.ptr, Self::dangling());
ptr::write(
allocation.cast::<Header>(),
Header { refs: AtomicUsize::new(1), capacity: target },
);
}
#[inline]
fn is_allocated(&self) -> bool {
!ptr::eq(self.ptr.as_ptr(), Self::dangling().as_ptr())
}
#[inline]
unsafe fn allocation(&self) -> *const u8 {
debug_assert!(self.is_allocated());
self.ptr.as_ptr().cast::<u8>().sub(Self::offset())
}
#[inline]
unsafe fn allocation_mut(&mut self) -> *mut u8 {
debug_assert!(self.is_allocated());
self.ptr.as_ptr().cast::<u8>().sub(Self::offset())
}
#[inline]
fn header(&self) -> Option<&Header> {
self.is_allocated()
.then(|| unsafe { &*self.allocation().cast::<Header>() })
}
#[inline]
fn data(&self) -> *const T {
self.ptr.as_ptr()
}
#[inline]
unsafe fn data_mut(&mut self) -> *mut T {
self.ptr.as_ptr()
}
#[inline]
fn layout(capacity: usize) -> Layout {
unsafe { Layout::from_size_align_unchecked(Self::size(capacity), Self::align()) }
}
#[inline]
fn size(capacity: usize) -> usize {
mem::size_of::<T>()
.checked_mul(capacity)
.and_then(|size| Self::offset().checked_add(size))
.filter(|&size| {
size < isize::MAX as usize - Self::align()
})
.unwrap_or_else(|| capacity_overflow())
}
#[inline]
const fn align() -> usize {
max(mem::align_of::<Header>(), mem::align_of::<T>())
}
#[inline]
const fn offset() -> usize {
max(mem::size_of::<Header>(), Self::align())
}
#[inline]
const fn dangling() -> NonNull<T> {
unsafe {
#[allow(clippy::useless_transmute)]
let ptr = mem::transmute::<usize, *mut T>(Self::offset());
NonNull::new_unchecked(ptr)
}
}
#[inline]
const fn min_cap() -> usize {
if mem::size_of::<T>() == 1 {
8
} else if mem::size_of::<T>() <= 32 {
4
} else {
1
}
}
}
impl<T: Clone> EcoVec<T> {
fn make_unique(&mut self) {
if !self.is_unique() {
*self = Self::from(self.as_slice());
}
}
}
impl EcoVec<u8> {
#[inline]
pub(crate) fn extend_from_byte_slice(&mut self, bytes: &[u8]) {
if bytes.is_empty() {
return;
}
self.reserve(bytes.len());
unsafe {
ptr::copy_nonoverlapping(
bytes.as_ptr(),
self.data_mut().add(self.len),
bytes.len(),
);
}
self.len += bytes.len();
}
}
unsafe impl<T: Sync + Send> Sync for EcoVec<T> {}
unsafe impl<T: Sync + Send> Send for EcoVec<T> {}
impl<T> EcoVec<T> {
#[inline]
pub fn is_unique(&mut self) -> bool {
self.header().map_or(true, |header| header.refs.load(Acquire) == 1)
}
}
impl<T: Clone> Clone for EcoVec<T> {
#[inline]
fn clone(&self) -> Self {
if let Some(header) = self.header() {
let prev = header.refs.fetch_add(1, Relaxed);
if prev > isize::MAX as usize {
ref_count_overflow(self.ptr, self.len);
}
}
Self { ptr: self.ptr, len: self.len, phantom: PhantomData }
}
}
impl<T> Drop for EcoVec<T> {
fn drop(&mut self) {
if self
.header()
.map_or(true, |header| header.refs.fetch_sub(1, Release) != 1)
{
return;
}
atomic::fence(Acquire);
struct Dealloc(*mut u8, Layout);
impl Drop for Dealloc {
fn drop(&mut self) {
unsafe {
alloc::alloc::dealloc(self.0, self.1);
}
}
}
let _dealloc =
unsafe { Dealloc(self.allocation_mut(), Self::layout(self.capacity())) };
unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.data_mut(), self.len));
}
}
}
impl<T> Deref for EcoVec<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T> Borrow<[T]> for EcoVec<T> {
#[inline]
fn borrow(&self) -> &[T] {
self.as_slice()
}
}
impl<T> AsRef<[T]> for EcoVec<T> {
#[inline]
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> Default for EcoVec<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T: Debug> Debug for EcoVec<T> {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.as_slice().fmt(f)
}
}
impl<T: Hash> Hash for EcoVec<T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl<T: Eq> Eq for EcoVec<T> {}
impl<T: PartialEq> PartialEq for EcoVec<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: PartialEq> PartialEq<[T]> for EcoVec<T> {
#[inline]
fn eq(&self, other: &[T]) -> bool {
self.as_slice() == other
}
}
impl<T: PartialEq> PartialEq<&[T]> for EcoVec<T> {
#[inline]
fn eq(&self, other: &&[T]) -> bool {
self.as_slice() == *other
}
}
impl<T: PartialEq, const N: usize> PartialEq<[T; N]> for EcoVec<T> {
#[inline]
fn eq(&self, other: &[T; N]) -> bool {
self.as_slice() == other
}
}
impl<T: PartialEq, const N: usize> PartialEq<&[T; N]> for EcoVec<T> {
#[inline]
fn eq(&self, other: &&[T; N]) -> bool {
self.as_slice() == *other
}
}
impl<T: PartialEq> PartialEq<Vec<T>> for EcoVec<T> {
#[inline]
fn eq(&self, other: &Vec<T>) -> bool {
self.as_slice() == other
}
}
impl<T: PartialEq> PartialEq<EcoVec<T>> for [T] {
#[inline]
fn eq(&self, other: &EcoVec<T>) -> bool {
self == other.as_slice()
}
}
impl<T: PartialEq, const N: usize> PartialEq<EcoVec<T>> for [T; N] {
#[inline]
fn eq(&self, other: &EcoVec<T>) -> bool {
self == other.as_slice()
}
}
impl<T: PartialEq> PartialEq<EcoVec<T>> for Vec<T> {
#[inline]
fn eq(&self, other: &EcoVec<T>) -> bool {
self == other.as_slice()
}
}
impl<T: Ord> Ord for EcoVec<T> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<T: PartialOrd> PartialOrd for EcoVec<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl<T: Clone> From<&[T]> for EcoVec<T> {
fn from(slice: &[T]) -> Self {
let mut vec = Self::new();
vec.extend_from_slice(slice);
vec
}
}
impl<T: Clone, const N: usize> From<[T; N]> for EcoVec<T> {
fn from(array: [T; N]) -> Self {
let mut vec = Self::new();
unsafe {
vec.extend_from_trusted(array);
}
vec
}
}
impl<T: Clone> From<Vec<T>> for EcoVec<T> {
fn from(mut other: Vec<T>) -> Self {
let len = other.len();
let mut vec = Self::with_capacity(len);
unsafe {
other.set_len(0);
ptr::copy_nonoverlapping(other.as_ptr(), vec.data_mut(), len);
vec.len = len;
}
vec
}
}
impl<T: Clone, const N: usize> TryFrom<EcoVec<T>> for [T; N] {
type Error = EcoVec<T>;
fn try_from(mut vec: EcoVec<T>) -> Result<Self, Self::Error> {
if vec.len() != N {
return Err(vec);
}
Ok(if vec.is_unique() {
vec.len = 0;
unsafe { ptr::read(vec.data() as *const [T; N]) }
} else {
unsafe { array::from_fn(|i| vec.get_unchecked(i).clone()) }
})
}
}
impl<T: Clone> FromIterator<T> for EcoVec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let hint = iter.size_hint().0;
let mut vec = Self::with_capacity(hint);
vec.extend(iter);
vec
}
}
impl<T: Clone> Extend<T> for EcoVec<T> {
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
let iter = iter.into_iter();
let hint = iter.size_hint().0;
if hint > 0 {
self.reserve(hint);
}
for value in iter {
self.push(value);
}
}
}
impl<'a, T> IntoIterator for &'a EcoVec<T> {
type IntoIter = core::slice::Iter<'a, T>;
type Item = &'a T;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<T: Clone> IntoIterator for EcoVec<T> {
type IntoIter = IntoIter<T>;
type Item = T;
#[inline]
fn into_iter(mut self) -> Self::IntoIter {
IntoIter {
unique: self.is_unique(),
front: 0,
back: self.len,
vec: self,
}
}
}
pub struct IntoIter<T> {
vec: EcoVec<T>,
unique: bool,
front: usize,
back: usize,
}
impl<T> IntoIter<T> {
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe {
core::slice::from_raw_parts(
self.vec.data().add(self.front),
self.back - self.front,
)
}
}
}
impl<T: Clone> Iterator for IntoIter<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
(self.front < self.back).then(|| {
let prev = self.front;
self.front += 1;
if self.unique {
unsafe { ptr::read(self.vec.data().add(prev)) }
} else {
unsafe { self.vec.get_unchecked(prev).clone() }
}
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.back - self.front;
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.len()
}
}
impl<T: Clone> DoubleEndedIterator for IntoIter<T> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
(self.back > self.front).then(|| {
self.back -= 1;
if self.unique {
unsafe { ptr::read(self.vec.data().add(self.back)) }
} else {
unsafe { self.vec.get_unchecked(self.back).clone() }
}
})
}
}
impl<T: Clone> ExactSizeIterator for IntoIter<T> {}
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
if !self.unique || !self.vec.is_allocated() {
return;
}
unsafe {
self.vec.len = 0;
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
self.vec.data_mut().add(self.front),
self.back - self.front,
));
}
}
}
impl<T: Debug> Debug for IntoIter<T> {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
}
}
#[cold]
fn capacity_overflow() -> ! {
panic!("capacity overflow");
}
#[cold]
fn ref_count_overflow<T>(ptr: NonNull<T>, len: usize) -> ! {
drop(EcoVec { ptr, len, phantom: PhantomData });
panic!("reference count overflow");
}
#[cold]
fn out_of_bounds(index: usize, len: usize) -> ! {
panic!("index is out bounds (index: {index}, len: {len})");
}
#[inline]
const fn max(x: usize, y: usize) -> usize {
if x > y {
x
} else {
y
}
}
#[cfg(feature = "std")]
impl std::io::Write for EcoVec<u8> {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.extend_from_byte_slice(buf);
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
#[cfg(feature = "serde")]
mod serde {
use crate::EcoVec;
use core::{fmt, marker::PhantomData};
use serde::de::{Deserializer, Visitor};
impl<T: serde::Serialize> serde::Serialize for EcoVec<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.as_slice().serialize(serializer)
}
}
struct EcoVecVisitor<T>(PhantomData<T>);
impl<'a, T: serde::Deserialize<'a> + Clone> Visitor<'a> for EcoVecVisitor<T> {
type Value = EcoVec<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'a>,
{
let len = seq.size_hint().unwrap_or(0);
let mut values = EcoVec::with_capacity(len);
while let Some(value) = seq.next_element()? {
values.push(value)
}
Ok(values)
}
}
impl<'de, T: serde::Deserialize<'de> + Clone> serde::Deserialize<'de> for EcoVec<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(EcoVecVisitor(PhantomData))
}
}
}