Crate mucellUnstable [stability]
[-]
[+]
[src]
A cell with the ability to mutate the value through an immutable reference when safe.
Comparison with RefCell
RefCell
goes for completely runtime checking, having try_borrow
, try_borrow_mut
,
borrow
and borrow_mut
all taking &self
and using custom reference types everywhere.
MuCell
(out of pity and the fact that “non-ascii idents are not fully supported” I did not
name it ΜCell
with the crate named µcell
) makes much more use of true Rust borrow checking
for a result that is more efficient and has no possibility of panicking.
However, its purpose is not the same as RefCell
; it is designed specifically for cases where
something only needs an immutable reference, but where being able to safely take a mutable
reference can improve efficiency. Say, for example, where it’s beneficial to be able to cache
the result of a calculation, but you don’t really want to need to do that.
The purpose of all of this is for an accessor for a T
that can be made more efficient if it
can have &mut self
, but doesn’t strictly require it. For this reason, it’s often going to be
paired with std::borrow::Cow
, e.g.
Cow<String, str>
(a.k.a. std::str::CowString
) or Cow<Vec<T>, [T]>
(a.k.a.
std::vec::CowVec
), producing Borrowed
if you are able to mutate the value or Owned
of the
same data if not.
Examples
This example covers most of the surface area of the library:
let mut cell = MuCell::new(vec![1, 2, 3]); // You can borrow from the cell mutably at no cost. cell.borrow_mut().push(4); // You can borrow immutably, too, and it’s very cheap. // (Rust’s standard borrow checking prevents you from doing // this while there’s a mutable reference taken out.) assert_eq!(&*cell.borrow(), &[1, 2, 3, 4]); // So long as there are no active borrows, // try_mutate can be used to mutate the value. assert!(cell.try_mutate(|x| x.push(5))); assert_eq!(&*cell.borrow(), &[1, 2, 3, 4, 5]); // But when there is an immutable borrow active, // try_mutate says no. let b = cell.borrow(); assert!(!cell.try_mutate(|_| unreachable!())); drop(b); // We can have many immutable borrows at a time, too. { let a = cell.borrow(); let b = cell.borrow(); let c = cell.borrow(); assert_eq!(&*a as *const _, &*b as *const _); } // Once they’re all cleared, try_mutate is happy again. assert!(cell.try_mutate(|x| x.push(6))); assert_eq!(&*cell.borrow(), &[1, 2, 3, 4, 5, 6]);
Look at the examples in the repository for some slightly more practical (though still typically contrived) examples. Also see the mucell_ref_type! docs for an example of that part of the library.
Macros
mucell_ref_type! | Create a new reference type to something inside the cell. |
Structs
MuCell | A cell with the ability to mutate the value through an immutable reference when safe |
Ref | An immutable reference to a |