generic_container/impls/
checked_rc_refcell.rs

1use alloc::rc::Rc;
2use core::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut};
3
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7use crate::container_traits::{
8    FragileTryContainer, FragileTryMutContainer, TryContainer, TryMutContainer,
9};
10
11
12/// A thin wrapper around `Rc<RefCell<T>>` which implements the container traits differently:
13/// `CheckedRcRefCell<T>` is fallible, but not [fragile].
14///
15/// Note that `Rc<RefCell<T>>` is an infallible but [fragile] container, essentially interpreting
16/// any circumstance which *would* return an error in `CheckedRcRefCell<T>` as instead being a bug
17/// and panicking. The user of a fragile container must uphold greater restrictions, in exchange for
18/// infallibility. Those restrictions still effectively apply here, but violating them results in
19/// errors being returned instead of being fatal.
20///
21/// [fragile]: crate#fragility-potential-panics-or-deadlocks
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
24pub struct CheckedRcRefCell<T: ?Sized>(pub Rc<RefCell<T>>);
25
26impl<T: ?Sized> Clone for CheckedRcRefCell<T> {
27    #[inline]
28    fn clone(&self) -> Self {
29        Self(Rc::clone(&self.0))
30    }
31
32    #[inline]
33    fn clone_from(&mut self, source: &Self) {
34        self.0.clone_from(&source.0);
35    }
36}
37
38impl<T: ?Sized> FragileTryContainer<T> for CheckedRcRefCell<T> {
39    type Ref<'a>  = Ref<'a, T> where T: 'a;
40    type RefError = BorrowError;
41
42    #[inline]
43    fn new_container(t: T) -> Self where T: Sized {
44        Self(Rc::new(RefCell::new(t)))
45    }
46
47    /// Attempt to retrieve the inner `T` from the container.
48    /// Behaves identically to [`Rc::into_inner`].
49    #[inline]
50    fn into_inner(self) -> Option<T> where T: Sized {
51        Rc::into_inner(self.0).map(RefCell::into_inner)
52    }
53
54    /// Immutably borrows the inner `T`, returning an error if the value is currently mutably
55    /// borrowed.
56    ///
57    /// Behaves identically to [`RefCell::try_borrow`].
58    #[inline]
59    fn try_get_ref(&self) -> Result<Self::Ref<'_>, Self::RefError> {
60        self.0.try_borrow()
61    }
62}
63
64impl<T: ?Sized> TryContainer<T> for CheckedRcRefCell<T> {}
65
66impl<T: ?Sized> FragileTryMutContainer<T> for CheckedRcRefCell<T> {
67    type RefMut<'a>  = RefMut<'a, T> where T: 'a;
68    type RefMutError = BorrowMutError;
69
70    /// Mutably borrows the inner `T`, returning an error if the value is currently borrowed.
71    ///
72    /// Behaves identically to [`RefCell::try_borrow_mut`].
73    #[inline]
74    fn try_get_mut(&mut self) -> Result<Self::RefMut<'_>, Self::RefMutError> {
75        self.0.try_borrow_mut()
76    }
77}
78
79impl<T: ?Sized> TryMutContainer<T> for CheckedRcRefCell<T> {}