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
33#[derive(Debug, Default, Clone)]
38pub struct Metadata(Box<MetadataInner>);
39
40#[derive(Debug, Default, Clone)]
44struct MetadataInner(BTreeMap<TypeId, Rc<dyn Any>>);
45
46impl MetadataInner {
47 #[allow(clippy::unwrap_used)]
51 pub fn try_get<T: 'static + Clone>(&self) -> Option<T> {
52 self.0
54 .get(&TypeId::of::<T>())
55 .map(|v| v.downcast_ref::<T>().unwrap())
56 .cloned()
57 }
58
59 pub fn insert<T: 'static + Clone>(&mut self, value: T) {
63 self.0.insert(TypeId::of::<T>(), Rc::new(value));
67 }
68}
69
70pub type Watcher<T> = Rc<dyn Fn(Context<T>) + 'static>;
72
73#[derive(Debug, Clone)]
75pub struct Context<T> {
76 value: T,
78 metadata: Metadata,
80}
81
82impl<T> Context<T> {
83 pub const fn new(value: T, metadata: Metadata) -> Self {
85 Self { value, metadata }
86 }
87
88 #[must_use]
90 pub fn with<V: Clone + 'static>(mut self, value: V) -> Self {
91 self.metadata = self.metadata.with(value);
92 self
93 }
94
95 pub fn into_value(self) -> T {
97 self.value
98 }
99
100 pub const fn value(&self) -> &T {
102 &self.value
103 }
104
105 pub const fn value_mut(&mut self) -> &mut T {
107 &mut self.value
108 }
109
110 pub const fn metadata(&self) -> &Metadata {
112 &self.metadata
113 }
114
115 pub const fn metadata_mut(&mut self) -> &mut Metadata {
117 &mut self.metadata
118 }
119
120 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Context<U> {
122 Context::new(f(self.value), self.metadata)
123 }
124
125 pub fn as_ref(&self) -> Context<&T> {
127 Context::new(&self.value, self.metadata.clone())
128 }
129
130 pub fn as_mut(&mut self) -> Context<&mut T> {
132 Context::new(&mut self.value, self.metadata.clone())
133 }
134
135 pub fn as_deref(&self) -> Context<&T::Target>
137 where
138 T: core::ops::Deref,
139 {
140 Context::new(&*self.value, self.metadata.clone())
141 }
142
143 pub fn as_deref_mut(&mut self) -> Context<&mut T::Target>
145 where
146 T: core::ops::DerefMut,
147 {
148 Context::new(&mut *self.value, self.metadata.clone())
149 }
150}
151
152impl<T> From<T> for Context<T> {
153 fn from(value: T) -> Self {
154 Self::new(value, Metadata::new())
155 }
156}
157
158#[must_use]
160pub trait WatcherGuard: 'static {}
161
162impl<T: 'static> WatcherGuard for Option<T> {}
163
164impl<T: WatcherGuard, E: WatcherGuard> WatcherGuard for Result<T, E> {}
165
166impl WatcherGuard for () {}
167
168impl<T1: WatcherGuard, T2: WatcherGuard> WatcherGuard for (T1, T2) {}
169
170#[derive(Debug)]
172pub struct OnDrop<F>(Option<F>)
173where
174 F: FnOnce();
175
176impl<F> OnDrop<F>
177where
178 F: FnOnce() + 'static,
179{
180 pub const fn new(f: F) -> Self {
182 Self(Some(f))
183 }
184
185 #[allow(clippy::needless_pass_by_value)]
187 pub fn attach(guard: impl WatcherGuard, f: F) -> impl WatcherGuard {
188 OnDrop::new(move || {
189 let _ = guard;
190 f();
191 })
192 }
193}
194
195#[allow(clippy::unwrap_used)]
196impl<F> Drop for OnDrop<F>
197where
198 F: FnOnce(),
199{
200 fn drop(&mut self) {
201 (self.0.take().unwrap())();
202 }
203}
204
205pub type BoxWatcherGuard = Box<dyn WatcherGuard>;
207
208impl<T: WatcherGuard + ?Sized> WatcherGuard for Box<T> {}
209impl<T: WatcherGuard + ?Sized> WatcherGuard for Rc<T> {}
210
211impl<F: FnOnce() + 'static> WatcherGuard for OnDrop<F> {}
212
213impl Metadata {
214 #[must_use]
216 pub fn new() -> Self {
217 Self::default()
218 }
219
220 #[must_use]
226 #[allow(clippy::expect_used)]
227 pub fn get<T: 'static + Clone>(&self) -> T {
228 self.try_get()
229 .expect("Value of requested type should be present in metadata")
230 }
231
232 #[must_use]
236 pub fn try_get<T: 'static + Clone>(&self) -> Option<T> {
237 self.0.try_get()
238 }
239
240 #[must_use]
244 pub fn with<T: 'static + Clone>(mut self, value: T) -> Self {
245 self.0.insert(value);
246 self
247 }
248
249 #[must_use]
251 pub fn is_empty(&self) -> bool {
252 self.0.0.is_empty()
253 }
254}
255
256pub(crate) type WatcherId = NonZeroUsize;
258
259#[derive(Debug)]
263pub struct WatcherManager<T> {
264 inner: Rc<RefCell<WatcherManagerInner<T>>>,
265}
266
267impl<T> Clone for WatcherManager<T> {
268 fn clone(&self) -> Self {
269 Self {
270 inner: self.inner.clone(),
271 }
272 }
273}
274
275impl<T> Default for WatcherManager<T> {
276 fn default() -> Self {
277 Self {
278 inner: Rc::default(),
279 }
280 }
281}
282
283impl<T: 'static> WatcherManager<T> {
284 #[must_use]
286 pub fn new() -> Self {
287 Self::default()
288 }
289
290 #[must_use]
292 pub fn is_empty(&self) -> bool {
293 self.inner.borrow().is_empty()
294 }
295
296 pub fn register(&self, watcher: impl Fn(Context<T>) + 'static) -> WatcherId {
298 self.inner.borrow_mut().register(watcher)
299 }
300
301 pub fn register_as_guard(
303 &self,
304 watcher: impl Fn(Context<T>) + 'static,
305 ) -> WatcherManagerGuard<T> {
306 let id = self.register(watcher);
307 let this = self.clone();
308 WatcherManagerGuard { manager: this, id }
309 }
310
311 pub fn notify(&self, ctx: &Context<T>)
313 where
314 T: Clone,
315 {
316 let watchers = {
317 let inner = self.inner.borrow();
318 inner.watchers_snapshot()
319 };
320
321 if watchers.is_empty() {
322 return;
323 }
324
325 for watcher in watchers {
326 watcher(ctx.clone());
327 }
328 }
329
330 pub fn cancel(&self, id: WatcherId) {
332 self.inner.borrow_mut().cancel(id);
333 }
334}
335
336#[must_use]
338#[derive(Debug)]
339pub struct WatcherManagerGuard<T: 'static> {
340 manager: WatcherManager<T>,
341 id: WatcherId,
342}
343
344impl<T> WatcherGuard for WatcherManagerGuard<T> {}
345
346impl<T: 'static> Drop for WatcherManagerGuard<T> {
347 fn drop(&mut self) {
348 self.manager.cancel(self.id);
349 }
350}
351
352struct WatcherManagerInner<T> {
356 id: WatcherId,
357 map: BTreeMap<WatcherId, Watcher<T>>,
358}
359
360impl<T> Debug for WatcherManagerInner<T> {
361 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
362 f.write_str(type_name::<Self>())
363 }
364}
365
366impl<T> Default for WatcherManagerInner<T> {
367 fn default() -> Self {
368 Self {
369 id: WatcherId::MIN,
370 map: BTreeMap::new(),
371 }
372 }
373}
374
375impl<T: 'static> WatcherManagerInner<T> {
376 pub fn is_empty(&self) -> bool {
378 self.map.is_empty()
379 }
380
381 const fn assign(&mut self) -> WatcherId {
383 let id = self.id;
384 self.id = match self.id.checked_add(1) {
385 Some(id) => id,
386 None => panic!("`id` grows beyond `usize::MAX`"),
387 };
388 id
389 }
390
391 pub fn register(&mut self, watcher: impl Fn(Context<T>) + 'static) -> WatcherId {
393 let id = self.assign();
394 self.map.insert(id, Rc::new(watcher));
395 id
396 }
397
398 fn watchers_snapshot(&self) -> Vec<Watcher<T>> {
400 self.map.values().cloned().collect()
401 }
402
403 pub fn cancel(&mut self, id: WatcherId) {
405 self.map.remove(&id);
406 }
407}