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}