Expand description
Weak pointer serialization support for Rc and Arc.
This module provides RcWeak<T> and ArcWeak<T> wrapper types that integrate
Rust’s std::rc::Weak / std::sync::Weak into the Fory serialization framework,
with full support for:
- Reference identity tracking — weak pointers serialize as references to their corresponding strong pointers, ensuring shared and circular references in the graph are preserved without duplication.
- Null weak pointers — if the strong pointer has been dropped or was never set,
the weak will serialize as a
Nullflag. - Forward references during deserialization — if the strong pointer appears later
in the serialized data, the weak will be resolved after deserialization using
RefReadercallbacks.
§When to use
Use these wrappers when your graph structure contains parent/child relationships or other shared edges where a strong pointer would cause a reference cycle. Storing a weak pointer avoids owning the target strongly, but serialization will preserve the link by reference ID.
§Example — Parent/Child Graph
ⓘ
use fory_core::RcWeak;
use fory_core::Fory;
use std::cell::RefCell;
use std::rc::Rc;
use fory_derive::ForyObject;
#[derive(ForyObject)]
struct Node {
value: i32,
parent: RcWeak<RefCell<Node>>,
children: Vec<Rc<RefCell<Node>>>,
}
let mut fory = Fory::default();
fory.register::<Node>(2000);
let parent = Rc::new(RefCell::new(Node {
value: 1,
parent: RcWeak::new(),
children: vec![],
}));
let child1 = Rc::new(RefCell::new(Node {
value: 2,
parent: RcWeak::from(&parent),
children: vec![],
}));
let child2 = Rc::new(RefCell::new(Node {
value: 3,
parent: RcWeak::from(&parent),
children: vec![],
}));
parent.borrow_mut().children.push(child1);
parent.borrow_mut().children.push(child2);
let serialized = fory.serialize(&parent);
let deserialized: Rc<RefCell<Node>> = fory.deserialize(&serialized).unwrap();
assert_eq!(deserialized.borrow().children.len(), 2);
for child in &deserialized.borrow().children {
let upgraded_parent = child.borrow().parent.upgrade().unwrap();
assert!(Rc::ptr_eq(&deserialized, &upgraded_parent));
}§Example — Arc for Multi-Threaded Graphs
ⓘ
use fory_core::ArcWeak;
use fory_core::Fory;
use std::sync::{Arc, Mutex};
use fory_derive::ForyObject;
#[derive(ForyObject)]
struct Node {
value: i32,
parent: ArcWeak<Mutex<Node>>,
}
let mut fory = Fory::default();
fory.register::<Node>(2001);
let parent = Arc::new(Mutex::new(Node { value: 1, parent: ArcWeak::new() }));
let child = Arc::new(Mutex::new(Node { value: 2, parent: ArcWeak::from(&parent) }));
let serialized = fory.serialize(&child);
let deserialized: Arc<Mutex<Node>> = fory.deserialize(&serialized).unwrap();
assert_eq!(deserialized.lock().unwrap().value, 2);§Notes
- These types share the same
UnsafeCellacross clones, so updating a weak in one clone will update all of them. - During serialization, weak pointers never serialize the target object’s data directly
— they only emit a reference to the already-serialized strong pointer, or
Null. - During deserialization, unresolved references will be patched up by
RefReader::add_callbackonce the strong pointer becomes available.