moonpool_sim/chaos/
state_handle.rs1use std::any::Any;
18use std::cell::RefCell;
19use std::collections::HashMap;
20use std::rc::Rc;
21
22#[derive(Clone, Default)]
27pub struct StateHandle {
28 inner: Rc<RefCell<HashMap<String, Box<dyn Any>>>>,
29}
30
31impl StateHandle {
32 pub fn new() -> Self {
34 Self::default()
35 }
36
37 pub fn publish<T: Any + 'static>(&self, key: &str, value: T) {
39 self.inner
40 .borrow_mut()
41 .insert(key.to_string(), Box::new(value));
42 }
43
44 pub fn get<T: Any + Clone + 'static>(&self, key: &str) -> Option<T> {
48 self.inner
49 .borrow()
50 .get(key)
51 .and_then(|v| v.downcast_ref::<T>())
52 .cloned()
53 }
54
55 pub fn contains(&self, key: &str) -> bool {
57 self.inner.borrow().contains_key(key)
58 }
59}
60
61impl std::fmt::Debug for StateHandle {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 let count = self.inner.borrow().len();
64 f.debug_struct("StateHandle")
65 .field("key_count", &count)
66 .finish()
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn test_publish_and_get() {
76 let state = StateHandle::new();
77 state.publish("count", 42u64);
78 assert_eq!(state.get::<u64>("count"), Some(42));
79 }
80
81 #[test]
82 fn test_get_wrong_type_returns_none() {
83 let state = StateHandle::new();
84 state.publish("count", 42u64);
85 assert_eq!(state.get::<String>("count"), None);
86 }
87
88 #[test]
89 fn test_get_missing_key_returns_none() {
90 let state = StateHandle::new();
91 assert_eq!(state.get::<u64>("missing"), None);
92 }
93
94 #[test]
95 fn test_contains() {
96 let state = StateHandle::new();
97 assert!(!state.contains("key"));
98 state.publish("key", "value".to_string());
99 assert!(state.contains("key"));
100 }
101
102 #[test]
103 fn test_publish_replaces() {
104 let state = StateHandle::new();
105 state.publish("x", 1u64);
106 state.publish("x", 2u64);
107 assert_eq!(state.get::<u64>("x"), Some(2));
108 }
109
110 #[test]
111 fn test_clone_shares_state() {
112 let state = StateHandle::new();
113 let clone = state.clone();
114 state.publish("shared", true);
115 assert_eq!(clone.get::<bool>("shared"), Some(true));
116 }
117}