use alloc::borrow::Cow;
use alloc::vec::Vec;
use core::iter::FromIterator;
use crate::{
CellCowExt, CellSliceExt, CowPolicy, MelinoeCell, MelinoeMut, MelinoeRef, ReadPermit,
RetainDecision, WritePermit,
};
#[derive(Debug, Default)]
pub struct BrandedVec<'brand, T> {
cells: Vec<MelinoeCell<'brand, T>>,
}
impl<'brand, T> BrandedVec<'brand, T> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self { cells: Vec::new() }
}
#[inline]
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self {
cells: Vec::with_capacity(capacity),
}
}
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.cells.len()
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.cells.is_empty()
}
#[inline]
#[must_use]
pub fn capacity(&self) -> usize {
self.cells.capacity()
}
#[inline]
pub fn push(&mut self, value: T) {
self.cells.push(MelinoeCell::new(value));
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
self.cells.pop().map(MelinoeCell::into_inner)
}
#[inline]
pub fn insert(&mut self, index: usize, value: T) {
self.cells.insert(index, MelinoeCell::new(value));
}
#[inline]
pub fn remove(&mut self, index: usize) -> T {
self.cells.remove(index).into_inner()
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
self.cells.swap_remove(index).into_inner()
}
#[inline]
pub fn swap(&mut self, a: usize, b: usize) {
self.cells.swap(a, b);
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.cells.reserve(additional);
}
#[inline]
pub fn clear(&mut self) {
self.cells.clear();
}
#[inline]
pub fn truncate(&mut self, len: usize) {
self.cells.truncate(len);
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.cells.shrink_to_fit();
}
#[inline]
pub fn resize_with<F>(&mut self, new_len: usize, mut f: F)
where
F: FnMut() -> T,
{
self.cells.resize_with(new_len, || MelinoeCell::new(f()));
}
#[inline]
pub fn retain_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
self.cells.retain_mut(|cell| f(cell.get_mut()));
}
#[inline]
#[must_use]
pub fn as_cells(&self) -> &[MelinoeCell<'brand, T>] {
&self.cells
}
#[inline]
#[must_use]
pub fn as_mut_cells(&mut self) -> &mut [MelinoeCell<'brand, T>] {
&mut self.cells
}
#[inline]
pub fn get<'a, P>(&'a self, index: usize, permit: P) -> Option<MelinoeRef<'a, 'brand, T>>
where
P: ReadPermit<'brand> + 'a,
{
self.cells.get(index).map(|cell| cell.borrow(permit))
}
#[inline]
pub fn get_mut<'a, P>(&'a self, index: usize, permit: P) -> Option<MelinoeMut<'a, 'brand, T>>
where
P: WritePermit<'brand> + 'a,
{
self.cells.get(index).map(|cell| cell.borrow_mut(permit))
}
#[inline]
pub fn as_slice<'a, P>(&'a self, permit: P) -> &'a [T]
where
P: ReadPermit<'brand> + 'a,
{
self.cells.borrow_slice(permit)
}
#[inline]
pub fn as_mut_slice<'a, P>(&'a self, permit: P) -> &'a mut [T]
where
P: WritePermit<'brand> + 'a,
{
self.cells.borrow_slice_mut(permit)
}
#[inline]
pub fn borrow_cow<'a, P>(&'a self, permit: P) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
{
self.cells.borrow_cow(permit)
}
#[inline]
pub fn retain_cow<'a, P>(&'a self, permit: P) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
{
self.cells.retain_cow(permit)
}
#[inline]
pub fn cow_with<'a, P, C>(&'a self, permit: P, policy: C) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
C: CowPolicy,
{
self.cells.borrow_cow_with(permit, policy)
}
#[inline]
#[must_use]
pub fn clone_with<'a, P>(&'a self, permit: P) -> Self
where
T: Clone,
P: ReadPermit<'brand> + 'a,
{
Self::from_iter(self.as_slice(permit).iter().cloned())
}
#[inline]
pub fn cow_if<'a, P>(&'a self, permit: P, decision: RetainDecision) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
{
self.cells.borrow_cow_if(permit, decision)
}
#[inline]
#[must_use]
pub fn into_vec(self) -> Vec<T> {
unsafe {
let mut cells = core::mem::ManuallyDrop::new(self.cells);
let ptr = cells.as_mut_ptr() as *mut T;
Vec::from_raw_parts(ptr, cells.len(), cells.capacity())
}
}
#[inline]
pub fn drain<R>(&mut self, range: R) -> BrandedDrain<'_, 'brand, T>
where
R: core::ops::RangeBounds<usize>,
{
BrandedDrain {
inner: self.cells.drain(range),
}
}
#[inline]
#[must_use]
pub fn split_off(&mut self, at: usize) -> Self {
Self {
cells: self.cells.split_off(at),
}
}
#[inline]
pub fn append(&mut self, other: &mut Self) {
self.cells.append(&mut other.cells);
}
#[cfg(feature = "std")]
#[inline]
pub fn partition_for_each_mut_with<F>(&mut self, plan: crate::sync::PartitionPlan, f: F)
where
T: Send,
F: Fn(usize, &mut [T]) + Sync,
{
crate::sync::partition_for_each_with(&mut self.cells, plan, |start, mut shard| {
f(start, shard.as_mut_slice());
});
}
#[cfg(feature = "std")]
#[inline]
pub fn partition_map_mut_with<R, F>(&mut self, plan: crate::sync::PartitionPlan, f: F) -> Vec<R>
where
T: Send,
R: Send,
F: Fn(usize, &mut [T]) -> R + Sync,
{
crate::sync::partition_map_with(&mut self.cells, plan, |start, mut shard| {
f(start, shard.as_mut_slice())
})
}
#[cfg(feature = "std")]
#[inline]
pub fn partition_map_with<'a, P, R, F>(
&'a self,
permit: P,
plan: crate::sync::PartitionPlan,
f: F,
) -> Vec<R>
where
P: ReadPermit<'brand> + 'a,
T: Sync,
R: Send,
F: Fn(usize, &[T]) -> R + Sync,
{
crate::sync::partition_read_map_with(self.as_slice(permit), plan, f)
}
#[cfg(feature = "std")]
#[inline]
pub fn partition_for_each_with<'a, P, F>(
&'a self,
permit: P,
plan: crate::sync::PartitionPlan,
f: F,
) where
P: ReadPermit<'brand> + 'a,
T: Sync,
F: Fn(usize, &[T]) + Sync,
{
crate::sync::partition_read_for_each_with(self.as_slice(permit), plan, f);
}
}
impl<'brand, T> Extend<T> for BrandedVec<'brand, T> {
#[inline]
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
self.cells.extend(iter.into_iter().map(MelinoeCell::new));
}
}
impl<'brand, T> FromIterator<T> for BrandedVec<'brand, T> {
#[inline]
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
let mut values = Self::new();
values.extend(iter);
values
}
}
impl<'brand, T> From<Vec<T>> for BrandedVec<'brand, T> {
#[inline]
fn from(values: Vec<T>) -> Self {
unsafe {
let mut values = core::mem::ManuallyDrop::new(values);
let ptr = values.as_mut_ptr() as *mut MelinoeCell<'brand, T>;
Self {
cells: Vec::from_raw_parts(ptr, values.len(), values.capacity()),
}
}
}
}
impl<'brand, T> IntoIterator for BrandedVec<'brand, T> {
type Item = T;
type IntoIter = alloc::vec::IntoIter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.into_vec().into_iter()
}
}
pub struct BrandedDrain<'a, 'brand, T> {
inner: alloc::vec::Drain<'a, MelinoeCell<'brand, T>>,
}
impl<'a, 'brand, T> Iterator for BrandedDrain<'a, 'brand, T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(MelinoeCell::into_inner)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, 'brand, T> DoubleEndedIterator for BrandedDrain<'a, 'brand, T> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(MelinoeCell::into_inner)
}
}
impl<'a, 'brand, T> ExactSizeIterator for BrandedDrain<'a, 'brand, T> {}