1use std::any::Any;
16use std::fmt::{Debug, Display};
17use std::hash::Hash;
18use std::sync::{Arc, Weak};
19
20use derive_builder::Builder;
21use parking_lot::RwLock;
22use weak_table::WeakValueHashMap;
23
24use crate::context::{ContextId, Tree, TreeContext};
25use crate::obj_utils::{DynEq, DynHash};
26use crate::{span, Span, TreeRoot};
27
28#[derive(Debug, Clone, Builder)]
31#[builder(default)]
32pub struct Config {
33 verbose: bool,
35}
36
37#[allow(clippy::derivable_impls)]
38impl Default for Config {
39 fn default() -> Self {
40 Self { verbose: false }
41 }
42}
43
44pub trait Key: Hash + Eq + Debug + Send + Sync + 'static {}
49impl<T> Key for T where T: Hash + Eq + Debug + Send + Sync + 'static {}
50
51trait ObjKey: DynHash + DynEq + Debug + Send + Sync + 'static {}
53impl<T> ObjKey for T where T: DynHash + DynEq + Debug + Send + Sync + 'static {}
54
55pub trait ToRootSpan {
58 fn to_root_span(&self) -> Span;
60}
61
62impl<T: Display> ToRootSpan for T {
63 fn to_root_span(&self) -> Span {
64 span!("{self}")
65 }
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
70struct AnonymousKey(ContextId);
71
72impl Display for AnonymousKey {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 write!(f, "Anonymous #{}", self.0 .0)
75 }
76}
77
78#[derive(Clone)]
80pub struct AnyKey(Arc<dyn ObjKey>);
81
82impl PartialEq for AnyKey {
83 fn eq(&self, other: &Self) -> bool {
84 self.0.dyn_eq(other.0.as_dyn_eq())
85 }
86}
87
88impl Eq for AnyKey {}
89
90impl Hash for AnyKey {
91 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
92 self.0.dyn_hash(state);
93 }
94}
95
96impl Debug for AnyKey {
97 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 self.0.fmt(f)
99 }
100}
101
102impl Display for AnyKey {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 macro_rules! delegate_to_display {
106 ($($t:ty),* $(,)?) => {
107 $(
108 if let Some(k) = self.as_any().downcast_ref::<$t>() {
109 return write!(f, "{}", k);
110 }
111 )*
112 };
113 }
114 delegate_to_display!(String, &str, AnonymousKey);
115
116 write!(f, "{:?}", self)
117 }
118}
119
120impl AnyKey {
121 fn new(key: impl ObjKey) -> Self {
122 Self(Arc::new(key))
123 }
124
125 pub fn as_any(&self) -> &dyn Any {
127 self.0.as_ref().as_any()
128 }
129
130 pub fn is<K: Any>(&self) -> bool {
134 self.as_any().is::<K>()
135 }
136
137 pub fn is_anonymous(&self) -> bool {
139 self.as_any().is::<AnonymousKey>()
140 }
141
142 pub fn downcast_ref<K: Any>(&self) -> Option<&K> {
146 self.as_any().downcast_ref()
147 }
148}
149
150type Contexts = RwLock<WeakValueHashMap<AnyKey, Weak<TreeContext>>>;
151
152struct RegistryCore {
153 contexts: Contexts,
154 config: Config,
155}
156
157pub struct Registry(Arc<RegistryCore>);
161
162impl Debug for Registry {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 f.debug_struct("Registry")
165 .field("config", self.config())
166 .finish_non_exhaustive()
167 }
168}
169
170impl Clone for Registry {
171 fn clone(&self) -> Self {
172 Self(Arc::clone(&self.0))
173 }
174}
175
176impl Registry {
177 fn contexts(&self) -> &Contexts {
178 &self.0.contexts
179 }
180
181 fn config(&self) -> &Config {
182 &self.0.config
183 }
184}
185
186impl Registry {
187 pub fn new(config: Config) -> Self {
189 Self(
190 RegistryCore {
191 contexts: Default::default(),
192 config,
193 }
194 .into(),
195 )
196 }
197
198 pub fn try_current() -> Option<Self> {
206 crate::root::current_registry()
207 }
208
209 pub fn current() -> Self {
213 Self::try_current().expect("no current registry")
214 }
215
216 fn register_inner(&self, key: impl Key, context: Arc<TreeContext>) -> TreeRoot {
217 self.contexts()
218 .write()
219 .insert(AnyKey::new(key), Arc::clone(&context));
220
221 TreeRoot {
222 context,
223 registry: WeakRegistry(Arc::downgrade(&self.0)),
224 }
225 }
226
227 pub fn register(&self, key: impl Key, root_span: impl Into<Span>) -> TreeRoot {
233 let context = Arc::new(TreeContext::new(root_span.into(), self.config().verbose));
234 self.register_inner(key, context)
235 }
236
237 pub fn register_derived_root(&self, key: impl Key + ToRootSpan) -> TreeRoot {
242 let root_span = key.to_root_span();
243 self.register(key, root_span)
244 }
245
246 pub fn register_anonymous(&self, root_span: impl Into<Span>) -> TreeRoot {
254 let context = Arc::new(TreeContext::new(root_span.into(), self.config().verbose));
255 self.register_inner(AnonymousKey(context.id()), context) }
257
258 pub fn get(&self, key: impl Key) -> Option<Tree> {
262 self.contexts()
263 .read()
264 .get(&AnyKey::new(key)) .map(|v| v.tree().clone())
266 }
267
268 pub fn clear(&self) {
270 self.contexts().write().clear();
271 }
272
273 pub fn collect<K: Key + Clone>(&self) -> Vec<(K, Tree)> {
275 self.contexts()
276 .read()
277 .iter()
278 .filter_map(|(k, v)| {
279 k.0.as_ref()
280 .as_any()
281 .downcast_ref::<K>()
282 .map(|k| (k.clone(), v.tree().clone()))
283 })
284 .collect()
285 }
286
287 pub fn collect_anonymous(&self) -> Vec<Tree> {
289 self.contexts()
290 .read()
291 .iter()
292 .filter_map(|(k, v)| {
293 if k.is_anonymous() {
294 Some(v.tree().clone())
295 } else {
296 None
297 }
298 })
299 .collect()
300 }
301
302 pub fn collect_all(&self) -> Vec<(AnyKey, Tree)> {
304 self.contexts()
305 .read()
306 .iter()
307 .map(|(k, v)| (k.clone(), v.tree().clone()))
308 .collect()
309 }
310}
311
312pub(crate) struct WeakRegistry(Weak<RegistryCore>);
313
314impl WeakRegistry {
315 pub fn upgrade(&self) -> Option<Registry> {
316 self.0.upgrade().map(Registry)
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 use super::*;
323
324 #[test]
325 fn test_registry() {
326 let registry = Registry::new(Config::default());
327
328 let _0_i32 = registry.register(0_i32, "0");
329 let _1_i32 = registry.register(1_i32, "1");
330 let _2_i32 = registry.register(2_i32, "2");
331
332 let _0_str = registry.register("0", "0");
333 let _1_str = registry.register("1", "1");
334
335 let _unit = registry.register((), "()");
336 let _unit_replaced = registry.register((), "[]");
337
338 let _anon = registry.register_anonymous("anon");
339 let _anon = registry.register_anonymous("anon");
340
341 let i32s = registry.collect::<i32>();
342 assert_eq!(i32s.len(), 3);
343
344 let strs = registry.collect::<&'static str>();
345 assert_eq!(strs.len(), 2);
346
347 let units = registry.collect::<()>();
348 assert_eq!(units.len(), 1);
349
350 let anons = registry.collect_anonymous();
351 assert_eq!(anons.len(), 2);
352
353 let all = registry.collect_all();
354 assert_eq!(all.len(), 8);
355 }
356}