use std::fmt;
use std::ops::{Bound, Index, IndexMut, RangeBounds};
use std::sync::{Arc, Mutex};
use typed_arena::Arena;
use super::CowVecIter;
struct CowArena<T> {
arena: Mutex<Arena<T>>,
}
impl<T> CowArena<T> {
fn new() -> Self {
Self {
arena: Mutex::new(Arena::new()),
}
}
fn with_capacity(capacity: usize) -> Self {
Self {
arena: Mutex::new(Arena::with_capacity(capacity)),
}
}
fn alloc(&self, value: T) -> *const T {
let arena = self.arena.lock().unwrap();
let reference = arena.alloc(value);
reference as *const T
}
fn len(&self) -> usize {
self.arena.lock().unwrap().len()
}
}
pub struct CowVec<T> {
arena: Arc<CowArena<T>>,
items: Arc<Vec<*const T>>,
}
unsafe impl<T: Send + Sync> Send for CowVec<T> {}
unsafe impl<T: Send + Sync> Sync for CowVec<T> {}
impl<T> CowVec<T> {
#[inline]
fn items_mut(&mut self) -> &mut Vec<*const T> {
Arc::make_mut(&mut self.items)
}
pub fn new() -> Self {
Self {
arena: Arc::new(CowArena::new()),
items: Arc::new(Vec::new()),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
arena: Arc::new(CowArena::with_capacity(capacity)),
items: Arc::new(Vec::with_capacity(capacity)),
}
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn is_structure_shared(&self) -> bool {
Arc::strong_count(&self.items) > 1
}
pub fn is_storage_shared(&self) -> bool {
Arc::strong_count(&self.arena) > 1
}
pub fn as_slice(&self) -> &[&T] {
unsafe { std::mem::transmute(self.items.as_slice()) }
}
pub fn get(&self, index: usize) -> Option<&T> {
self.items.get(index).map(|ptr| {
unsafe { &**ptr }
})
}
pub fn push(&mut self, value: T) {
let ptr = self.arena.alloc(value);
self.items_mut().push(ptr);
}
pub fn iter(&self) -> CowVecIter<'_, T> {
CowVecIter {
vec: self,
position: 0,
}
}
pub fn first(&self) -> Option<&T> {
self.get(0)
}
pub fn last(&self) -> Option<&T> {
if self.is_empty() {
None
} else {
self.get(self.len() - 1)
}
}
pub fn pop(&mut self) -> Option<&T> {
self.items_mut().pop().map(|ptr| {
unsafe { &*ptr }
})
}
pub fn remove(&mut self, index: usize) -> &T {
let ptr = self.items_mut().remove(index);
unsafe { &*ptr }
}
pub fn swap(&mut self, a: usize, b: usize) {
self.items_mut().swap(a, b);
}
pub fn reverse(&mut self) {
self.items_mut().reverse();
}
pub fn truncate(&mut self, len: usize) {
self.items_mut().truncate(len);
}
pub fn clear(&mut self) {
self.items_mut().clear();
}
pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for item in iter {
self.push(item);
}
}
pub fn position<P>(&self, predicate: P) -> Option<usize>
where
P: FnMut(&T) -> bool,
{
self.iter().position(predicate)
}
pub fn insert(&mut self, index: usize, value: T) {
let ptr = self.arena.alloc(value);
self.items_mut().insert(index, ptr);
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
self.items_mut().retain(|ptr| {
let value = unsafe { &**ptr };
f(value)
});
}
pub fn split_off(&mut self, at: usize) -> Self {
let tail_items = self.items_mut().split_off(at);
Self {
arena: Arc::clone(&self.arena),
items: Arc::new(tail_items),
}
}
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Vec<&T>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = T>,
{
let start = match range.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&n) => n + 1,
Bound::Excluded(&n) => n,
Bound::Unbounded => self.len(),
};
let new_ptrs: Vec<*const T> = replace_with
.into_iter()
.map(|item| self.arena.alloc(item))
.collect();
let removed_ptrs: Vec<*const T> = self.items_mut().splice(start..end, new_ptrs).collect();
removed_ptrs
.into_iter()
.map(|ptr| {
unsafe { &*ptr }
})
.collect()
}
}
impl<T: PartialEq> CowVec<T> {
pub fn contains(&self, value: &T) -> bool {
self.iter().any(|item| item == value)
}
}
impl<T: Clone> CowVec<T> {
pub fn to_vec(&self) -> Vec<T> {
self.iter().cloned().collect()
}
pub fn clone_with_max_capacity(&self, max_capacity: usize) -> Self {
if self.arena.len() <= max_capacity {
return self.clone();
}
let new_arena = Arc::new(CowArena::with_capacity(self.len()));
let new_items: Vec<*const T> = self
.iter()
.map(|item| new_arena.alloc(item.clone()))
.collect();
Self {
arena: new_arena,
items: Arc::new(new_items),
}
}
}
impl<T> CowVec<T> {
pub fn set(&mut self, index: usize, value: T) {
if index >= self.items.len() {
panic!(
"index out of bounds: the len is {} but the index is {}",
self.len(),
index
);
}
let ptr = self.arena.alloc(value);
self.items_mut()[index] = ptr;
}
}
impl<T> Default for CowVec<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Clone for CowVec<T> {
fn clone(&self) -> Self {
Self {
arena: Arc::clone(&self.arena),
items: Arc::clone(&self.items),
}
}
}
impl<T: fmt::Debug> fmt::Debug for CowVec<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T> From<Vec<T>> for CowVec<T> {
fn from(vec: Vec<T>) -> Self {
let arena = Arc::new(CowArena::with_capacity(vec.len()));
let items: Vec<*const T> = vec.into_iter().map(|item| arena.alloc(item)).collect();
Self {
arena,
items: Arc::new(items),
}
}
}
impl<T> Index<usize> for CowVec<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
self.get(index).expect("index out of bounds")
}
}
impl<T: Clone> IndexMut<usize> for CowVec<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index >= self.items.len() {
panic!(
"index out of bounds: the len is {} but the index is {}",
self.len(),
index
);
}
let current = unsafe { &*self.items[index] }.clone();
let ptr = self.arena.alloc(current);
self.items_mut()[index] = ptr;
unsafe { &mut *(ptr as *mut T) }
}
}