pub struct MuCell<T: ?Sized> { /* private fields */ }Expand description
A cell with the ability to mutate the value through an immutable reference when safe.
Implementations§
source§impl<T> MuCell<T>
impl<T> MuCell<T>
sourcepub fn new(value: T) -> MuCell<T>
pub fn new(value: T) -> MuCell<T>
Examples found in repository?
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
fn main() {
// Having these cells as the values in a map is about the most common mode of usage for this
// library that I can think of.
let mut items = HashMap::new();
items.insert("foo", MuCell::new(Inner::new(vec![1, 2, 3])));
items.insert("bar", MuCell::new(Inner::new(vec![4, 5, 6])));
items.insert("baz", MuCell::new(Inner::new(vec![7, 8, 9])));
// foo and baz can be unborrowed, but bar can be borrowed.
let _active_borrow = items.get("bar").unwrap().borrow();
let item = items.get("foo").unwrap();
// First of all, we see—can we ensure that we have the munged version, in place? If we can,
// that will make retrieving the munged version multiple times (provided `set` is not called in
// between) more efficient, as it will only need to do the work once. Because the
// `Ref::map(item.borrow(), item.munged())` is operating on the Cow basis and doesn’t *need*
// `munge` to have been called, it’s fine if this mutation doesn’t actually happen.
item.try_mutate(|x| x.munge());
// In this particular case, we know it’s done it.
item.borrow().assert_munged_exists();
// Whether it had happened or not, this part is definitely true:
let a = Ref::map(item.borrow(), |inner| inner.munged());
assert_eq!(&*a, [2, 3, 4]);
// Now suppose we do the same for bar, which has been borrowed.
let item = items.get(&"bar").unwrap();
// This time, try_mutate will *not* do the munging.
item.try_mutate(|x| x.munge());
item.borrow().assert_munged_does_not_exist();
// … but the munged() Cow is still just fine.
let a = Ref::map(item.borrow(), |inner| inner.munged());
assert_eq!(&*a, [5, 6, 7]);
// With another map call and an into_inner(), we can get the value out of
// it without cloning it all if it’s already Cow::Owned. Efficiency, yay!
let _munged: Vec<i32> = Ref::map(a, |a| a.into_owned()).into_inner();
}sourcepub fn into_inner(self) -> T
pub fn into_inner(self) -> T
Consumes the MuCell, returning the wrapped value.
§Examples
use mucell::MuCell;
let c = MuCell::new(5);
let five = c.into_inner();source§impl<T: ?Sized> MuCell<T>
impl<T: ?Sized> MuCell<T>
sourcepub fn borrow(&self) -> Ref<'_, &T>
pub fn borrow(&self) -> Ref<'_, &T>
Immutably borrows the wrapped value.
The borrow lasts until the returned Ref exits scope.
Multiple immutable borrows can be taken out at the same time.
§Panics
Panics if called inside the try_mutate() mutator function.
But that’s generally a nonsensical thing to do, anyway, so just be sensible and you’re OK.
Examples found in repository?
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
fn main() {
// Having these cells as the values in a map is about the most common mode of usage for this
// library that I can think of.
let mut items = HashMap::new();
items.insert("foo", MuCell::new(Inner::new(vec![1, 2, 3])));
items.insert("bar", MuCell::new(Inner::new(vec![4, 5, 6])));
items.insert("baz", MuCell::new(Inner::new(vec![7, 8, 9])));
// foo and baz can be unborrowed, but bar can be borrowed.
let _active_borrow = items.get("bar").unwrap().borrow();
let item = items.get("foo").unwrap();
// First of all, we see—can we ensure that we have the munged version, in place? If we can,
// that will make retrieving the munged version multiple times (provided `set` is not called in
// between) more efficient, as it will only need to do the work once. Because the
// `Ref::map(item.borrow(), item.munged())` is operating on the Cow basis and doesn’t *need*
// `munge` to have been called, it’s fine if this mutation doesn’t actually happen.
item.try_mutate(|x| x.munge());
// In this particular case, we know it’s done it.
item.borrow().assert_munged_exists();
// Whether it had happened or not, this part is definitely true:
let a = Ref::map(item.borrow(), |inner| inner.munged());
assert_eq!(&*a, [2, 3, 4]);
// Now suppose we do the same for bar, which has been borrowed.
let item = items.get(&"bar").unwrap();
// This time, try_mutate will *not* do the munging.
item.try_mutate(|x| x.munge());
item.borrow().assert_munged_does_not_exist();
// … but the munged() Cow is still just fine.
let a = Ref::map(item.borrow(), |inner| inner.munged());
assert_eq!(&*a, [5, 6, 7]);
// With another map call and an into_inner(), we can get the value out of
// it without cloning it all if it’s already Cow::Owned. Efficiency, yay!
let _munged: Vec<i32> = Ref::map(a, |a| a.into_owned()).into_inner();
}sourcepub fn borrow_mut(&mut self) -> &mut T
pub fn borrow_mut(&mut self) -> &mut T
Mutably borrows the wrapped value.
Unlike RefCell.borrow_mut, this method lets Rust’s type system prevent aliasing
and so cannot have anything go wrong. It is also, in consequence, completely free,
unlike RefCell or MuCell.borrow which all have to keep track of borrows at runtime.
sourcepub fn try_mutate<F: FnOnce(&mut T)>(&self, mutator: F) -> bool
pub fn try_mutate<F: FnOnce(&mut T)>(&self, mutator: F) -> bool
Mutate the contained object if possible.
If any immutable references produced by calling borrow() are active,
this will return false, not executing the function given.
If there are no immutable references active, this will execute the mutator function and return true.
The mutator function should not touch self (not that it would really
make much sense to be touching it, anyway); most notably, you may not call borrow on
self inside the mutator, which includes things like the == implementation which borrow
the value briefly; while calling try_mutate inside it will just return false, calling
borrow will panic.
Examples found in repository?
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
fn main() {
// Having these cells as the values in a map is about the most common mode of usage for this
// library that I can think of.
let mut items = HashMap::new();
items.insert("foo", MuCell::new(Inner::new(vec![1, 2, 3])));
items.insert("bar", MuCell::new(Inner::new(vec![4, 5, 6])));
items.insert("baz", MuCell::new(Inner::new(vec![7, 8, 9])));
// foo and baz can be unborrowed, but bar can be borrowed.
let _active_borrow = items.get("bar").unwrap().borrow();
let item = items.get("foo").unwrap();
// First of all, we see—can we ensure that we have the munged version, in place? If we can,
// that will make retrieving the munged version multiple times (provided `set` is not called in
// between) more efficient, as it will only need to do the work once. Because the
// `Ref::map(item.borrow(), item.munged())` is operating on the Cow basis and doesn’t *need*
// `munge` to have been called, it’s fine if this mutation doesn’t actually happen.
item.try_mutate(|x| x.munge());
// In this particular case, we know it’s done it.
item.borrow().assert_munged_exists();
// Whether it had happened or not, this part is definitely true:
let a = Ref::map(item.borrow(), |inner| inner.munged());
assert_eq!(&*a, [2, 3, 4]);
// Now suppose we do the same for bar, which has been borrowed.
let item = items.get(&"bar").unwrap();
// This time, try_mutate will *not* do the munging.
item.try_mutate(|x| x.munge());
item.borrow().assert_munged_does_not_exist();
// … but the munged() Cow is still just fine.
let a = Ref::map(item.borrow(), |inner| inner.munged());
assert_eq!(&*a, [5, 6, 7]);
// With another map call and an into_inner(), we can get the value out of
// it without cloning it all if it’s already Cow::Owned. Efficiency, yay!
let _munged: Vec<i32> = Ref::map(a, |a| a.into_owned()).into_inner();
}Trait Implementations§
source§impl<T: Ord> Ord for MuCell<T>
impl<T: Ord> Ord for MuCell<T>
source§impl<T: ?Sized + PartialEq> PartialEq for MuCell<T>
impl<T: ?Sized + PartialEq> PartialEq for MuCell<T>
source§impl<T: PartialOrd> PartialOrd for MuCell<T>
impl<T: PartialOrd> PartialOrd for MuCell<T>
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self and other) and is used by the <=
operator. Read moreimpl<T: ?Sized + Eq> Eq for MuCell<T>
impl<T> Send for MuCell<T>
Auto Trait Implementations§
impl<T> !Freeze for MuCell<T>
impl<T> !RefUnwindSafe for MuCell<T>
impl<T> !Sync for MuCell<T>
impl<T> Unpin for MuCell<T>
impl<T> UnwindSafe for MuCell<T>where
T: UnwindSafe + ?Sized,
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit)