use alloc::borrow::Cow;
use super::{CellSliceExt, MelinoeCell};
use crate::token::ReadPermit;
mod sealed {
pub trait Sealed {}
}
pub trait CowPolicy: sealed::Sealed + Copy {
#[must_use]
fn cow<T: Clone>(slice: &[T]) -> Cow<'_, [T]>;
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Borrowed;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Retained;
impl sealed::Sealed for Borrowed {}
impl sealed::Sealed for Retained {}
impl CowPolicy for Borrowed {
#[inline]
fn cow<T: Clone>(slice: &[T]) -> Cow<'_, [T]> {
Cow::Borrowed(slice)
}
}
impl CowPolicy for Retained {
#[inline]
fn cow<T: Clone>(slice: &[T]) -> Cow<'_, [T]> {
Cow::Owned(slice.to_vec())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RetainDecision {
Borrow,
Retain,
}
impl RetainDecision {
#[inline]
fn cow<T: Clone>(self, slice: &[T]) -> Cow<'_, [T]> {
match self {
Self::Borrow => Borrowed::cow(slice),
Self::Retain => Retained::cow(slice),
}
}
}
#[inline]
pub(crate) fn cow_from_segments<'a, T, C>(first: &'a [T], second: &[T], _policy: C) -> Cow<'a, [T]>
where
T: Clone,
C: CowPolicy,
{
if second.is_empty() {
C::cow(first)
} else {
let mut values = alloc::vec::Vec::with_capacity(first.len() + second.len());
values.extend_from_slice(first);
values.extend_from_slice(second);
Cow::Owned(values)
}
}
pub trait CellCowExt<'brand, T> {
fn borrow_cow<'a, P>(&'a self, permit: P) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a;
fn retain_cow<'a, P>(&'a self, permit: P) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a;
fn borrow_cow_with<'a, P, C>(&'a self, permit: P, policy: C) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
C: CowPolicy;
fn borrow_cow_if<'a, P>(&'a self, permit: P, decision: RetainDecision) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a;
}
impl<'brand, T> CellCowExt<'brand, T> for [MelinoeCell<'brand, T>] {
#[inline]
fn borrow_cow<'a, P>(&'a self, permit: P) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
{
Borrowed::cow(self.borrow_slice(permit))
}
#[inline]
fn retain_cow<'a, P>(&'a self, permit: P) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
{
Retained::cow(self.borrow_slice(permit))
}
#[inline]
fn borrow_cow_with<'a, P, C>(&'a self, permit: P, _policy: C) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
C: CowPolicy,
{
let slice = self.borrow_slice(permit);
C::cow(slice)
}
#[inline]
fn borrow_cow_if<'a, P>(&'a self, permit: P, decision: RetainDecision) -> Cow<'a, [T]>
where
T: Clone,
P: ReadPermit<'brand> + 'a,
{
let slice = self.borrow_slice(permit);
decision.cow(slice)
}
}