1use alloc::{boxed::Box, collections::BTreeMap, rc::Rc};
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));
45 }
46}
47
48pub type BoxWatcher<T> = Box<dyn Fn(Context<T>) + 'static>;
50
51#[derive(Debug, Clone)]
53pub struct Context<T> {
54 value: T,
56 metadata: Metadata,
58}
59
60impl<T> Context<T> {
61 pub const fn new(value: T, metadata: Metadata) -> Self {
63 Self { value, metadata }
64 }
65
66 #[must_use]
68 pub fn with<V: Clone + 'static>(mut self, value: V) -> Self {
69 self.metadata = self.metadata.with(value);
70 self
71 }
72
73 pub fn into_value(self) -> T {
75 self.value
76 }
77
78 pub const fn value(&self) -> &T {
80 &self.value
81 }
82
83 pub const fn value_mut(&mut self) -> &mut T {
85 &mut self.value
86 }
87
88 pub const fn metadata(&self) -> &Metadata {
90 &self.metadata
91 }
92
93 pub const fn metadata_mut(&mut self) -> &mut Metadata {
95 &mut self.metadata
96 }
97
98 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Context<U> {
100 Context::new(f(self.value), self.metadata)
101 }
102
103 pub fn as_ref(&self) -> Context<&T> {
105 Context::new(&self.value, self.metadata.clone())
106 }
107
108 pub fn as_mut(&mut self) -> Context<&mut T> {
110 Context::new(&mut self.value, self.metadata.clone())
111 }
112
113 pub fn as_deref(&self) -> Context<&T::Target>
115 where
116 T: core::ops::Deref,
117 {
118 Context::new(&*self.value, self.metadata.clone())
119 }
120
121 pub fn as_deref_mut(&mut self) -> Context<&mut T::Target>
123 where
124 T: core::ops::DerefMut,
125 {
126 Context::new(&mut *self.value, self.metadata.clone())
127 }
128}
129
130impl<T> From<T> for Context<T> {
131 fn from(value: T) -> Self {
132 Self::new(value, Metadata::new())
133 }
134}
135
136#[must_use]
138pub trait WatcherGuard: 'static {}
139
140impl WatcherGuard for () {}
141
142impl<T1: WatcherGuard, T2: WatcherGuard> WatcherGuard for (T1, T2) {}
143
144#[derive(Debug)]
146pub struct OnDrop<F>(Option<F>)
147where
148 F: FnOnce();
149
150impl<F> OnDrop<F>
151where
152 F: FnOnce() + 'static,
153{
154 pub const fn new(f: F) -> Self {
156 Self(Some(f))
157 }
158
159 #[allow(clippy::needless_pass_by_value)]
161 pub fn attach(guard: impl WatcherGuard, f: F) -> impl WatcherGuard {
162 OnDrop::new(move || {
163 let _ = guard;
164 f();
165 })
166 }
167}
168
169#[allow(clippy::unwrap_used)]
170impl<F> Drop for OnDrop<F>
171where
172 F: FnOnce(),
173{
174 fn drop(&mut self) {
175 (self.0.take().unwrap())();
176 }
177}
178
179pub type BoxWatcherGuard = Box<dyn WatcherGuard>;
181
182impl WatcherGuard for Box<dyn WatcherGuard> {}
183
184impl WatcherGuard for Rc<dyn WatcherGuard> {}
185
186impl<F: FnOnce() + 'static> WatcherGuard for OnDrop<F> {}
187
188impl Metadata {
189 #[must_use]
191 pub fn new() -> Self {
192 Self::default()
193 }
194
195 #[must_use]
201 #[allow(clippy::expect_used)]
202 pub fn get<T: 'static + Clone>(&self) -> T {
203 self.try_get()
204 .expect("Value of requested type should be present in metadata")
205 }
206
207 #[must_use]
211 pub fn try_get<T: 'static + Clone>(&self) -> Option<T> {
212 self.0.try_get()
213 }
214
215 #[must_use]
219 pub fn with<T: 'static + Clone>(mut self, value: T) -> Self {
220 self.0.insert(value);
221 self
222 }
223
224 #[must_use]
226 pub fn is_empty(&self) -> bool {
227 self.0.0.is_empty()
228 }
229}
230
231pub(crate) type WatcherId = NonZeroUsize;
233
234#[derive(Debug)]
238pub struct WatcherManager<T> {
239 inner: Rc<RefCell<WatcherManagerInner<T>>>,
240}
241
242impl<T> Clone for WatcherManager<T> {
243 fn clone(&self) -> Self {
244 Self {
245 inner: self.inner.clone(),
246 }
247 }
248}
249
250impl<T> Default for WatcherManager<T> {
251 fn default() -> Self {
252 Self {
253 inner: Rc::default(),
254 }
255 }
256}
257
258impl<T: 'static> WatcherManager<T> {
259 #[must_use]
261 pub fn new() -> Self {
262 Self::default()
263 }
264
265 #[must_use]
267 pub fn is_empty(&self) -> bool {
268 self.inner.borrow().is_empty()
269 }
270
271 pub fn register(&self, watcher: impl Fn(Context<T>) + 'static) -> WatcherId {
273 self.inner.borrow_mut().register(watcher)
274 }
275
276 pub fn register_as_guard(
278 &self,
279 watcher: impl Fn(Context<T>) + 'static,
280 ) -> WatcherManagerGuard<T> {
281 let id = self.register(watcher);
282 let this = self.clone();
283 WatcherManagerGuard { manager: this, id }
284 }
285
286 pub fn notify(&self, ctx: impl Fn() -> Context<T>) {
288 let this = Rc::downgrade(&self.inner);
289 if let Some(this) = this.upgrade() {
290 this.borrow().notify(ctx);
291 }
292 }
293
294 pub fn clear(&self) {
296 self.inner.borrow_mut().map.clear();
297 }
298
299 pub fn cancel(&self, id: WatcherId) {
301 self.inner.borrow_mut().cancel(id);
302 }
303}
304
305#[must_use]
307#[derive(Debug)]
308pub struct WatcherManagerGuard<T: 'static> {
309 manager: WatcherManager<T>,
310 id: WatcherId,
311}
312
313impl<T> WatcherGuard for WatcherManagerGuard<T> {}
314
315impl<T: 'static> Drop for WatcherManagerGuard<T> {
316 fn drop(&mut self) {
317 self.manager.cancel(self.id);
318 }
319}
320
321struct WatcherManagerInner<T> {
325 id: WatcherId,
326 map: BTreeMap<WatcherId, BoxWatcher<T>>,
327}
328
329impl<T> Debug for WatcherManagerInner<T> {
330 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
331 f.write_str(type_name::<Self>())
332 }
333}
334
335impl<T> Default for WatcherManagerInner<T> {
336 fn default() -> Self {
337 Self {
338 id: WatcherId::MIN,
339 map: BTreeMap::new(),
340 }
341 }
342}
343
344impl<T: 'static> WatcherManagerInner<T> {
345 pub fn is_empty(&self) -> bool {
347 self.map.is_empty()
348 }
349
350 const fn assign(&mut self) -> WatcherId {
352 let id = self.id;
353 self.id = match self.id.checked_add(1) {
354 Some(id) => id,
355 None => panic!("`id` grows beyond `usize::MAX`"),
356 };
357 id
358 }
359
360 pub fn register(&mut self, watcher: impl Fn(Context<T>) + 'static) -> WatcherId {
362 let id = self.assign();
363 self.map.insert(id, Box::new(watcher));
364 id
365 }
366
367 pub fn notify(&self, ctx: impl Fn() -> Context<T>) {
369 for watcher in self.map.values() {
370 watcher(ctx());
371 }
372 }
373
374 pub fn cancel(&mut self, id: WatcherId) {
376 self.map.remove(&id);
377 }
378}