use std::{borrow::{Borrow, BorrowMut}, ops::{Deref, DerefMut}, rc::Rc};
use crate::lazy::LazyClone;
#[derive(Debug)]
pub struct Lc<T> (Rc<T>);
impl<T: Clone> Lc<T> {
#[inline(always)]
pub fn new(value: T) -> Self {
Self(Rc::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());
Rc::get_mut(&mut self.0).unwrap()
}
#[inline(always)]
pub fn write(&mut self, value: T) {
self.0 = Rc::new(value);
}
#[inline(always)]
pub fn take(&self) -> T {
self.0.as_ref().clone()
}
#[inline(always)]
pub fn ptr_eq(&self, other: &Self) -> bool {
Rc::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.")
}
Rc::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> Deref for Lc<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.read()
}
}
impl<T: Clone> DerefMut for Lc<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
self.read_mut()
}
}
impl<T: Clone> LazyClone for Lc<T> {
#[inline(always)]
fn lazy(&self) -> Self {
Self(Rc::clone(&self.0))
}
#[inline(always)]
fn eager(&self) -> Self {
Self(Rc::new(self.take()))
}
#[inline(always)]
fn is_mutable(&self) -> bool {
Rc::strong_count(&self.0) == 1
}
}
impl<T: Clone> Clone for Lc<T> {
#[inline(always)]
fn clone(&self) -> Self {
LazyClone::lazy(&self)
}
}
impl<T: Clone> From<T> for Lc<T> {
#[inline(always)]
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T: Clone> Borrow<T> for Lc<T> {
#[inline(always)]
fn borrow(&self) -> &T {
self.0.borrow()
}
}
impl<T: Clone> BorrowMut<T> for Lc<T> {
#[inline(always)]
fn borrow_mut(&mut self) -> &mut T {
self.read_mut()
}
}