use std::{borrow::{Borrow, BorrowMut}, ops::{Deref, DerefMut}, sync::Arc};
use crate::lazy::LazyClone;
#[derive(Debug)]
pub struct Alc<T: Clone> (Arc<T>);
impl<T: Clone> Alc<T> {
#[inline(always)]
pub fn new(value: T) -> Self {
Self(Arc::new(value))
}
#[inline(always)]
pub fn read(&self) -> &T {
&self.0
}
#[inline(always)]
pub fn read_mut(&mut self) -> &mut T {
if !self.is_mutable() {
*self = self.eager();
}
assert!(self.is_mutable());
Arc::get_mut(&mut self.0).unwrap()
}
#[inline(always)]
pub fn write(&mut self, value: T) {
self.0 = Arc::new(value);
}
#[inline(always)]
pub fn take(&self) -> T {
self.0.as_ref().clone()
}
#[inline(always)]
pub fn ptr_eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
pub unsafe fn destroy(self) -> T {
if !self.is_mutable() {
panic!("Destroyed a lazy clone that was being shared, this is invalid.")
}
Arc::into_inner(self.0)
.expect("Destroyed a lazy clone that was being shared, this is invalid.")
}
pub fn unwrap(self) -> T {
if self.is_mutable() {
unsafe { self.destroy() }
} else {
self.take()
}
}
}
impl<T: Clone> LazyClone for Alc<T> {
#[inline(always)]
fn lazy(&self) -> Self {
Self(Arc::clone(&self.0))
}
#[inline(always)]
fn eager(&self) -> Self {
Self(Arc::new(self.take()))
}
#[inline(always)]
fn is_mutable(&self) -> bool {
Arc::strong_count(&self.0) == 1
}
}
impl<T: Clone> Clone for Alc<T> {
#[inline(always)]
fn clone(&self) -> Self {
LazyClone::lazy(&self)
}
}
impl<T: Clone> From<T> for Alc<T> {
#[inline(always)]
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T: Clone> Deref for Alc<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.0.as_ref()
}
}
impl<T: Clone> DerefMut for Alc<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
self.read_mut()
}
}
impl<T: Clone> Borrow<T> for Alc<T> {
#[inline(always)]
fn borrow(&self) -> &T {
self.0.borrow()
}
}
impl<T: Clone> BorrowMut<T> for Alc<T> {
#[inline(always)]
fn borrow_mut(&mut self) -> &mut T {
self.read_mut()
}
}