use super::ref_counters::*;
pub use crate::prelude::*;
use core::marker::PhantomData;
#[repr(transparent)]
pub struct RcArray<A, R, E, L = ()>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
data: ManuallyDrop<A>,
phantom: PhantomData<(R, E, L)>,
}
impl<A, R, E, L> RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
fn from_ref(ptr: A) -> Self {
Self {
data: ManuallyDrop::new(ptr),
phantom: PhantomData,
}
}
fn to_ref(self) -> A {
let ret = unsafe { mem::transmute_copy(&self.data) };
mem::forget(self);
ret
}
pub fn ref_count(&self) -> usize {
self.data.get_label().counter()
}
pub fn to_owned(self) -> Result<A, Self> {
if self.ref_count() > 1 {
Err(self)
} else {
Ok(self.to_ref())
}
}
}
impl<A, R, E, L> RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef + Clone,
R: RefCounter<L>,
{
pub fn make_owned(&self) -> A {
(*self.data).clone()
}
}
impl<A, R, E, L> BaseArrayRef for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
}
impl<A, R, E, L> Clone for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
fn clone(&self) -> Self {
(*self.data).get_label().increment();
unsafe { mem::transmute_copy(self) }
}
}
impl<A, R, E, L> ArrayRef for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
}
impl<A, R, E, L> Index<usize> for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef + Index<usize, Output = E>,
R: RefCounter<L>,
{
type Output = E;
fn index(&self, idx: usize) -> &E {
&self.data[idx]
}
}
impl<A, R, E, L> Drop for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
fn drop(&mut self) {
let ref_count = self.data.get_label().decrement();
if ref_count == 0 {
unsafe {
ptr::drop_in_place(&mut *self.data);
}
}
}
}
impl<A, R, E, L> Container for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
fn len(&self) -> usize {
self.data.len()
}
}
impl<A, R, E, L> CopyMap<usize, E> for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
fn get(&self, key: usize) -> Option<&E> {
self.data.get(key)
}
fn get_mut(&mut self, key: usize) -> Option<&mut E> {
if self.data.get_label().counter() == 1 {
self.data.get_mut(key)
} else {
None
}
}
fn insert(&mut self, key: usize, value: E) -> Option<E> {
if self.data.get_label().counter() == 1 {
self.data.insert(key, value)
} else {
None
}
}
}
impl<A, R, E, L> LabelledArray<E, L> for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
{
fn with_label<F>(label: L, len: usize, mut func: F) -> Self
where
F: FnMut(&mut L, usize) -> E,
{
let new_ptr = A::with_label(R::new(label), len, |rc_struct, idx| {
func(&mut rc_struct.get_data_mut(), idx)
});
Self::from_ref(new_ptr)
}
unsafe fn with_label_unsafe(label: L, len: usize) -> Self {
Self::from_ref(A::with_label_unsafe(R::new(label), len))
}
fn get_label(&self) -> &L {
self.data.get_label().get_data()
}
unsafe fn get_label_unsafe(&self) -> &mut L {
self.data.get_label_unsafe().get_data_mut()
}
unsafe fn get_unsafe(&self, idx: usize) -> &mut E {
self.data.get_unsafe(idx)
}
}
impl<A, R, E, L> LabelledArrayRefMut<E, L> for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef + LabelledArrayMut<E, R>,
R: RefCounter<L>,
{
fn get_label_mut(&mut self) -> Option<&mut L> {
if self.data.get_label().counter() == 1 {
Some(self.data.get_label_mut().get_data_mut())
} else {
None
}
}
}
impl<A, R, E> MakeArray<E> for RcArray<A, R, E, ()>
where
A: LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<()>,
{
fn new<F>(len: usize, mut func: F) -> Self
where
F: FnMut(usize) -> E,
{
Self::with_label((), len, |_, idx| func(idx))
}
}
impl<A, R, E, L> DefaultLabelledArray<E, L> for RcArray<A, R, E, L>
where
A: DefaultLabelledArray<E, R> + LabelledArray<E, R> + BaseArrayRef,
R: RefCounter<L>,
E: Default,
{
fn with_len(label: L, len: usize) -> Self {
Self::from_ref(A::with_len(R::new(label), len))
}
}
impl<A, R, E, L> SliceArrayRef<E> for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef + SliceArray<E>,
R: RefCounter<L>,
{
fn as_slice(&self) -> &[E] {
self.data.as_slice()
}
fn as_slice_mut(&mut self) -> Option<&mut [E]> {
if self.ref_count() > 1 {
None
} else {
Some(self.data.as_slice_mut())
}
}
}
impl<'b, A, R, E, L> IntoIterator for &'b RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef + SliceArray<E>,
R: RefCounter<L>,
{
type Item = &'b E;
type IntoIter = core::slice::Iter<'b, E>;
fn into_iter(self) -> Self::IntoIter {
self.as_slice().into_iter()
}
}
impl<A, R, E, L> fmt::Debug for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef + SliceArray<E>,
R: RefCounter<L>,
E: fmt::Debug,
L: fmt::Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("RcArray")
.field("label", &self.get_label())
.field("ref_count", &self.ref_count())
.field("len", &self.len())
.field("elements", &self.as_slice())
.finish()
}
}
unsafe impl<A, R, E, L> Send for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef + Send + Sync,
R: RefCounter<L> + Send + Sync,
E: Send + Sync,
L: Send + Sync,
{
}
unsafe impl<A, R, E, L> Sync for RcArray<A, R, E, L>
where
A: LabelledArray<E, R> + BaseArrayRef + Sync,
R: RefCounter<L> + Send + Sync,
E: Send + Sync,
L: Send + Sync,
{
}