Crates.io | deferred-cell |
lib.rs | deferred-cell |
version | 0.6.1 |
created_at | 2025-06-30 17:52:12.691152+00 |
updated_at | 2025-06-30 20:29:26.817104+00 |
description | A single-assignment, weak reference wrapper for cyclic node graphs with late initialization |
homepage | https://github.com/BernardIgiri/deferred-cell |
repository | https://github.com/BernardIgiri/deferred-cell |
max_upload_size | |
id | 1732136 |
size | 16,283 |
A single-assignment, weak reference wrapper for cyclic node graphs with write-once, late initialization.
This crate provides a lightweight alternative to RefCell<Option<Weak<T>>>
when building write-once reference graphs, such as cyclic trees, linked lists, and bidirectional or circular structures. It enables you to cleanly and safely establish weak links between nodes after they are constructed.
OnceCell<Weak<T>>
SetOnce
Add to your Cargo.toml
:
[dependencies]
deferred-cell = "0.6"
In Rust, it’s often tricky to build cyclic data structures due to ownership rules. A common workaround is:
RefCell<Option<Weak<T>>>
However, this allows re-assignment and mutation, which is overkill in cases where the weak reference should be set only once. deferred-cell
simplifies this pattern with explicit, single-assignment behavior and no runtime borrow checking.
use deferred_cell::{Deferred, SetOnce, DeferredError};
use std::rc::Rc;
struct Node {
value: String,
neighbor: Deferred<Node>,
}
fn main() -> Result<(), DeferredError> {
let node = Rc::new(Node {
value: "A".into(),
neighbor: Deferred::default(),
});
let neighbor = Rc::new(Node {
value: "B".into(),
neighbor: Deferred::default(),
});
// Assign weak reference after both nodes are constructed
SetOnce::from(&node.neighbor).try_set(&neighbor)?;
// Access the neighbor
let linked = node.neighbor.try_get()?;
assert_eq!(linked.value, "B");
Ok(())
}
let d: Deferred<T> = Deferred::default();
let rc: Rc<T> = ...;
// One-time set
SetOnce::from(&d).try_set(&rc)?;
// Later access
let strong: Rc<T> = d.try_get()?;
// Optional checks
if d.is_ready() { ... }
Also includes a DeferredIteratorExt
trait to streamline iteration:
let values: Vec<_> = list
.into_iter()
.get_deferred()
.map(|rc| rc.value.clone())
.collect();
Two error types are defined:
DeferredError::DuplicateInitialization
– if try_set()
is called more than onceDeferredError::NotInitializedError
– if get()
or try_get()
is called before a value is set