lazy_cogs/
alc.rs

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