rccell/
lib.rs

1//! A convenient wrapper for `Rc<RefCell<T>>>` and `Weak<RefCell<T>>>`.
2//!
3//! The `RcCell` library defines two structs:
4//! - `RcCell<T>`: a wrapper for `Rc<RefCell<T>>`.
5//! - `WeakCell<T>`: a wrapper for `Weak<RefCell<T>>`.
6//!
7//! ```rust
8//! use rccell::{RcCell, WeakCell};
9//!
10//! let a = RcCell::new(1);     // a is a RcCell that wraps an Rc<RefCell<i32>>
11//! let b = a.clone();          // You can create multiple RcCells pointing to the same data.
12//!
13//! let mut c = a.borrow_mut();  // You can use borrow and borrow_mut methods as if  RcCells were RefCells
14//! *c = 2;
15//! // let mut d = b.borrow_mut()   You cannot create two RefMuts for the same RcCell.
16//! drop(c);
17//!
18//! assert!(a.try_borrow().is_ok());  // You can use try_borrow and try_borrow_mut to avoid panicking
19//! // let d = a.unwrap()  You can use unwrap to get the inner value (if there is only one RcCell)
20//! assert!(a.try_unwrap().is_err());  // You can use try_unwrap to avoid panicking
21//!
22//! let d: WeakCell<i32> = b.downgrade();  // Use downgrade to create a WeakCell pointing to the same data
23//! assert!(d.upgrade().is_some());  // Use the upgrade method to get a RcCell pointing to the same data as the WeakCell.
24//! ```
25//!
26//! `RcCell<T>` structs implement the `Hash` trait by using the value of their inner `Rc` pointer value.
27
28use std::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut};
29use std::cmp::PartialEq;
30use std::fmt::Debug;
31use std::hash::{Hash, Hasher};
32use std::ops::Deref;
33use std::pin::Pin;
34use std::rc::{Rc, Weak};
35
36/// Wrapper for `Rc<RefCell<T>>`.
37#[derive(Debug, Default, Eq)]
38pub struct RcCell<T>(Rc<RefCell<T>>);
39
40/// Version of `RefCell` that holds a non-owning reference to the managed allocation.
41#[derive(Debug, Default)]
42pub struct WeakCell<T>(Weak<RefCell<T>>);
43
44impl<T> RcCell<T> {
45    /// Constructs a new `RcCell<T>`.
46    /// # Examples
47    /// ```rust
48    /// use rccell::RcCell;
49    ///
50    /// let x = RcCell::new(1);
51    /// ```
52    pub fn new(value: T) -> Self {
53        Self(Rc::new(RefCell::new(value)))
54    }
55
56    /// Similar to [Rc::try_unwrap].
57    /// Returns the inner value if the `RefCell` has only one strong reference.
58    /// Otherwise, it returns an `Err` with the same `RefCell` that was passed in.
59    /// Note that this function success even if there are multiple weak references.
60    /// # Examples
61    /// ```rust
62    /// use rccell::RcCell;
63    ///
64    /// let x = RcCell::new(1);
65    /// assert_eq!(RcCell::try_unwrap(x), Ok(1));
66    ///
67    /// let x = RcCell::new(2);
68    /// let _y = RcCell::clone(&x);
69    /// assert!(RcCell::try_unwrap(x).is_err());
70    /// ```
71    pub fn try_unwrap(self) -> Result<T, Self> {
72        Rc::try_unwrap(self.0)
73            .map(RefCell::into_inner)
74            .map_err(Self)
75    }
76
77    /// Returns the inner value if the `RefCell` has only one strong reference. Otherwise, it panics.
78    /// Note that this function success even if there are multiple weak references.
79    /// # Examples
80    /// ```rust
81    /// use rccell::RcCell;
82    ///
83    /// let x = RcCell::new(1);
84    /// assert_eq!(RcCell::unwrap(x), 1);
85    ///
86    /// let x = RcCell::new(2);
87    /// let _y = RcCell::clone(&x);
88    /// // assert_eq!(RcCell::unwrap(x), 2);  // This will panic, as there are two RcCells
89    /// ```
90    pub fn unwrap(self) -> T {
91        self.try_unwrap().ok().unwrap()
92    }
93
94    /// Similar to [Rc::downgrade].
95    /// Creates a new [WeakCell] pointer to this allocation.
96    /// # Examples
97    /// ```rust
98    /// use rccell::RcCell;
99    ///
100    /// let x = RcCell::new(1);
101    /// let weak_five = x.downgrade();
102    /// ```
103    pub fn downgrade(&self) -> WeakCell<T> {
104        WeakCell(Rc::downgrade(&self.0))
105    }
106
107    /// Similar to [Rc::weak_count].
108    /// Gets the number of [WeakCell] pointers to this allocation.
109    /// # Examples
110    /// ```rust
111    /// use rccell::RcCell;
112    ///
113    /// let x = RcCell::new(1);
114    /// let weak_five = x.downgrade();
115    ///
116    /// assert_eq!(RcCell::weak_count(&x), 1);
117    /// ```
118    pub fn weak_count(this: &Self) -> usize {
119        Rc::weak_count(&this.0)
120    }
121
122    /// Similar to [Rc::strong_count].
123    /// Gets the number of strong ([RcCell]) pointers to this allocation.
124    /// # Examples
125    /// ```rust
126    /// use rccell::RcCell;
127    ///
128    /// let x = RcCell::new(1);
129    /// let _y = x.clone();
130    ///
131    /// assert_eq!(RcCell::strong_count(&x), 2);
132    /// ```
133    pub fn strong_count(this: &Self) -> usize {
134        Rc::strong_count(&this.0)
135    }
136
137    /// Similar to [Rc::ptr_eq].
138    /// Returns `true` if two `RcCell`s point to the same allocation.
139    /// # Examples
140    /// ```rust
141    /// use rccell::RcCell;
142    ///
143    /// let x = RcCell::new(1);
144    /// let xx = x.clone();
145    /// let y = RcCell::new(1);
146    ///
147    /// assert!(RcCell::ptr_eq(&x, &xx));
148    /// assert!(!RcCell::ptr_eq(&x, &y));
149    /// ```
150    pub fn ptr_eq(this: &Self, other: &Self) -> bool {
151        Rc::ptr_eq(&this.0, &other.0)
152    }
153
154    /// Similar to [RefCell::try_borrow].
155    /// Returns a [Ref] to the inner value if there is no [RefMut] pointing to the same allocation.
156    /// Otherwise, it returns a `BorrowError`.
157    /// # Examples
158    /// ```rust
159    /// use rccell::RcCell;
160    ///
161    /// let x = RcCell::new(1);
162    ///
163    /// let x_ref = x.try_borrow();
164    /// assert!(x_ref.is_ok());
165    /// ```
166    pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> {
167        self.0.try_borrow()
168    }
169
170    /// Similar to [RefCell::try_borrow_mut].
171    /// Returns a [RefMut] to the inner value if there is no [RefMut] nor [Ref] pointing to the same allocation.
172    /// Otherwise, it returns a `BorrowMutError`.
173    /// # Examples
174    /// ```rust
175    /// use rccell::RcCell;
176    ///
177    /// let x = RcCell::new(1);
178    ///
179    /// let mut x_ref = x.try_borrow_mut();
180    /// assert!(x_ref.is_ok());
181    /// ```
182    pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError> {
183        self.0.try_borrow_mut()
184    }
185
186    /// Similar to [RefCell::borrow].
187    /// Returns a [Ref] to the inner value if there is no [RefMut] pointing to the same allocation.
188    /// Otherwise, it panics.
189    /// # Examples
190    /// ```rust
191    /// use rccell::RcCell;
192    ///
193    /// let x = RcCell::new(1);
194    /// let x_ref = x.borrow();
195    /// ```
196    pub fn borrow(&self) -> Ref<T> {
197        self.0.borrow()
198    }
199
200    /// Similar to [RefCell::borrow_mut].
201    /// Returns a [RefMut] to the inner value if there is no [RefMut] nor [Ref] pointing to the same allocation.
202    /// Otherwise, it panics.
203    /// # Examples
204    /// ```rust
205    /// use rccell::RcCell;
206    ///
207    /// let x = RcCell::new(1);
208    /// let x_ref = x.borrow_mut();
209    /// ```
210    pub fn borrow_mut(&self) -> RefMut<T> {
211        self.0.borrow_mut()
212    }
213}
214
215impl<T: std::marker::Unpin> RcCell<T> {
216    /// Constructs a new `Pin<RcCell<T>>`. It is only implemented if T implements [Unpin].
217    pub fn pin(value: T) -> Pin<Self> {
218        Pin::new(Self::new(value))
219    }
220}
221
222impl<T> WeakCell<T> {
223    /// Constructs a new `WeakCell<T>`, without allocating any memory.
224    /// Calling [WeakCell::upgrade] on the return value always gives [None].
225    /// # Examples
226    /// ```rust
227    /// use rccell::WeakCell;
228    ///
229    /// let empty: WeakCell<i32> = WeakCell::new();
230    /// assert!(empty.upgrade().is_none());
231    /// ```
232    pub fn new() -> Self {
233        Self(Weak::new())
234    }
235
236    /// Similar to [Weak::upgrade].
237    /// Attempts to upgrade the `WeakCell` pointer to an `RcCell`.
238    /// Returns `None` if the inner value has been dropped.
239    /// # Examples
240    /// ```rust
241    /// use rccell::RcCell;
242    ///
243    /// let five = RcCell::new(5);
244    ///
245    /// let weak_five = five.downgrade();
246    /// let strong_five = weak_five.upgrade();
247    /// assert!(strong_five.is_some());
248    ///
249    /// drop(strong_five);
250    /// drop(five);
251    /// assert!(weak_five.upgrade().is_none());
252    /// ```
253    pub fn upgrade(&self) -> Option<RcCell<T>> {
254        self.0.upgrade().map(RcCell)
255    }
256
257    /// Gets the number of strong (`RcCell`) pointers pointing to this allocation.
258    /// If `self` was created using [WeakCell::new], this will return 0.
259    pub fn strong_count(&self) -> usize {
260        self.0.strong_count()
261    }
262
263    /// Gets the number of `WeakCell` pointers pointing to this allocation.
264    /// If no strong pointers remain, this will return 0.
265    pub fn weak_count(&self) -> usize {
266        self.0.weak_count()
267    }
268
269    /// Returns `true` if the two `Weak`s point to the same allocation, or if both don't point to any allocation.
270    pub fn ptr_eq(&self, other: &Self) -> bool {
271        self.0.ptr_eq(&other.0)
272    }
273}
274
275impl<T> Clone for RcCell<T> {
276    fn clone(&self) -> Self {
277        RcCell(self.0.clone())
278    }
279}
280
281/// `RefCell<T>` does not implement `Deref`, and borrowing its inner value can cause a lot of panic errors.
282/// Therefore, `Deref::deref` will return a reference to the inner `RefCell<T>`.
283impl<T> Deref for RcCell<T> {
284    type Target = RefCell<T>;
285    fn deref(&self) -> &Self::Target {
286        self.0.deref()
287    }
288}
289
290/// `RefCell<T>` does not implement `PartialEq`, and borrowing its inner value can cause a lot of panic errors.
291/// Therefore, `Hash` will only use the value of the `Rc` pointer inside `RefCell<T>`.
292impl<T> Hash for RcCell<T> {
293    fn hash<H: Hasher>(&self, state: &mut H) {
294        self.0.as_ptr().hash(state);
295    }
296}
297
298/// `RefCell<T>` does not implement `PartialEq`, and borrowing its inner value can cause a lot of panic errors.
299/// Therefore, `PartialEq` will check that two `RefCell<T>` point to the exact same allocation.
300impl<T> PartialEq for RcCell<T> {
301    fn eq(&self, other: &Self) -> bool {
302        self.0.as_ptr() == other.0.as_ptr()
303    }
304}
305
306impl<T> Clone for WeakCell<T> {
307    fn clone(&self) -> Self {
308        WeakCell(self.0.clone())
309    }
310}
311
312#[cfg(test)]
313mod tests {
314    use super::RcCell;
315    use std::collections::HashMap;
316
317    #[derive(Debug, PartialEq, Eq)]
318    struct DummyStruct {
319        name: String,
320    }
321    impl DummyStruct {
322        fn new(name: &str) -> Self {
323            Self {
324                name: name.to_string(),
325            }
326        }
327    }
328
329    #[test]
330    fn test_try_unwrap() {
331        let a = RcCell::new(DummyStruct::new("dummy"));
332        let b = a.clone();
333        let c = b.clone();
334        let d = c.downgrade();
335        let e = d.clone();
336        assert!(RcCell::ptr_eq(&a, &c));
337        assert_eq!(RcCell::weak_count(&a), 2);
338        assert_eq!(RcCell::strong_count(&a), 3);
339
340        assert!(RcCell::try_unwrap(a).is_err());
341        assert!(d.upgrade().is_some());
342        assert!(RcCell::try_unwrap(b).is_err());
343        assert!(e.upgrade().is_some());
344        let res = RcCell::try_unwrap(c);
345        assert!(res.is_ok());
346        assert_eq!(res.ok().unwrap().name, "dummy");
347        assert!(d.upgrade().is_none());
348        assert!(e.upgrade().is_none());
349    }
350
351    #[test]
352    #[should_panic(expected = "called `Option::unwrap()` on a `None` value")]
353    fn test_unwrap_panic() {
354        let a = RcCell::new(DummyStruct::new("dummy"));
355        let _b = a.clone();
356        let _res = RcCell::unwrap(a);
357    }
358
359    #[test]
360    fn test_unwrap_ok() {
361        let a = RcCell::new(DummyStruct::new("dummy"));
362        let _b = a.downgrade();
363        assert_eq!(RcCell::unwrap(a).name, "dummy")
364    }
365
366    #[test]
367    fn test_try_borrows() {
368        let a = RcCell::new(DummyStruct::new("dummy"));
369        let b = a.downgrade();
370        assert_eq!(RcCell::weak_count(&a), 1);
371        assert_eq!(RcCell::strong_count(&a), 1);
372        assert!(a.try_borrow().is_ok());
373        assert!(b.upgrade().is_some());
374        assert!(b.upgrade().unwrap().try_borrow().is_ok());
375
376        let c = b.upgrade().unwrap();
377        assert!(a.try_borrow().is_ok());
378        assert!(b.upgrade().is_some());
379        assert!(b.upgrade().unwrap().try_borrow().is_ok());
380        assert!(c.try_borrow().is_ok());
381
382        let d = a.try_borrow_mut();
383        assert!(d.is_ok());
384        assert!(c.try_borrow().is_err());
385        assert!(c.try_borrow_mut().is_err());
386        drop(d);
387        let d = a.try_borrow();
388        assert!(d.is_ok());
389        assert!(c.try_borrow().is_ok());
390        assert!(c.try_borrow_mut().is_err());
391    }
392
393    #[test]
394    #[should_panic(expected = "already borrowed: BorrowMutError")]
395    fn test_borrow_mut_panic() {
396        let a = RcCell::new(DummyStruct::new("dummy"));
397        let _b = a.try_borrow();
398        a.borrow_mut();
399    }
400
401    #[test]
402    #[should_panic(expected = "already borrowed: BorrowMutError")]
403    fn test_mut_borrow_panic() {
404        let a = RcCell::new(DummyStruct::new("dummy"));
405        let _b = a.try_borrow_mut();
406        a.borrow_mut();
407    }
408
409    #[test]
410    #[should_panic(expected = "already mutably borrowed: BorrowError")]
411    fn test_mut_borrow_mut_panic() {
412        let a = RcCell::new(DummyStruct::new("dummy"));
413        let _b = a.try_borrow_mut();
414        a.borrow();
415    }
416
417    #[test]
418    fn test_borrow() {
419        let a = RcCell::new(DummyStruct::new("dummy"));
420        let b = a.clone();
421        let c = RcCell::new(DummyStruct::new("dummy"));
422        assert_eq!(a, b);
423        assert_ne!(a, c);
424        assert_eq!(*a.borrow(), *c.borrow());
425        assert!(RcCell::ptr_eq(&a, &b));
426        assert!(!RcCell::ptr_eq(&a, &c));
427
428        a.borrow_mut().name = String::from("DUMMY");
429        assert_eq!(a, b);
430        assert_ne!(a, c);
431        assert_ne!(*a.borrow(), *c.borrow());
432    }
433
434    #[test]
435    fn test_hashmap() {
436        let a = RcCell::new(DummyStruct::new("a"));
437        let b = RcCell::new(DummyStruct::new("a"));
438        let c = RcCell::new(DummyStruct::new("a"));
439        assert!(!RcCell::ptr_eq(&a, &b));
440
441        let mut map = HashMap::new();
442        assert!(map.is_empty());
443        assert!(map.insert(a.clone(), 1).is_none());
444        assert!(map.insert(b.clone(), 2).is_none());
445        assert!(map.insert(a.clone(), 3).is_some());
446        assert!(map.get(&a).is_some());
447        assert_eq!(map.get(&a).unwrap(), &3);
448        assert!(map.get(&b).is_some());
449        assert_eq!(map.get(&b).unwrap(), &2);
450        assert!(map.get(&c).is_none());
451    }
452}