widgetui/widget/
param.rs

1use std::{
2    any::{type_name, Any, TypeId},
3    cell::{Ref, RefMut},
4    collections::HashMap,
5    marker::PhantomData,
6    ops::{Deref, DerefMut},
7};
8
9use crate::states::States;
10
11pub trait WidgetParam {
12    type Item<'new>;
13    fn retrieve(resources: &States) -> Self::Item<'_>;
14}
15
16pub struct Res<'a, T: 'static> {
17    value: Ref<'a, Box<dyn Any>>,
18    _marker: PhantomData<&'a T>,
19}
20
21impl<'a, T: 'static> Deref for Res<'a, T> {
22    type Target = T;
23    fn deref(&self) -> &Self::Target {
24        self.value.downcast_ref().unwrap()
25    }
26}
27
28impl<'a, T: 'static> WidgetParam for Res<'a, T> {
29    type Item<'new> = Res<'new, T>;
30    fn retrieve(resources: &States) -> Self::Item<'_> {
31        Res {
32            value: resources.get(&TypeId::of::<T>()).unwrap().borrow(),
33            _marker: PhantomData,
34        }
35    }
36}
37
38pub struct ResMut<'a, T: 'static> {
39    value: RefMut<'a, Box<dyn Any>>,
40    _marker: PhantomData<&'a mut T>,
41}
42
43impl<T: 'static> Deref for ResMut<'_, T> {
44    type Target = T;
45
46    fn deref(&self) -> &T {
47        self.value.downcast_ref().unwrap()
48    }
49}
50
51impl<T: 'static> DerefMut for ResMut<'_, T> {
52    fn deref_mut(&mut self) -> &mut T {
53        self.value.downcast_mut().unwrap()
54    }
55}
56
57impl<'a, T: 'static> WidgetParam for ResMut<'a, T> {
58    type Item<'new> = ResMut<'new, T>;
59
60    fn retrieve(resources: &States) -> Self::Item<'_> {
61        ResMut {
62            value: resources
63                .get(&TypeId::of::<T>())
64                .unwrap_or_else(|| {
65                    panic!(
66                        "Resource: `{}` with id `{:?}` Not Found",
67                        type_name::<T>(),
68                        TypeId::of::<T>()
69                    )
70                })
71                .borrow_mut(),
72            _marker: PhantomData,
73        }
74    }
75}