1use std::cell::UnsafeCell;
2use std::ops::{Deref, DerefMut};
4
5pub struct ScopeCell<'a, T: Clone> {
10 original_data: &'a T,
11 modified_data: UnsafeCell<Option<T>>, }
13
14impl<'a, T: Clone> ScopeCell<'a, T> {
15 pub fn new(data: &'a T) -> Self {
17 ScopeCell {
18 original_data: data,
19 modified_data: UnsafeCell::new(None),
20 }
21 }
22
23 pub fn into_inner(self) -> T {
25 if let Some(modified) = unsafe { (*self.modified_data.get()).take() } {
26 modified
27 } else {
28 self.original_data.clone()
29 }
30 }
31
32 pub fn revert(&mut self) {
34 unsafe {
35 *self.modified_data.get() = None;
36 }
37 }
38
39 pub fn get(&self) -> &T {
41 if let Some(ref modified) = unsafe { &*self.modified_data.get() } {
42 modified
43 } else {
44 self.original_data
45 }
46 }
47
48 pub fn get_mut(&self) -> &mut T {
50 if unsafe { &*self.modified_data.get() }.is_none() {
51 unsafe {
53 *self.modified_data.get() = Some(self.original_data.clone());
54 }
55 }
56
57 unsafe { (*self.modified_data.get()).as_mut().unwrap() }
58 }
59}
60
61pub struct ScopeBorrow<'b, T: Clone> {
62 cell: &'b ScopeCell<'b, T>,
63}
64
65impl<'b, T: Clone> Deref for ScopeBorrow<'b, T> {
66 type Target = T;
67
68 fn deref(&self) -> &Self::Target {
69 self.cell.get()
70 }
71}
72
73pub struct ScopeBorrowMut<'b, T: Clone> {
74 cell: &'b mut ScopeCell<'b, T>,
75}
76
77impl<'b, T: Clone> Deref for ScopeBorrowMut<'b, T> {
78 type Target = T;
79
80 fn deref(&self) -> &Self::Target {
81 self.cell.get()
82 }
83}
84
85impl<'b, T: Clone> DerefMut for ScopeBorrowMut<'b, T> {
86 fn deref_mut(&mut self) -> &mut Self::Target {
87 self.cell.get_mut()
88 }
89}
90
91impl<'a, T: Clone> Drop for ScopeCell<'a, T> {
93 fn drop(&mut self) {
94 self.revert(); }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_basic_revert() {
104 let data = 10;
105 {
106 let mut scope = ScopeCell::new(&data);
107 *scope.get_mut() = 20;
108 assert_eq!(*scope.get(), 20);
109 } assert_eq!(data, 10); }
112
113 #[test]
114 fn test_revert_mid_scope() {
115 let data = vec![1, 2, 3];
116 {
117 let mut scope = ScopeCell::new(&data);
118 scope.get_mut().push(4);
119 scope.revert(); assert_eq!(scope.get().len(), 3); scope.get_mut().push(5);
122 }
123 assert_eq!(data, vec![1, 2, 3]); }
125
126 #[test]
127 fn test_into_inner_no_revert() {
128 let data = vec![1, 2, 3];
129 let inner;
130 {
131 let mut scope = ScopeCell::new(&data);
132 scope.get_mut().push(4); inner = scope.into_inner(); }
135 assert_eq!(inner, vec![1, 2, 3, 4]); assert_eq!(data, vec![1, 2, 3]); }
138
139 #[test]
140 fn test_multiple_reverts() {
141 let data = vec![1, 2, 3];
142 {
143 let mut scope = ScopeCell::new(&data);
144 scope.get_mut().push(4);
145 scope.revert(); scope.get_mut().push(5);
147 scope.revert(); }
149 assert_eq!(data, vec![1, 2, 3]); }
151
152 #[test]
153 fn test_with_string_mutation() {
154 let data = String::from("hello");
155 {
156 let mut scope = ScopeCell::new(&data);
157 scope.get_mut().push_str(" world");
158 assert_eq!(*scope.get(), "hello world"); }
160 assert_eq!(data, "hello"); }
162
163 #[test]
164 fn test_with_copy_type() {
165 let data = 10;
166 {
167 let mut Scope = ScopeCell::new(&data);
168 *Scope.get_mut() = 20;
169 assert_eq!(*Scope.get(), 20); }
171 assert_eq!(data, 10); }
173
174 #[test]
175 fn test_with_needs_drop_type() {
176 let data = vec![1, 2, 3];
177 {
178 let mut Scope = ScopeCell::new(&data);
179 Scope.get_mut().push(4);
180 assert_eq!(*Scope.get(), vec![1, 2, 3, 4]); }
182 assert_eq!(data, vec![1, 2, 3]); }
184
185 #[test]
186 fn test_nested_borrows() {
187 let data = vec![1, 2, 3];
188 {
189 let mut Scope = ScopeCell::new(&data);
190 let mut borrowed = Scope.get_mut();
191 borrowed.push(4);
192 assert_eq!(borrowed.len(), 4); borrowed.pop(); }
195 assert_eq!(data, vec![1, 2, 3]); }
197
198 #[test]
199 fn test_multiple_scope_cells() {
200 let data1 = vec![1, 2, 3];
201 let data2 = vec![4, 5, 6];
202
203 {
204 let mut scope1 = ScopeCell::new(&data1);
205 let mut scope2 = ScopeCell::new(&data2);
206
207 scope1.get_mut().push(4);
208 scope2.get_mut().push(7);
209 }
210 assert_eq!(data1, vec![1, 2, 3]); assert_eq!(data2, vec![4, 5, 6]); }
213
214 #[test]
215 fn test_needs_drop_after_into_inner() {
216 let data = vec![1, 2, 3];
217 {
218 let scope = ScopeCell::new(&data);
219 let _inner = scope.into_inner(); }
221 assert_eq!(data.len(), 3);
223 }
224
225 #[test]
226 fn test_no_mutation_revert() {
227 let data = vec![1, 2, 3];
228 {
229 let scope = ScopeCell::new(&data);
230 }
232 assert_eq!(data, vec![1, 2, 3]); }
234
235 #[test]
236 fn test_multiple_borrow_same_scope() {
237 let data = vec![1, 2, 3];
238 {
239 let mut scope = ScopeCell::new(&data);
240 let borrowed1 = scope.get();
241 let borrowed2 = scope.get();
242 assert_eq!(borrowed1.len(), 3);
243 assert_eq!(borrowed2.len(), 3);
244 }
245 assert_eq!(data, vec![1, 2, 3]); }
247
248 #[test]
249 fn test_mutation_after_revert() {
250 let data = vec![1, 2, 3];
251 {
252 let mut scope = ScopeCell::new(&data);
253 scope.get_mut().push(4);
254 scope.revert();
255 assert_eq!(scope.get().len(), 3); scope.get_mut().push(5); assert_eq!(scope.get().len(), 4); }
259 assert_eq!(data, vec![1, 2, 3]); }
261
262 #[test]
263 fn test_borrow_and_mut_borrow() {
264 let data = vec![1, 2, 3];
265 {
266 let mut scope = ScopeCell::new(&data);
267 let borrowed = scope.get(); assert_eq!(borrowed.len(), 3);
269
270 let mut borrowed_mut = scope.get_mut(); borrowed_mut.push(4);
272 assert_eq!(borrowed_mut.len(), 4);
273 }
274 assert_eq!(data, vec![1, 2, 3]); }
276
277 #[test]
278 fn test_nested_scope_cell() {
279 let data1 = vec![1, 2, 3];
280 let data2 = vec![4, 5, 6];
281 {
282 let mut outer_scope = ScopeCell::new(&data1);
283 let mut inner_scope = ScopeCell::new(&data2);
284 inner_scope.get_mut().push(7);
285 outer_scope.get_mut().push(4);
286
287 assert_eq!(inner_scope.get(), &vec![4, 5, 6, 7]);
288 assert_eq!(outer_scope.get(), &vec![1, 2, 3, 4]);
289 }
290 assert_eq!(data1, vec![1, 2, 3]); assert_eq!(data2, vec![4, 5, 6]); }
293}