#[path = "support.rs"]
mod support;
use std::rc::Rc;
use std::sync::Arc;
use noyalib::{AnchorRegistry, ArcAnchorRegistry};
fn main() {
support::header("noyalib -- registry (AnchorRegistry / ArcAnchorRegistry)");
support::task_with_output("Register and resolve values", || {
let mut reg = AnchorRegistry::<String>::new();
let rc = reg.register("greeting".into(), "hello world".into());
let resolved = reg.resolve("greeting").unwrap();
assert_eq!(*resolved, "hello world");
assert!(Rc::ptr_eq(&rc, &resolved));
vec![
format!("registered: greeting = {:?}", *rc),
format!("resolved: greeting = {:?} (same Rc)", *resolved),
]
});
support::task_with_output("Multiple resolves share one allocation (Rc)", || {
let mut reg = AnchorRegistry::<i64>::new();
let original = reg.register("count".into(), 42);
let alias1 = reg.resolve("count").unwrap();
let alias2 = reg.resolve("count").unwrap();
let alias3 = reg.resolve("count").unwrap();
assert!(Rc::ptr_eq(&original, &alias1));
assert!(Rc::ptr_eq(&alias1, &alias2));
assert!(Rc::ptr_eq(&alias2, &alias3));
vec![
format!("Rc strong count = {}", Rc::strong_count(&original)),
format!("All 4 references point to the same heap allocation"),
]
});
support::task_with_output("ArcAnchorRegistry for thread-safe sharing", || {
let mut reg = ArcAnchorRegistry::<String>::new();
let arc = reg.register("shared".into(), "cross-thread data".into());
let alias = reg.resolve("shared").unwrap();
assert!(Arc::ptr_eq(&arc, &alias));
let handle = std::thread::spawn(move || {
assert_eq!(*alias, "cross-thread data");
format!("Thread received: {:?}", *alias)
});
let thread_result = handle.join().unwrap();
vec![
format!("main thread: {:?}", *arc),
thread_result,
format!("Arc::ptr_eq confirmed across threads"),
]
});
support::task_with_output("DAG structure with shared nodes", || {
#[derive(Debug, Clone)]
#[allow(dead_code)]
struct Node {
name: String,
children: Vec<Rc<Node>>,
}
let mut reg = AnchorRegistry::<Node>::new();
let leaf_a = reg.register(
"leaf_a".into(),
Node {
name: "A".into(),
children: vec![],
},
);
let _leaf_b = reg.register(
"leaf_b".into(),
Node {
name: "B".into(),
children: vec![],
},
);
let shared_a = reg.resolve("leaf_a").unwrap();
let shared_b = reg.resolve("leaf_b").unwrap();
let _parent = reg.register(
"parent".into(),
Node {
name: "Parent".into(),
children: vec![shared_a, shared_b],
},
);
let shared_a2 = reg.resolve("leaf_a").unwrap();
let _sibling = reg.register(
"sibling".into(),
Node {
name: "Sibling".into(),
children: vec![shared_a2],
},
);
assert!(Rc::strong_count(&leaf_a) >= 3);
vec![
format!("DAG nodes registered: {}", reg.len()),
format!(
"leaf_a strong_count = {} (shared by parent + sibling)",
Rc::strong_count(&leaf_a)
),
format!("True DAG: no duplication of leaf nodes"),
]
});
support::task_with_output("Clear and reuse registry", || {
let mut reg = AnchorRegistry::<String>::new();
let _ = reg.register("a".into(), "alpha".into());
let _ = reg.register("b".into(), "beta".into());
let _ = reg.register("c".into(), "gamma".into());
assert_eq!(reg.len(), 3);
assert!(!reg.is_empty());
reg.clear();
assert!(reg.is_empty());
assert_eq!(reg.len(), 0);
assert!(reg.resolve("a").is_none());
let _ = reg.register("x".into(), "new value".into());
assert_eq!(reg.len(), 1);
assert!(reg.resolve("x").is_some());
vec![
format!("Registered 3 entries, cleared, then added 1 new"),
format!("Final len = {}", reg.len()),
]
});
support::task("Default constructor starts empty", || {
let reg = AnchorRegistry::<()>::default();
assert!(reg.is_empty());
assert_eq!(reg.len(), 0);
});
support::task("Resolve unknown name returns None", || {
let reg = AnchorRegistry::<String>::new();
assert!(reg.resolve("nonexistent").is_none());
});
support::task_with_output("Overwrite replaces existing entry", || {
let mut reg = AnchorRegistry::<String>::new();
let first = reg.register("key".into(), "first".into());
let second = reg.register("key".into(), "second".into());
let resolved = reg.resolve("key").unwrap();
assert!(!Rc::ptr_eq(&first, &second));
assert!(Rc::ptr_eq(&second, &resolved));
assert_eq!(*resolved, "second");
vec![
format!("first = {:?} (orphaned)", *first),
format!("second = {:?} (current)", *resolved),
]
});
support::summary(8);
}