Crate mucell [] [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<str> or Cow<[T]>, 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 Vec<i32>, &*b as *const Vec<i32>);
}

// 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.

Structs

MuCell

A cell with the ability to mutate the value through an immutable reference when safe.

Ref

An immutable reference to a MuCell. Normally you should dereference to get at the object, but after transformation with Ref::map or Ref::filter_map you might instead use .into_inner().