1use alloc::{boxed::Box, collections::BTreeMap, rc::Rc, vec::Vec};
26use core::{
27 any::{Any, TypeId, type_name},
28 cell::RefCell,
29 fmt::Debug,
30 num::NonZeroUsize,
31};
32
33use crate::observe::{self, Origin};
34
35#[derive(Debug, Default, Clone)]
40pub struct Metadata(Box<MetadataInner>);
41
42#[derive(Debug, Default, Clone)]
46struct MetadataInner(BTreeMap<TypeId, Rc<dyn Any>>);
47
48impl MetadataInner {
49 pub fn try_get<T: 'static + Clone>(&self) -> Option<T> {
53 self.0
55 .get(&TypeId::of::<T>())
56 .and_then(|value| value.downcast_ref::<T>())
57 .cloned()
58 }
59
60 pub fn insert<T: 'static + Clone>(&mut self, value: T) {
64 self.0.insert(TypeId::of::<T>(), Rc::new(value));
68 }
69}
70
71pub type Watcher<T> = Rc<dyn Fn(Context<T>) + 'static>;
73
74#[derive(Debug, Clone)]
76pub struct Context<T> {
77 value: T,
79 metadata: Metadata,
81}
82
83impl<T> Context<T> {
84 pub const fn new(value: T, metadata: Metadata) -> Self {
86 Self { value, metadata }
87 }
88
89 #[must_use]
91 pub fn with<V: Clone + 'static>(mut self, value: V) -> Self {
92 self.metadata = self.metadata.with(value);
93 self
94 }
95
96 pub fn into_value(self) -> T {
98 self.value
99 }
100
101 pub const fn value(&self) -> &T {
103 &self.value
104 }
105
106 pub const fn value_mut(&mut self) -> &mut T {
108 &mut self.value
109 }
110
111 pub const fn metadata(&self) -> &Metadata {
113 &self.metadata
114 }
115
116 pub const fn metadata_mut(&mut self) -> &mut Metadata {
118 &mut self.metadata
119 }
120
121 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Context<U> {
123 Context::new(f(self.value), self.metadata)
124 }
125
126 pub fn as_ref(&self) -> Context<&T> {
128 Context::new(&self.value, self.metadata.clone())
129 }
130
131 pub fn as_mut(&mut self) -> Context<&mut T> {
133 Context::new(&mut self.value, self.metadata.clone())
134 }
135
136 pub fn as_deref(&self) -> Context<&T::Target>
138 where
139 T: core::ops::Deref,
140 {
141 Context::new(&*self.value, self.metadata.clone())
142 }
143
144 pub fn as_deref_mut(&mut self) -> Context<&mut T::Target>
146 where
147 T: core::ops::DerefMut,
148 {
149 Context::new(&mut *self.value, self.metadata.clone())
150 }
151}
152
153impl<T> From<T> for Context<T> {
154 fn from(value: T) -> Self {
155 Self::new(value, Metadata::new())
156 }
157}
158
159#[must_use]
161pub trait WatcherGuard: 'static {}
162
163impl<T: 'static> WatcherGuard for Option<T> {}
164
165impl<T: WatcherGuard, E: WatcherGuard> WatcherGuard for Result<T, E> {}
166
167impl WatcherGuard for () {}
168
169impl<T1: WatcherGuard, T2: WatcherGuard> WatcherGuard for (T1, T2) {}
170
171#[derive(Debug)]
173pub struct OnDrop<F>(Option<F>)
174where
175 F: FnOnce();
176
177impl<F> OnDrop<F>
178where
179 F: FnOnce() + 'static,
180{
181 pub const fn new(f: F) -> Self {
183 Self(Some(f))
184 }
185
186 #[allow(clippy::needless_pass_by_value)]
188 pub fn attach(guard: impl WatcherGuard, f: F) -> impl WatcherGuard {
189 OnDrop::new(move || {
190 let _ = guard;
191 f();
192 })
193 }
194}
195
196impl<F> Drop for OnDrop<F>
197where
198 F: FnOnce(),
199{
200 fn drop(&mut self) {
201 let Some(callback) = self.0.take() else {
202 panic!("OnDrop::drop called with missing callback");
203 };
204 callback();
205 }
206}
207
208pub type BoxWatcherGuard = Box<dyn WatcherGuard>;
210
211impl<T: WatcherGuard + ?Sized> WatcherGuard for Box<T> {}
212impl<T: WatcherGuard + ?Sized> WatcherGuard for Rc<T> {}
213
214impl<F: FnOnce() + 'static> WatcherGuard for OnDrop<F> {}
215
216impl Metadata {
217 #[must_use]
219 pub fn new() -> Self {
220 Self::default()
221 }
222
223 #[must_use]
229 pub fn get<T: 'static + Clone>(&self) -> T {
230 self.try_get()
231 .unwrap_or_else(|| panic!("Metadata::get missing value for requested type"))
232 }
233
234 #[must_use]
238 pub fn try_get<T: 'static + Clone>(&self) -> Option<T> {
239 self.0.try_get()
240 }
241
242 #[must_use]
246 pub fn with<T: 'static + Clone>(mut self, value: T) -> Self {
247 self.0.insert(value);
248 self
249 }
250
251 #[must_use]
253 pub fn is_empty(&self) -> bool {
254 self.0.0.is_empty()
255 }
256}
257
258pub(crate) type WatcherId = NonZeroUsize;
260
261#[derive(Debug)]
265pub struct WatcherManager<T> {
266 inner: Rc<RefCell<WatcherManagerInner<T>>>,
267}
268
269impl<T> Clone for WatcherManager<T> {
270 fn clone(&self) -> Self {
271 Self {
272 inner: self.inner.clone(),
273 }
274 }
275}
276
277impl<T> Default for WatcherManager<T> {
278 fn default() -> Self {
279 Self {
280 inner: Rc::default(),
281 }
282 }
283}
284
285impl<T: 'static> WatcherManager<T> {
286 #[must_use]
288 pub fn new() -> Self {
289 Self::default()
290 }
291
292 #[must_use]
299 pub fn with_origin(origin: Origin) -> Self {
300 observe::on_create(origin);
301 Self {
302 inner: Rc::new(RefCell::new(WatcherManagerInner::with_origin(origin))),
303 }
304 }
305
306 #[must_use]
308 pub fn is_empty(&self) -> bool {
309 self.inner.borrow().is_empty()
310 }
311
312 pub fn register(&self, watcher: impl Fn(Context<T>) + 'static) -> WatcherId {
314 let (id, origin, subscribers) = {
315 let mut inner = self.inner.borrow_mut();
316 let id = inner.register(watcher);
317 (id, inner.origin, inner.len())
318 };
319 observe::on_subscribe(origin, subscribers);
320 id
321 }
322
323 pub fn register_as_guard(
325 &self,
326 watcher: impl Fn(Context<T>) + 'static,
327 ) -> WatcherManagerGuard<T> {
328 let id = self.register(watcher);
329 let this = self.clone();
330 WatcherManagerGuard { manager: this, id }
331 }
332
333 pub fn notify(&self, ctx: &Context<T>)
335 where
336 T: Clone,
337 {
338 let (watchers, origin) = {
339 let inner = self.inner.borrow();
340 (inner.watchers_snapshot(), inner.origin)
341 };
342
343 if watchers.is_empty() {
344 return;
345 }
346
347 observe::on_notify(origin, watchers.len());
348
349 for watcher in watchers {
350 watcher(ctx.clone());
351 }
352 }
353
354 pub fn cancel(&self, id: WatcherId) {
356 let (origin, subscribers) = {
357 let mut inner = self.inner.borrow_mut();
358 inner.cancel(id);
359 (inner.origin, inner.len())
360 };
361 observe::on_unsubscribe(origin, subscribers);
362 }
363}
364
365#[must_use]
367#[derive(Debug)]
368pub struct WatcherManagerGuard<T: 'static> {
369 manager: WatcherManager<T>,
370 id: WatcherId,
371}
372
373impl<T> WatcherGuard for WatcherManagerGuard<T> {}
374
375impl<T: 'static> Drop for WatcherManagerGuard<T> {
376 fn drop(&mut self) {
377 self.manager.cancel(self.id);
378 }
379}
380
381struct WatcherManagerInner<T> {
385 id: WatcherId,
386 map: BTreeMap<WatcherId, Watcher<T>>,
387 origin: Origin,
388}
389
390impl<T> Debug for WatcherManagerInner<T> {
391 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
392 f.write_str(type_name::<Self>())
393 }
394}
395
396impl<T> Default for WatcherManagerInner<T> {
397 fn default() -> Self {
398 Self {
399 id: WatcherId::MIN,
400 map: BTreeMap::new(),
401 origin: Origin::default(),
402 }
403 }
404}
405
406impl<T> Drop for WatcherManagerInner<T> {
407 fn drop(&mut self) {
408 observe::on_drop(self.origin);
409 }
410}
411
412impl<T: 'static> WatcherManagerInner<T> {
413 fn with_origin(origin: Origin) -> Self {
415 Self {
416 id: WatcherId::MIN,
417 map: BTreeMap::new(),
418 origin,
419 }
420 }
421
422 pub fn is_empty(&self) -> bool {
424 self.map.is_empty()
425 }
426
427 fn len(&self) -> usize {
429 self.map.len()
430 }
431
432 const fn assign(&mut self) -> WatcherId {
434 let id = self.id;
435 self.id = match self.id.checked_add(1) {
436 Some(id) => id,
437 None => panic!("`id` grows beyond `usize::MAX`"),
438 };
439 id
440 }
441
442 pub fn register(&mut self, watcher: impl Fn(Context<T>) + 'static) -> WatcherId {
444 let id = self.assign();
445 self.map.insert(id, Rc::new(watcher));
446 id
447 }
448
449 fn watchers_snapshot(&self) -> Vec<Watcher<T>> {
451 self.map.values().cloned().collect()
452 }
453
454 pub fn cancel(&mut self, id: WatcherId) {
456 self.map.remove(&id);
457 }
458}