lazy_cogs/
lc.rs

1use std::{borrow::{Borrow, BorrowMut}, ops::{Deref, DerefMut}, rc::Rc};
2
3use crate::lazy::LazyClone;
4
5#[derive(Debug)]
6/// Lc is a LazyClone wrapper, to provide lazy cloning for any data that doesn't implement `LazyClone` trait
7/// 
8/// If you're able to implement LazyClone for the data that you need, do it, if not, use this wrapper
9pub struct Lc<T> (Rc<T>);
10
11impl<T: Clone> Lc<T> {
12    #[inline(always)]
13    /// Creates a new Lc from a value
14    pub fn new(value: T) -> Self {
15        Self(Rc::new(value))
16    }
17
18    #[inline(always)]
19    /// Returns a reference to the lazy cloned value
20    pub fn read(&self) -> &T {
21        &self.0
22    }
23
24    #[inline(always)]
25    /// Ensures that the lazily cloned value is mutable and returns a mutable reference to it
26    pub fn read_mut(&mut self) -> &mut T {
27        if !self.is_mutable() {
28            *self = self.eager();
29        }
30
31        assert!(self.is_mutable());
32
33        Rc::get_mut(&mut self.0).unwrap()
34    }
35
36    #[inline(always)]
37    /// Replaces the cloned value by another
38    /// 
39    /// Does not affect any value lazily cloned from this value
40    pub fn write(&mut self, value: T) {
41        self.0 = Rc::new(value);
42    }
43
44    #[inline(always)]
45    /// Does an actual clone of the contained value
46    /// 
47    /// This clone may be expensive
48    pub fn take(&self) -> T {
49        self.0.as_ref().clone()
50    }
51
52    #[inline(always)]
53    /// Checks if two Lc are pointing to the same data
54    pub fn ptr_eq(&self, other: &Self) -> bool {
55        Rc::ptr_eq(&self.0, &other.0)
56    }
57
58    /// Unwraps the lazy clone and returns the inner data in O(1). 
59    /// But it only works if the Lc hasn't been lazily cloned, otherwise it panics
60    /// 
61    /// # Panics
62    /// 
63    /// If the struct is lazily clonning other structures or if some one is lazily cloning the structure
64    pub unsafe fn destroy(self) -> T {
65        if !self.is_mutable() {
66            panic!("Destroyed a lazy clone that was being shared, this is invalid.")
67        }
68        Rc::into_inner(self.0).expect("Destroyed a lazy clone that was being shared, this is invalid.")
69    }
70
71    /// Unwraps the lazy clone and returns the inner data in O(1) if the Lc is mutable, otherwise performes an clone.
72    pub fn unwrap(self) -> T {
73        if self.is_mutable() { 
74            unsafe { self.destroy() } 
75        } else  {
76            self.take()
77        }
78    }
79}
80
81impl<T: Clone> Deref for Lc<T> {
82    type Target = T;
83
84    #[inline(always)]
85    fn deref(&self) -> &Self::Target {
86        self.read()
87    }
88}
89
90impl<T: Clone> DerefMut for Lc<T> {
91    #[inline(always)]
92    fn deref_mut(&mut self) -> &mut Self::Target {
93        self.read_mut()
94    }
95}
96
97impl<T: Clone> LazyClone for Lc<T> {
98    #[inline(always)]
99    fn lazy(&self) -> Self {
100        Self(Rc::clone(&self.0))
101    }
102
103    #[inline(always)]
104    fn eager(&self) -> Self {
105        Self(Rc::new(self.take()))
106    }
107
108    #[inline(always)]
109    fn is_mutable(&self) -> bool {
110        Rc::strong_count(&self.0) == 1
111    }    
112}
113
114impl<T: Clone> Clone for Lc<T> {
115    #[inline(always)]
116    fn clone(&self) -> Self {
117        LazyClone::lazy(&self)
118    }
119}
120
121impl<T: Clone> From<T> for Lc<T> {
122    #[inline(always)]
123    fn from(value: T) -> Self {
124        Self::new(value)
125    }
126}
127
128impl<T: Clone> Borrow<T> for Lc<T> {
129    #[inline(always)]
130    fn borrow(&self) -> &T {
131        self.0.borrow()
132    }
133}
134
135impl<T: Clone> BorrowMut<T> for Lc<T> {
136    #[inline(always)]
137    fn borrow_mut(&mut self) -> &mut T {
138        self.read_mut()
139    }
140}