Skip to main content

Module weak

Module weak 

Source
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 Null flag.
  • Forward references during deserialization — if the strong pointer appears later in the serialized data, the weak will be resolved after deserialization using RefReader callbacks.

§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 UnsafeCell across 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_callback once the strong pointer becomes available.

Structs§

ArcWeak
A serializable wrapper around std::sync::Weak<T> (thread-safe).
RcWeak
A serializable wrapper around std::rc::Weak<T>.