1use alloc::{boxed::Box, collections::BTreeMap, rc::Rc, vec::Vec};
7use core::{
8 any::{Any, TypeId, type_name},
9 cell::RefCell,
10 fmt::Debug,
11 num::NonZeroUsize,
12};
13
14#[derive(Debug, Default, Clone)]
19pub struct Metadata(Box<MetadataInner>);
20
21#[derive(Debug, Default, Clone)]
25struct MetadataInner(BTreeMap<TypeId, Rc<dyn Any>>);
26
27impl MetadataInner {
28 #[allow(clippy::unwrap_used)]
32 pub fn try_get<T: 'static + Clone>(&self) -> Option<T> {
33 self.0
35 .get(&TypeId::of::<T>())
36 .map(|v| v.downcast_ref::<T>().unwrap())
37 .cloned()
38 }
39
40 pub fn insert<T: 'static + Clone>(&mut self, value: T) {
44 self.0.insert(TypeId::of::<T>(), Rc::new(value));
48 }
49}
50
51pub type Watcher<T> = Rc<dyn Fn(Context<T>) + 'static>;
53
54#[derive(Debug, Clone)]
56pub struct Context<T> {
57 value: T,
59 metadata: Metadata,
61}
62
63impl<T> Context<T> {
64 pub const fn new(value: T, metadata: Metadata) -> Self {
66 Self { value, metadata }
67 }
68
69 #[must_use]
71 pub fn with<V: Clone + 'static>(mut self, value: V) -> Self {
72 self.metadata = self.metadata.with(value);
73 self
74 }
75
76 pub fn into_value(self) -> T {
78 self.value
79 }
80
81 pub const fn value(&self) -> &T {
83 &self.value
84 }
85
86 pub const fn value_mut(&mut self) -> &mut T {
88 &mut self.value
89 }
90
91 pub const fn metadata(&self) -> &Metadata {
93 &self.metadata
94 }
95
96 pub const fn metadata_mut(&mut self) -> &mut Metadata {
98 &mut self.metadata
99 }
100
101 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Context<U> {
103 Context::new(f(self.value), self.metadata)
104 }
105
106 pub fn as_ref(&self) -> Context<&T> {
108 Context::new(&self.value, self.metadata.clone())
109 }
110
111 pub fn as_mut(&mut self) -> Context<&mut T> {
113 Context::new(&mut self.value, self.metadata.clone())
114 }
115
116 pub fn as_deref(&self) -> Context<&T::Target>
118 where
119 T: core::ops::Deref,
120 {
121 Context::new(&*self.value, self.metadata.clone())
122 }
123
124 pub fn as_deref_mut(&mut self) -> Context<&mut T::Target>
126 where
127 T: core::ops::DerefMut,
128 {
129 Context::new(&mut *self.value, self.metadata.clone())
130 }
131}
132
133impl<T> From<T> for Context<T> {
134 fn from(value: T) -> Self {
135 Self::new(value, Metadata::new())
136 }
137}
138
139#[must_use]
141pub trait WatcherGuard: 'static {}
142
143impl WatcherGuard for () {}
144
145impl<T1: WatcherGuard, T2: WatcherGuard> WatcherGuard for (T1, T2) {}
146
147#[derive(Debug)]
149pub struct OnDrop<F>(Option<F>)
150where
151 F: FnOnce();
152
153impl<F> OnDrop<F>
154where
155 F: FnOnce() + 'static,
156{
157 pub const fn new(f: F) -> Self {
159 Self(Some(f))
160 }
161
162 #[allow(clippy::needless_pass_by_value)]
164 pub fn attach(guard: impl WatcherGuard, f: F) -> impl WatcherGuard {
165 OnDrop::new(move || {
166 let _ = guard;
167 f();
168 })
169 }
170}
171
172#[allow(clippy::unwrap_used)]
173impl<F> Drop for OnDrop<F>
174where
175 F: FnOnce(),
176{
177 fn drop(&mut self) {
178 (self.0.take().unwrap())();
179 }
180}
181
182pub type BoxWatcherGuard = Box<dyn WatcherGuard>;
184
185impl<T: WatcherGuard + ?Sized> WatcherGuard for Box<T> {}
186impl<T: WatcherGuard + ?Sized> WatcherGuard for Rc<T> {}
187
188impl<F: FnOnce() + 'static> WatcherGuard for OnDrop<F> {}
189
190impl Metadata {
191 #[must_use]
193 pub fn new() -> Self {
194 Self::default()
195 }
196
197 #[must_use]
203 #[allow(clippy::expect_used)]
204 pub fn get<T: 'static + Clone>(&self) -> T {
205 self.try_get()
206 .expect("Value of requested type should be present in metadata")
207 }
208
209 #[must_use]
213 pub fn try_get<T: 'static + Clone>(&self) -> Option<T> {
214 self.0.try_get()
215 }
216
217 #[must_use]
221 pub fn with<T: 'static + Clone>(mut self, value: T) -> Self {
222 self.0.insert(value);
223 self
224 }
225
226 #[must_use]
228 pub fn is_empty(&self) -> bool {
229 self.0.0.is_empty()
230 }
231}
232
233pub(crate) type WatcherId = NonZeroUsize;
235
236#[derive(Debug)]
240pub struct WatcherManager<T> {
241 inner: Rc<RefCell<WatcherManagerInner<T>>>,
242}
243
244impl<T> Clone for WatcherManager<T> {
245 fn clone(&self) -> Self {
246 Self {
247 inner: self.inner.clone(),
248 }
249 }
250}
251
252impl<T> Default for WatcherManager<T> {
253 fn default() -> Self {
254 Self {
255 inner: Rc::default(),
256 }
257 }
258}
259
260impl<T: 'static> WatcherManager<T> {
261 #[must_use]
263 pub fn new() -> Self {
264 Self::default()
265 }
266
267 #[must_use]
269 pub fn is_empty(&self) -> bool {
270 self.inner.borrow().is_empty()
271 }
272
273 pub fn register(&self, watcher: impl Fn(Context<T>) + 'static) -> WatcherId {
275 self.inner.borrow_mut().register(watcher)
276 }
277
278 pub fn register_as_guard(
280 &self,
281 watcher: impl Fn(Context<T>) + 'static,
282 ) -> WatcherManagerGuard<T> {
283 let id = self.register(watcher);
284 let this = self.clone();
285 WatcherManagerGuard { manager: this, id }
286 }
287
288 pub fn notify(&self, ctx: &Context<T>)
290 where
291 T: Clone,
292 {
293 let watchers = {
294 let inner = self.inner.borrow();
295 inner.watchers_snapshot()
296 };
297
298 if watchers.is_empty() {
299 return;
300 }
301
302 for watcher in watchers {
303 watcher(ctx.clone());
304 }
305 }
306
307 pub fn cancel(&self, id: WatcherId) {
309 self.inner.borrow_mut().cancel(id);
310 }
311}
312
313#[must_use]
315#[derive(Debug)]
316pub struct WatcherManagerGuard<T: 'static> {
317 manager: WatcherManager<T>,
318 id: WatcherId,
319}
320
321impl<T> WatcherGuard for WatcherManagerGuard<T> {}
322
323impl<T: 'static> Drop for WatcherManagerGuard<T> {
324 fn drop(&mut self) {
325 self.manager.cancel(self.id);
326 }
327}
328
329struct WatcherManagerInner<T> {
333 id: WatcherId,
334 map: BTreeMap<WatcherId, Watcher<T>>,
335}
336
337impl<T> Debug for WatcherManagerInner<T> {
338 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
339 f.write_str(type_name::<Self>())
340 }
341}
342
343impl<T> Default for WatcherManagerInner<T> {
344 fn default() -> Self {
345 Self {
346 id: WatcherId::MIN,
347 map: BTreeMap::new(),
348 }
349 }
350}
351
352impl<T: 'static> WatcherManagerInner<T> {
353 pub fn is_empty(&self) -> bool {
355 self.map.is_empty()
356 }
357
358 const fn assign(&mut self) -> WatcherId {
360 let id = self.id;
361 self.id = match self.id.checked_add(1) {
362 Some(id) => id,
363 None => panic!("`id` grows beyond `usize::MAX`"),
364 };
365 id
366 }
367
368 pub fn register(&mut self, watcher: impl Fn(Context<T>) + 'static) -> WatcherId {
370 let id = self.assign();
371 self.map.insert(id, Rc::new(watcher));
372 id
373 }
374
375 fn watchers_snapshot(&self) -> Vec<Watcher<T>> {
377 self.map.values().cloned().collect()
378 }
379
380 pub fn cancel(&mut self, id: WatcherId) {
382 self.map.remove(&id);
383 }
384}