cow_arc/
lib.rs

1//! CowArc can be useful for decreasing memory allocations by sharing immutable memory.
2//! It saves some RAM by sharing immutable values between CowArc clones.
3//! Memory allocates only in case of changing value.
4//! CowArc can be usefull for creating builders.
5
6use std::{
7    sync::{
8        Arc
9    },
10    ops::{
11        Deref
12    }
13};
14
15#[derive(Debug, Default)]
16pub struct CowArc<T: Clone>{
17    inner: Arc<T>
18}
19impl<T: Clone> CowArc<T> {
20    /// Creates new CowArc value
21    pub fn new(val: T) -> CowArc<T>{
22        CowArc{
23            inner: Arc::new(val)
24        }
25    }
26    
27    /// Method sets new value for inner Arc value.
28    /// Performs new allocation. 
29    /// All previous values are still available over previous clones.
30    /// # Examples
31    /// ```
32    /// use cow_arc::CowArc;
33    /// use std::ops::Deref;
34    ///
35    /// let source = CowArc::new(vec![1, 2, 3]);
36    /// 
37    /// // Still shared memory
38    /// let mut changed = source.clone();
39    /// assert!(std::ptr::eq(source.deref(), changed.deref()) == true);
40    /// assert!(changed.eq(&vec![1, 2, 3]));
41    /// 
42    /// // New memory allocation
43    /// changed.set_val(vec![1, 2, 3, 4]);
44    /// assert!(std::ptr::eq(source.deref(), changed.deref()) == false);
45    /// assert!(changed.eq(&vec![1, 2, 3, 4]));
46    /// ```
47    pub fn set_val(&mut self, val: T){
48        self.inner = Arc::new(val);
49    }
50
51    /// Method updates inner Arc value by replacing it with new value.
52    /// Performs new allocation.
53    /// All previous values are still available over previous clones.
54    /// # Examples
55    /// ```
56    /// use cow_arc::CowArc;
57    /// use std::ops::Deref;
58    ///
59    /// let source = CowArc::new(vec![1, 2, 3]);
60    /// 
61    /// // Still shared memory
62    /// let mut updated = source.clone();
63    /// assert!(std::ptr::eq(source.deref(), updated.deref()) == true);
64    /// assert!(updated.eq(&vec![1, 2, 3]));
65    /// 
66    /// // New memory allocation
67    /// updated.update_val(|val|{
68    ///        val.push(4);
69    /// });
70    /// assert!(std::ptr::eq(source.deref(), updated.deref()) == false);
71    /// assert!(updated.eq(&vec![1, 2, 3, 4]));
72    /// ```
73    pub fn update_val<F: FnOnce(&mut T)>(&mut self, f: F) {
74        let mut v: T = self.inner.deref().clone();
75        f(&mut v);
76        self.inner = Arc::new(v);
77    }
78}
79impl<T: Clone> Deref for CowArc<T>{
80    type Target = T;
81    fn deref(&self) -> &Self::Target {
82        self.inner.deref()
83    }
84}
85impl<T: Clone> Clone for CowArc<T>{
86    fn clone(&self) -> Self {
87        CowArc{
88            inner: self.inner.clone()
89        }   
90    }
91}
92
93#[cfg(test)]
94mod tests{
95    use super::*;
96
97    #[test]
98    fn test_cow_arc(){
99        {
100            let test_str = "Test string";
101            let new_val_str = "New value";
102
103            let source = CowArc::new(test_str.to_owned());
104            let cloned = source.clone();
105            let mut changed = cloned.clone();
106            changed.set_val(new_val_str.to_owned());
107            let changed_cloned = changed.clone();
108    
109            let source_ptr: &String = source.deref();
110            let cloned_ptr: &String = cloned.deref();
111            let changed_ptr: &String = changed.deref();
112            let changed_cloned_ptr: &String = changed_cloned.deref();
113    
114            assert!(std::ptr::eq(source_ptr, cloned_ptr));
115            assert!(std::ptr::eq(source_ptr, changed_ptr) == false);
116            assert!(std::ptr::eq(changed_ptr, changed_cloned_ptr));
117            assert!(cloned_ptr.eq(test_str));
118            assert!(changed.eq(new_val_str));
119        }
120
121        {
122            let source = CowArc::new(vec![1, 2, 3]);
123            let cloned = source.clone();
124            let mut changed = cloned.clone();
125            changed.set_val(vec![1, 2, 3, 4]);
126            let changed_cloned = changed.clone();
127            let mut updated = changed_cloned.clone();
128            updated.update_val(|val|{
129                val.push(5);
130            });
131
132            let source_ptr: &Vec<i32> = source.deref();
133            let cloned_ptr: &Vec<i32> = cloned.deref();
134            let changed_ptr: &Vec<i32> = changed.deref();
135            let changed_cloned_ptr: &Vec<i32> = changed_cloned.deref();
136            let updated_ptr: &Vec<i32> = updated.deref();
137
138            assert!(std::ptr::eq(source_ptr, cloned_ptr));
139            assert!(std::ptr::eq(source_ptr, changed_ptr) == false);
140            assert!(std::ptr::eq(changed_ptr, changed_cloned_ptr));
141            assert!(std::ptr::eq(changed_ptr, updated_ptr) == false);
142            assert!(changed.eq(&vec![1, 2, 3, 4]));
143            assert!(updated.eq(&vec![1, 2, 3, 4, 5]));
144        }
145    }
146}