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, Clone, PartialEq, Eq, PartialOrd, Ord)]
24pub struct CheckedRcRefCell<T: ?Sized>(pub Rc<RefCell<T>>);
25
26impl<T: ?Sized> FragileTryContainer<T> for CheckedRcRefCell<T> {
27    type Ref<'a>  = Ref<'a, T> where T: 'a;
28    type RefError = BorrowError;
29
30    #[inline]
31    fn new_container(t: T) -> Self where T: Sized {
32        Self(Rc::new(RefCell::new(t)))
33    }
34
35    /// Attempt to retrieve the inner `T` from the container.
36    /// Behaves identically to [`Rc::into_inner`].
37    #[inline]
38    fn into_inner(self) -> Option<T> where T: Sized {
39        Rc::into_inner(self.0).map(RefCell::into_inner)
40    }
41
42    /// Immutably borrows the inner `T`, returning an error if the value is currently mutably
43    /// borrowed.
44    ///
45    /// Behaves identically to [`RefCell::try_borrow`].
46    #[inline]
47    fn try_get_ref(&self) -> Result<Self::Ref<'_>, Self::RefError> {
48        self.0.try_borrow()
49    }
50}
51
52impl<T: ?Sized> TryContainer<T> for Rc<RefCell<T>> {}
53
54impl<T: ?Sized> FragileTryMutContainer<T> for CheckedRcRefCell<T> {
55    type RefMut<'a>  = RefMut<'a, T> where T: 'a;
56    type RefMutError = BorrowMutError;
57
58    /// Mutably borrows the inner `T`, returning an error if the value is currently borrowed.
59    ///
60    /// Behaves identically to [`RefCell::try_borrow_mut`].
61    #[inline]
62    fn try_get_mut(&mut self) -> Result<Self::RefMut<'_>, Self::RefMutError> {
63        self.0.try_borrow_mut()
64    }
65}
66
67impl<T: ?Sized> TryMutContainer<T> for Rc<RefCell<T>> {}