1use std::{
2 any::{Any, TypeId},
3 cell::{Ref, RefCell, RefMut},
4 collections::HashMap,
5};
6
7use crate::ecs::system_param::SystemParam;
8
9#[derive(Default)]
13pub struct Resources {
14 map: HashMap<TypeId, RefCell<Box<dyn Any>>>,
15}
16
17impl Resources {
18 fn cell<T: 'static>(&self) -> &RefCell<Box<dyn Any>> {
19 self.map
20 .get(&TypeId::of::<T>())
21 .unwrap_or_else(|| panic!("Resource not found: {}", std::any::type_name::<T>()))
22 }
23
24 pub fn insert<T: 'static>(&mut self, value: T) {
26 self.map
27 .insert(TypeId::of::<T>(), RefCell::new(Box::new(value)));
28 }
29
30 pub fn get<T: 'static>(&self) -> Ref<'_, T> {
32 Ref::map(self.cell::<T>().borrow(), |b| b.downcast_ref::<T>().unwrap())
33 }
34
35 pub fn get_mut<T: 'static>(&self) -> RefMut<'_, T> {
37 RefMut::map(self.cell::<T>().borrow_mut(), |b| b.downcast_mut::<T>().unwrap())
38 }
39
40 pub fn remove<T: 'static>(&mut self) -> Option<T> {
42 self.map
43 .remove(&TypeId::of::<T>())
44 .map(|cell| *cell.into_inner().downcast::<T>().unwrap())
45 }
46
47 pub fn contains<T: 'static>(&self) -> bool {
49 self.map.contains_key(&TypeId::of::<T>())
50 }
51}
52
53pub struct Read<'a, T: 'static> {
57 pub(crate) inner: Ref<'a, T>,
58}
59
60impl<'a, T> std::ops::Deref for Read<'a, T> {
61 type Target = T;
62
63 fn deref(&self) -> &Self::Target {
64 &self.inner
65 }
66}
67
68pub struct Write<'a, T: 'static> {
72 pub(crate) inner: RefMut<'a, T>,
73}
74
75impl<'a, T> std::ops::Deref for Write<'a, T> {
76 type Target = T;
77
78 fn deref(&self) -> &Self::Target {
79 &self.inner
80 }
81}
82
83impl<'a, T> std::ops::DerefMut for Write<'a, T> {
84 fn deref_mut(&mut self) -> &mut Self::Target {
85 &mut self.inner
86 }
87}
88
89impl<T: 'static> SystemParam for Read<'_, T> {
90 type Item<'a> = Read<'a, T>;
91 type State = ();
92
93 fn fetch<'a>(
94 _world: &'a hecs::World,
95 resources: &'a Resources,
96 _state: &'a mut Self::State,
97 ) -> Self::Item<'a> {
98 Read {
99 inner: resources.get::<T>(),
100 }
101 }
102}
103
104impl<T: 'static> SystemParam for Write<'_, T> {
105 type Item<'a> = Write<'a, T>;
106 type State = ();
107
108 fn fetch<'a>(
109 _world: &'a hecs::World,
110 resources: &'a Resources,
111 _state: &'a mut Self::State,
112 ) -> Self::Item<'a> {
113 Write {
114 inner: resources.get_mut::<T>(),
115 }
116 }
117}
118
119impl<T> SystemParam for Option<Read<'static, T>>
120where
121 T: 'static + Sync + Send,
122{
123 type Item<'a> = Option<Read<'a, T>>;
124 type State = ();
125
126 fn fetch<'a>(
127 world: &'a hecs::World,
128 resources: &'a Resources,
129 state: &'a mut Self::State,
130 ) -> Self::Item<'a> {
131 resources.contains::<T>().then(|| Read::fetch(world, resources, state))
132 }
133}
134
135impl<T> SystemParam for Option<Write<'static, T>>
136where
137 T: 'static + Sync + Send,
138{
139 type Item<'a> = Option<Write<'a, T>>;
140 type State = ();
141
142 fn fetch<'a>(
143 world: &'a hecs::World,
144 resources: &'a Resources,
145 state: &'a mut Self::State,
146 ) -> Self::Item<'a> {
147 resources.contains::<T>().then(|| Write::fetch(world, resources, state))
148 }
149}