pub struct TwiceCell<A, B> { /* private fields */ }
Expand description
A cell which can nominally be modified only once.
The main difference between this struct and a OnceCell
is that rather than operating on an Option
,
this type operates on an Either
– meaning methods such as TwiceCell::get_or_init
take a parameter
that can be used to compute the B
value of a TwiceCell
based on its A
value.
For a thread-safe version of this struct, see TwiceLock
.
§Examples
use twice_cell::TwiceCell;
let cell = TwiceCell::new("an initial `A` value for the cell");
assert!(cell.get().is_none());
let value = cell.get_or_init(|s| s.len()); // <- set a `B` value based on the inital `A` value!
assert_eq!(*value, 33);
assert!(cell.get().is_some());
Implementations§
Source§impl<A, B> TwiceCell<A, B>
impl<A, B> TwiceCell<A, B>
Sourcepub fn get(&self) -> Option<&B>
pub fn get(&self) -> Option<&B>
Gets the reference to the underlying value.
Returns None
if the cell hasn’t been set.
Sourcepub fn get_mut(&mut self) -> Option<&mut B>
pub fn get_mut(&mut self) -> Option<&mut B>
Gets the mutable reference to the underlying value.
Returns None
if the cell hasn’t been set.
Sourcepub fn get_either_mut(&mut self) -> Either<&mut A, &mut B> ⓘ
pub fn get_either_mut(&mut self) -> Either<&mut A, &mut B> ⓘ
Gets the mutable reference to either underlying value.
Sourcepub fn set(&self, value: B) -> Result<(), B>
pub fn set(&self, value: B) -> Result<(), B>
Sets the contents of the cell to value
.
§Errors
This method returns Ok(())
if the cell was empty and Err(value)
if
it was full.
§Examples
use twice_cell::TwiceCell;
let cell = TwiceCell::new(0);
assert!(cell.get().is_none());
assert_eq!(cell.set(92), Ok(()));
assert_eq!(cell.set(62), Err(62));
assert!(cell.get().is_some());
Sourcepub fn try_insert(&self, value: B) -> Result<&B, (&B, B)>
pub fn try_insert(&self, value: B) -> Result<&B, (&B, B)>
Sets the contents of the cell to value
if the cell was empty, then
returns a reference to it.
§Errors
This method returns Ok(&value)
if the cell was empty and
Err(¤t_value, value)
if it was full.
§Examples
use twice_cell::TwiceCell;
let cell = TwiceCell::new(0);
assert!(cell.get().is_none());
assert_eq!(cell.try_insert(92), Ok(&92));
assert_eq!(cell.try_insert(62), Err((&92, 62)));
assert!(cell.get().is_some());
Sourcepub fn get_or_init<F>(&self, f: F) -> &B
pub fn get_or_init<F>(&self, f: F) -> &B
Gets the contents of the cell, initializing it with f
if the cell was unset.
§Panics
If f
panics, the panic is propagated to the caller, and the cell
remains uninitialized.
It is an error to reentrantly initialize the cell from f
. Doing
so results in a panic.
§Examples
use twice_cell::TwiceCell;
let cell = TwiceCell::new("hello");
let value = cell.get_or_init(|s| s.len());
assert_eq!(value, &5);
let value = cell.get_or_init(|_| unreachable!());
assert_eq!(value, &5);
Sourcepub fn get_mut_or_init<F>(&mut self, f: F) -> &mut B
pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut B
Gets the mutable reference of the contents of the cell,
initializing it with f
if the cell was unset.
§Panics
If f
panics, the panic is propagated to the caller, and the cell
remains uninitialized.
§Examples
use twice_cell::TwiceCell;
let mut cell = TwiceCell::new("twice_cell");
let value = cell.get_mut_or_init(|s| s.len());
assert_eq!(*value, 10);
*value += 2;
assert_eq!(*value, 12);
let value = cell.get_mut_or_init(|_| unreachable!());
assert_eq!(*value, 12);
Sourcepub fn get_or_try_init<F, E>(&self, f: F) -> Result<&B, E>
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&B, E>
Gets the contents of the cell, initializing it with f
if
the cell was unset.
§Panics
If f
panics, the panic is propagated to the caller, and the cell
remains uninitialized.
It is an error to reentrantly initialize the cell from f
. Doing
so results in a panic.
§Errors
If the cell was unset and f
failed, an
error is returned.
§Examples
use twice_cell::TwiceCell;
let cell = TwiceCell::new(16);
assert_eq!(cell.get_or_try_init(|_| Err(())), Err(()));
assert!(cell.get().is_none());
let value = cell.get_or_try_init(|n| -> Result<i32, ()> {
Ok(n * 4)
});
assert_eq!(value, Ok(&64));
assert_eq!(cell.get(), Some(&64))
Sourcepub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut B, E>
pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut B, E>
Gets the mutable reference of the contents of the cell, initializing
it with f
if the cell was unset.
§Panics
If f
panics, the panic is propagated to the caller, and the cell
remains uninitialized.
§Errors
If the cell was unset and f
failed, an error is returned.
§Examples
use twice_cell::TwiceCell;
let mut cell = TwiceCell::new("not a number!");
// Failed initializers do not change the value
assert!(cell.get_mut_or_try_init(|s| s.parse::<i32>()).is_err());
assert!(cell.get().is_none());
let value = cell.get_mut_or_try_init(|_| "1234".parse());
assert_eq!(value, Ok(&mut 1234));
*value.unwrap() += 2;
assert_eq!(cell.get(), Some(&1236))
Sourcepub fn into_inner(self) -> Either<A, B> ⓘ
pub fn into_inner(self) -> Either<A, B> ⓘ
Consumes the cell, returning the wrapped value.
Returns Either::Left(A)
if the cell was unset.
§Examples
use twice_cell::TwiceCell;
use either::Either;
let cell: TwiceCell<u8, &'static str> = TwiceCell::new(123);
assert_eq!(cell.into_inner(), Either::Left(123));
let cell: TwiceCell<u8, &'static str> = TwiceCell::new(123);
cell.set("hello").unwrap();
assert_eq!(cell.into_inner(), Either::Right("hello"));
Sourcepub fn replace(&mut self, a: A) -> Either<A, B> ⓘ
pub fn replace(&mut self, a: A) -> Either<A, B> ⓘ
Replaces the value in this TwiceCell
, moving it back to an unset state.
Safety is guaranteed by requiring a mutable reference.
§Examples
use twice_cell::TwiceCell;
use either::Either;
let mut cell: TwiceCell<i32, &'static str> = TwiceCell::new(123);
assert_eq!(cell.replace(456), Either::Left(123));
let mut cell = TwiceCell::new(123);
cell.set("goodbye").unwrap();
assert_eq!(cell.replace(456), Either::Right("goodbye"));
assert_eq!(cell.get(), None);
Trait Implementations§
impl<A: Eq, B: Eq> Eq for TwiceCell<A, B>
Auto Trait Implementations§
impl<A, B> !Freeze for TwiceCell<A, B>
impl<A, B> !RefUnwindSafe for TwiceCell<A, B>
impl<A, B> Send for TwiceCell<A, B>
impl<A, B> !Sync for TwiceCell<A, B>
impl<A, B> Unpin for TwiceCell<A, B>
impl<A, B> UnwindSafe for TwiceCell<A, B>where
A: UnwindSafe,
B: UnwindSafe,
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§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more