mut_rc/
lib.rs

1#![no_std]
2#![forbid(unsafe_code)]
3
4#![doc = include_str!("../README.md")]
5
6#[cfg_attr(test, macro_use)]
7extern crate alloc;
8
9use core::cell::{RefCell, BorrowError, BorrowMutError};
10use alloc::rc::{Rc, Weak};
11
12/// An error resulting from [`MutRc::with_mut`].
13#[derive(Debug)]
14pub enum MutateError {
15    /// The shared value is already borrowed.
16    /// This can be caused if the same shared value is accessed from within [`MutRc::with`] or [`MutRc::with_mut`].
17    BorrowMutError(BorrowMutError),
18    /// There exists an aliasing [`Rc<T>`] returned by [`MutRc::finalize`] on the same shared value.
19    Finalized,
20}
21
22/// A temporarily-mutable version of [`Rc`].
23/// 
24/// [`MutRc<T>`] is essentially equivalent to [`Rc<RefCell<T>>`] except that it can be "finalized" into an [`Rc<T>`] once mutation is no longer needed.
25/// This operation preserves the original aliasing topology, and is useful for initializing aliasing structures
26/// that initially need mutability, but later can be converted to an immutable form.
27/// 
28/// All operations on [`MutRc`] are guaranteed to not panic.
29#[derive(Debug, Default)]
30pub struct MutRc<T>(Rc<RefCell<Rc<T>>>);
31impl<T> MutRc<T> {
32    /// Creates a new, unaliased instance of [`MutRc<T>`] with the given initial value.
33    pub fn new(value: T) -> Self {
34        Self(Rc::new(RefCell::new(Rc::new(value))))
35    }
36    /// Accesses the shared value immutably, optionally returning the result of the callback.
37    /// 
38    /// This operation can fail if the shared value is already borrowed mutably (i.e., if called from within [`MutRc::with_mut`] on the same shared value).
39    pub fn with<U, F: FnOnce(&T) -> U>(&self, f: F) -> Result<U, BorrowError> {
40        Ok(f(&*self.0.try_borrow()?))
41    }
42    /// Accesses the shared value mutably, optionally returning the result of the callback.
43    /// 
44    /// This operation can fail if the shared value is already borrowed (i.e., if called from within [`MutRc::with`] or [`MutRc::with_mut`] on the same shared value),
45    /// or if there exists an aliasing [`Rc<T>`] returned by [`MutRc::finalize`] on the same shared value.
46    /// 
47    /// If recursion is needed, but mutation is not, consider using [`MutRc::with`] instead.
48    pub fn with_mut<U, F: FnOnce(&mut T) -> U>(&self, f: F) -> Result<U, MutateError> {
49        match self.0.try_borrow_mut() {
50            Ok(mut x) => match Rc::get_mut(&mut *x) {
51                Some(x) => Ok(f(x)),
52                None => Err(MutateError::Finalized),
53            }
54            Err(e) => Err(MutateError::BorrowMutError(e)),
55        }
56    }
57    /// Finalizes the value into an (immutable) aliasing instance of [`Rc<T>`].
58    /// While this aliasing [`Rc<T>`] exists, all subsequent calls to [`MutRc::with_mut`] on the same shared value will fail.
59    /// 
60    /// This operation can fail if the shared value is already borrowed mutably (i.e., if called from within [`MutRc::with_mut`] on the same shared value).
61    pub fn finalize(&self) -> Result<Rc<T>, BorrowError> {
62        Ok(self.0.try_borrow()?.clone())
63    }
64
65    // -------------------------------------------------------------
66
67    /// Gets a copy of the currently stored value.
68    pub fn get(&self) -> Result<T, BorrowError> where T: Copy {
69        self.with(|x| *x)
70    }
71    /// Gets a clone of the currently stored value.
72    pub fn get_clone(&self) -> Result<T, BorrowError> where T: Clone {
73        self.with(Clone::clone)
74    }
75    /// Takes the currently stored value and replaces it with the default value.
76    pub fn take(&self) -> Result<T, MutateError> where T: Default {
77        self.with_mut(core::mem::take)
78    }
79    /// Replaces the currently stored value and returns the previous value.
80    pub fn replace(&self, value: T) -> Result<T, MutateError> {
81        self.with_mut(|x| core::mem::replace(x, value))
82    }
83    /// Sets the currently stored value.
84    pub fn set(&self, value: T) -> Result<(), MutateError> {
85        self.with_mut(|x| *x = value)
86    }
87
88    // -------------------------------------------------------------
89
90    /// Checks if two instances of [`MutRc<T>`] are aliases to the same value.
91    pub fn ptr_eq(this: &MutRc<T>, other: &MutRc<T>) -> bool {
92        Rc::ptr_eq(&this.0, &other.0)
93    }
94
95    // -------------------------------------------------------------
96
97    /// Downgrades this [`MutRc`] into a [`MutWeak`].
98    pub fn downgrade(this: &Self) -> MutWeak<T> {
99        MutWeak(Rc::downgrade(&this.0))
100    }
101}
102impl<T> Clone for MutRc<T> {
103    fn clone(&self) -> Self {
104        Self(self.0.clone())
105    }
106}
107impl<T> From<T> for MutRc<T> {
108    fn from(value: T) -> Self {
109        Self::new(value)
110    }
111}
112
113/// A weak reference counted version of [`MutRc`].
114pub struct MutWeak<T>(Weak<RefCell<Rc<T>>>);
115impl<T> MutWeak<T> {
116    // Creates a new, unaliased instance of [`MutWeak<T>`].
117    pub fn new() -> Self {
118        MutWeak(Weak::new())
119    }
120
121
122    /// Checks if two instances of [`MutWeak`] are (weak) aliases to the same value.
123    pub fn ptr_eq(this: &Self, other: &MutWeak<T>) -> bool {
124        this.0.ptr_eq(&other.0)
125    }
126
127    // -------------------------------------------------------------
128
129    /// Attempts to upgrade the weak reference back to a strong reference.
130    pub fn upgrade(&self) -> Option<MutRc<T>> {
131        self.0.upgrade().map(MutRc)
132    }
133}
134impl<T> Clone for MutWeak<T> {
135    fn clone(&self) -> Self {
136        Self(self.0.clone())
137    }
138}
139impl<T> Default for MutWeak<T> {
140    fn default() -> MutWeak<T> {
141        MutWeak::new()
142    }
143}
144impl<T> core::fmt::Debug for MutWeak<T> {
145    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
146        write!(f, "(MutWeak)")
147    }
148}
149
150#[test]
151fn test_basic() {
152    struct NoClone(i32);
153
154    let a = MutRc::new(NoClone(45));
155    let b = a.clone();
156    let c = MutRc::new(NoClone(45));
157
158    assert!(MutRc::ptr_eq(&a, &b));
159    assert!(!MutRc::ptr_eq(&a, &c));
160    assert!(!MutRc::ptr_eq(&b, &c));
161
162    assert_eq!(a.with(|x| x.0).unwrap(), 45);
163    assert_eq!(b.with(|x| x.0).unwrap(), 45);
164    assert_eq!(c.with(|x| x.0).unwrap(), 45);
165
166    a.with_mut(|x| x.0 = -23).unwrap();
167
168    match a.with_mut(|_| a.with_mut(|_| ())) {
169        Ok(Err(MutateError::BorrowMutError(_))) => (),
170        x => panic!("{x:?}"),
171    }
172
173    assert_eq!(a.with(|x| x.0).unwrap(), -23);
174    assert_eq!(b.with(|x| x.0).unwrap(), -23);
175    assert_eq!(c.with(|x| x.0).unwrap(), 45);
176
177    assert_eq!(a.with(|_| a.with(|x| x.0).unwrap()).unwrap(), -23);
178    assert_eq!(b.with(|_| b.with(|x| x.0).unwrap()).unwrap(), -23);
179    assert_eq!(c.with(|_| c.with(|x| x.0).unwrap()).unwrap(), 45);
180
181    a.finalize().unwrap();
182    b.finalize().unwrap();
183    c.finalize().unwrap();
184
185    b.with_mut(|x| x.0 = 17).unwrap();
186    c.with_mut(|x| x.0 = 12).unwrap();
187
188    assert_eq!(a.with(|_| a.with(|x| x.0).unwrap()).unwrap(), 17);
189    assert_eq!(b.with(|_| b.with(|x| x.0).unwrap()).unwrap(), 17);
190    assert_eq!(c.with(|_| c.with(|x| x.0).unwrap()).unwrap(), 12);
191
192    let fa = a.finalize().unwrap();
193    let fb = b.finalize().unwrap();
194    let fc = c.finalize().unwrap();
195
196    match (a.with_mut(|_| ()), b.with_mut(|_| ()), c.with_mut(|_| ())) {
197        (Err(MutateError::Finalized), Err(MutateError::Finalized), Err(MutateError::Finalized)) => (),
198        x => panic!("{x:?}"),
199    }
200
201    assert!(Rc::ptr_eq(&fa, &fb));
202    assert!(!Rc::ptr_eq(&fa, &fc));
203    assert!(!Rc::ptr_eq(&fb, &fc));
204
205    assert_eq!(fa.0, 17);
206    assert_eq!(fb.0, 17);
207    assert_eq!(fc.0, 12);
208
209    assert_eq!(a.with(|x| x.0).unwrap(), 17);
210    assert_eq!(b.with(|x| x.0).unwrap(), 17);
211    assert_eq!(c.with(|x| x.0).unwrap(), 12);
212
213    assert_eq!(a.with(|_| a.with(|x| x.0).unwrap()).unwrap(), 17);
214    assert_eq!(b.with(|_| b.with(|x| x.0).unwrap()).unwrap(), 17);
215    assert_eq!(c.with(|_| c.with(|x| x.0).unwrap()).unwrap(), 12);
216}
217
218#[test]
219fn test_traits() {
220    let a: MutRc<i32> = Default::default();
221    assert_eq!(a.with(|x| *x).unwrap(), 0);
222    let fa = a.finalize().unwrap();
223    assert_eq!(*fa, 0);
224
225    let s = format!("{a:?}");
226    assert!(!s.is_empty());
227
228    let b: MutRc<u64> = 475.into();
229    assert_eq!(b.with(|x| *x).unwrap(), 475);
230    let fb = b.finalize().unwrap();
231    assert_eq!(*fb, 475);
232}
233
234#[test]
235fn test_extra() {
236    #[derive(Default, Clone, Copy)]
237    struct Thing(i32);
238
239    let a = MutRc::new(Thing(23));
240    let b = a.clone();
241
242    assert_eq!(a.get().unwrap().0, 23);
243    assert_eq!(a.get_clone().unwrap().0, 23);
244    assert_eq!(b.get().unwrap().0, 23);
245    assert_eq!(b.get_clone().unwrap().0, 23);
246    assert!(MutRc::ptr_eq(&a, &b));
247
248    assert_eq!(b.replace(Thing(44)).unwrap().0, 23);
249    assert_eq!(a.get().unwrap().0, 44);
250    assert_eq!(a.get_clone().unwrap().0, 44);
251    assert_eq!(b.get().unwrap().0, 44);
252    assert_eq!(b.get_clone().unwrap().0, 44);
253    assert!(MutRc::ptr_eq(&a, &b));
254
255    assert_eq!(a.take().unwrap().0, 44);
256    assert_eq!(a.get().unwrap().0, 0);
257    assert_eq!(a.get_clone().unwrap().0, 0);
258    assert_eq!(b.get().unwrap().0, 0);
259    assert_eq!(b.get_clone().unwrap().0, 0);
260    assert!(MutRc::ptr_eq(&a, &b));
261
262    assert_eq!(b.set(Thing(47)).unwrap(), ());
263    assert_eq!(a.get().unwrap().0, 47);
264    assert_eq!(a.get_clone().unwrap().0, 47);
265    assert_eq!(b.get().unwrap().0, 47);
266    assert_eq!(b.get_clone().unwrap().0, 47);
267    assert!(MutRc::ptr_eq(&a, &b));
268}
269
270#[test]
271fn test_weak() {
272    struct NoClone;
273
274    let a = MutRc::new(NoClone);
275    let b = a.clone();
276    let c = MutRc::downgrade(&a);
277    let d = MutRc::downgrade(&b);
278    let e = MutRc::new(NoClone);
279    let f = MutRc::downgrade(&e);
280
281    assert!(MutWeak::ptr_eq(&c, &d));
282    assert!(!MutWeak::ptr_eq(&c, &f));
283    assert!(!MutWeak::ptr_eq(&d, &f));
284
285    assert!(MutWeak::ptr_eq(&c.clone(), &c.clone()));
286    assert!(MutWeak::ptr_eq(&c.clone(), &d.clone()));
287    assert!(MutWeak::ptr_eq(&d.clone(), &d.clone()));
288    assert!(MutWeak::ptr_eq(&f.clone(), &f.clone()));
289    assert!(!MutWeak::ptr_eq(&c.clone(), &f.clone()));
290    assert!(!MutWeak::ptr_eq(&d.clone(), &f.clone()));
291
292    assert!(MutRc::ptr_eq(&c.upgrade().unwrap(), &a));
293    assert!(MutRc::ptr_eq(&d.upgrade().unwrap(), &a));
294    assert!(MutRc::ptr_eq(&f.upgrade().unwrap(), &e));
295
296    drop(a);
297
298    assert!(MutRc::ptr_eq(&c.upgrade().unwrap(), &b));
299    assert!(MutRc::ptr_eq(&d.upgrade().unwrap(), &b));
300    assert!(MutRc::ptr_eq(&f.upgrade().unwrap(), &e));
301
302    drop(b);
303
304    assert!(c.upgrade().is_none());
305    assert!(d.upgrade().is_none());
306    assert!(MutRc::ptr_eq(&f.upgrade().unwrap(), &e));
307
308    drop(e);
309
310    assert!(c.upgrade().is_none());
311    assert!(d.upgrade().is_none());
312    assert!(f.upgrade().is_none());
313}
314
315#[test]
316fn test_weak_traits() {
317    struct NoClone;
318
319    let a: MutWeak<NoClone> = Default::default();
320    let d: MutWeak<NoClone> = MutWeak::new();
321    assert!(a.upgrade().is_none());
322    assert!(d.upgrade().is_none());
323
324    let s = format!("{a:?}");
325    assert!(!s.is_empty());
326    assert_eq!(s, "(MutWeak)");
327
328    let b = MutRc::new(NoClone);
329    let b = MutRc::downgrade(&b);
330
331    assert!(!MutWeak::ptr_eq(&a, &b));
332
333    let s = format!("{b:?}");
334    assert_eq!(s, "(MutWeak)");
335}