pub struct SlotCell<T> { /* private fields */ }Expand description
A cell type that enforces borrowing semantics (take/put) for interior mutability.
SlotCell<T> wraps a value that can be temporarily “taken out” and later “put back”.
This is useful for scenarios where you need to move a value out of a structure temporarily,
perform operations on it, and then return it. In practice SlotCell fills the same role as
RefCell and acts more like a “lockless mutex”, while:
- Since backed by a simple
Cell- Potentially more memory efficient depending on alignment
- Faster for small stack values (1 register, <= 8 bytes)
- Comparable for medium stack values (2 - 3 registers, <= 24 bytes)
- Slower for large stack values (Consider
RefCellor moving data to heap if performance is the main concern)
- allowing owned access.
Unlike Cell<T> or Cell<Option<T>>:
Tdoes not need to implementCopy/Clone/Default, or a separateTneeded, to take the value out.- Implements
Debug,PartialEq,Eq,PartialOrd,Ord,Hash, andDefaultifTdoes. - Does not implement
CloneorCopy, or requireTto beCloneorCopyfor certain operations. - Enforces a correct usage patterns that mimics “borrow semantics” with a runtime check.
Unlike RefCell<T>:
- No borrow counting is used
- Owned values rather references are returned
- No multiple read references
High level
- Owned values are used over guards with references/lifetimes. Thus, it is up to the programmer to follow semantics around taking and returning values or it will panic otherwise.
- A value can only be taken once (until put back)
- A value can only be put back when the slot is empty
- A value can only be replaced when not already empty
In debug builds, SlotCell tracks the location of the last modification, providing
helpful panic messages when usage rules are violated.
§Examples
let cell = SlotCell::new(42);
let value = cell.take();
assert_eq!(value, 42);
// Put the value back
cell.put(100);
// Take it again
let value = cell.take();
assert_eq!(value, 100);§Panics
This type will panic if usage rules are violated (taking when empty, putting when full, etc.). In debug builds, panic messages include the location of the last modification.
Implementations§
Source§impl<T> SlotCell<T>
impl<T> SlotCell<T>
Sourcepub fn new(val: T) -> Self
pub fn new(val: T) -> Self
Creates a new SlotCell containing the given value.
§Examples
let cell = SlotCell::new(42);
assert!(!cell.is_empty());Sourcepub fn empty() -> Self
pub fn empty() -> Self
Creates a new SlotCell that starts empty (without a value).
This is useful for late initialization patterns where the value
will be provided later via put().
§Examples
let cell: SlotCell<i32> = SlotCell::empty();
assert!(cell.is_empty());
cell.put(42);
assert!(!cell.is_empty());Sourcepub fn take(&self) -> T
pub fn take(&self) -> T
Takes the value out of the cell, leaving it empty.
After calling this method, the cell will be empty until put() is called.
§Panics
Panics if the slot is already empty. In debug builds, the panic message includes the location of the last modification.
§Examples
let cell = SlotCell::new(42);
let value = cell.take();
assert_eq!(value, 42);Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Checks whether the slot is currently empty.
Returns true if the cell currently empty, false if it’s filled.
§Examples
let cell = SlotCell::new(42);
assert!(!cell.is_empty()); // Has value, not taken
let _value = cell.take();
assert!(cell.is_empty()); // Now empty/takenSourcepub fn is_filled(&self) -> bool
pub fn is_filled(&self) -> bool
Checks whether the slot is currently empty.
Returns true if the cell currently contains a value, false if it’s empty.
§Examples
let cell = SlotCell::new(42);
assert!(cell.is_filled()); // Has value, not taken
let _value = cell.take();
assert!(!cell.is_filled()); // Now empty/takenSourcepub fn put(&self, val: T)
pub fn put(&self, val: T)
Puts a value into the cell, filling an empty slot.
This is used to return a value that was previously removed via take(),
or to initialize a cell created with empty().
§Panics
Panics if the slot is already filled. SlotCell enforces that a value
must be taken before a new one can be put back. In debug builds,
the panic message includes the location of the last modification.
§Examples
let cell = SlotCell::empty();
cell.put(42); // Initialize empty slot
let _ = cell.take();
cell.put(100); // Put back after takingSourcepub fn replace(&self, val: T) -> T
pub fn replace(&self, val: T) -> T
Replaces the current value in the cell with a new one.
Unlike put(), this method requires the cell to currently contain a value.
It is used to update the contents without changing the “filled” state
of the slot.
§Panics
Panics if the slot is already empty. To fill an empty cell,
use put() instead. In debug builds, the panic message includes the
location of the last modification.
§Examples
let cell = SlotCell::new(42);
cell.replace(100);
assert_eq!(cell.take(), 100);Sourcepub fn swap(&self, other: &Self)
pub fn swap(&self, other: &Self)
Swaps the values between two full SlotCells.
This efficiently exchanges the contents of self and other without
requiring an intermediate take() or put() call.
§Panics
Panics if either self or other is currently empty. In debug
builds, the panic message includes the location of the last modification
for the empty cell.
§Examples
let cell_a = SlotCell::new(1);
let cell_b = SlotCell::new(2);
cell_a.swap(&cell_b);
assert_eq!(cell_a.take(), 2);
assert_eq!(cell_b.take(), 1);Sourcepub fn with<R>(&self, f: impl FnOnce(&mut T) -> R) -> R
pub fn with<R>(&self, f: impl FnOnce(&mut T) -> R) -> R
Executes a closure with a mutable reference to the value inside the cell.
This method provides a way to modify the contents of the SlotCell or perform
operations on it without needing to manually call take() and put().
Because SlotCell works by moving values, this method internally takes the
value out of the cell, passes it to your closure, and automatically puts
it back once the closure returns.
§Panics
Panics if the cell is currently empty or if already filled when attempting to return the value. In debug builds, the panic message includes the location of the last modification.
§Examples
let cell = SlotCell::new(String::from("Hello"));
cell.with(|s| {
s.push_str(", World!");
});
assert_eq!(cell.into_inner(), "Hello, World!");It can also return a value from the closure:
let cell = SlotCell::new(10);
let is_even = cell.with(|x| *x % 2 == 0);
assert!(is_even);Sourcepub fn update(&self, f: impl FnOnce(T) -> T)
pub fn update(&self, f: impl FnOnce(T) -> T)
Updates the value inside the cell by applying a transformation function.
This method takes ownership of the value, passes it to the closure, and puts the result back into the cell.
Unlike with, which provides a mutable reference, update
allows you to consume the value and return a new one of the same type.
§Panics
Panics if the cell is currently empty or if already filled when attempting to return the value. In debug builds, the panic message includes the location of the last modification.
§Examples
let cell = SlotCell::new(5);
// Multiply the value by 2
cell.update(|v| v * 2);
assert_eq!(cell.take(), 10);It can also be used to swap out owned data like a String or Vec:
let cell = SlotCell::new(vec![1, 2, 3]);
cell.update(|mut v| {
v.push(4);
v
});
assert_eq!(cell.into_inner().len(), 4);