use std::any::Any;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
#[derive(Clone, Default)]
struct Kept(Rc<RefCell<HashMap<&'static str, Rc<dyn Any>>>>);
pub fn kept<T: Clone + 'static>(key: &'static str, init: impl FnOnce() -> T) -> T {
let store = match services_core::try_inject::<Kept>() {
Some(store) => store,
None => {
let store = Kept::default();
let _ = services_core::provide(store.clone());
store
}
};
let existing = store
.0
.borrow()
.get(key)
.and_then(|value| Rc::clone(value).downcast::<T>().ok());
if let Some(value) = existing {
return (*value).clone();
}
let value = init();
store
.0
.borrow_mut()
.insert(key, Rc::new(value.clone()) as Rc<dyn Any>);
value
}
#[cfg(test)]
mod tests {
use super::*;
use reactive_core::signal;
use services_core::Scope;
#[test]
fn a_second_build_reads_back_what_the_first_one_kept() {
Scope::with(|| {
let first = kept("test.query", || signal(String::new()));
first.set("telar".to_string());
let second = kept("test.query", || signal(String::new()));
assert_eq!(
second.peek(),
"telar",
"the rebuilt tree subscribes to the signal the old one was writing, not to a fresh one"
);
assert_eq!(
kept("test.other", || signal(String::new())).peek(),
"",
"and a different key is a different value"
);
});
}
#[test]
fn one_surfaces_state_is_not_another_surfaces() {
let first = Scope::with(|| kept("test.page", || signal(3usize)).peek());
let second = Scope::with(|| kept("test.page", || signal(0usize)).peek());
assert_eq!((first, second), (3, 0));
}
}