termite/storage/
resource.rs1use std::cell::UnsafeCell;
2
3use crate::{ChangeTicks, ComponentId, SparseArray};
4
5pub trait Resource: Send + Sync + 'static {}
6
7impl<T> Resource for T where T: Send + Sync + 'static {}
8
9impl dyn Resource {
10 #[inline]
11 pub unsafe fn downcast_ref<T: Resource>(&self) -> &T {
12 unsafe { &*(self as *const dyn Resource as *const T) }
13 }
14
15 #[inline]
16 pub unsafe fn downcast_mut<T: Resource>(&mut self) -> &mut T {
17 unsafe { &mut *(self as *mut dyn Resource as *mut T) }
18 }
19}
20
21pub struct ResourceData {
22 data: *mut dyn Resource,
23 change_ticks: UnsafeCell<ChangeTicks>,
24}
25
26impl ResourceData {
27 #[inline]
28 pub fn new<T: Resource>(data: T, change_tick: u32) -> Self {
29 Self {
30 data: Box::into_raw(Box::new(data)),
31 change_ticks: UnsafeCell::new(ChangeTicks::new(change_tick)),
32 }
33 }
34
35 #[inline]
36 pub fn from_boxed(data: Box<dyn Resource>, change_tick: u32) -> Self {
37 Self {
38 data: Box::into_raw(data),
39 change_ticks: UnsafeCell::new(ChangeTicks::new(change_tick)),
40 }
41 }
42
43 #[inline]
44 pub fn as_ptr(&self) -> *mut dyn Resource {
45 self.data
46 }
47
48 #[inline]
49 pub fn change_ticks(&self) -> &UnsafeCell<ChangeTicks> {
50 &self.change_ticks
51 }
52
53 #[inline]
54 pub fn change_ticks_mut(&mut self) -> &mut ChangeTicks {
55 self.change_ticks.get_mut()
56 }
57}
58
59impl Drop for ResourceData {
60 #[inline]
61 fn drop(&mut self) {
62 unsafe { Box::from_raw(self.data) };
64 }
65}
66
67#[derive(Default)]
68pub struct Resources {
69 resources: SparseArray<ResourceData>,
70}
71
72impl Resources {
73 #[inline]
74 pub fn contains(&self, id: ComponentId) -> bool {
75 self.resources.contains(id.index())
76 }
77
78 #[inline]
79 pub unsafe fn insert(
80 &mut self,
81 id: ComponentId,
82 resource: Box<dyn Resource>,
83 change_tick: u32,
84 ) {
85 let data = ResourceData::from_boxed(resource, change_tick);
86 self.resources.insert(id.index(), data);
87 }
88
89 #[inline]
90 pub fn remove(&mut self, id: ComponentId) -> Option<*mut dyn Resource> {
91 Some(self.resources.remove(id.index())?.as_ptr())
92 }
93
94 #[inline]
95 pub fn get(&self, id: ComponentId) -> Option<*mut dyn Resource> {
96 Some(self.resources.get(id.index())?.as_ptr())
97 }
98
99 #[inline]
100 pub fn get_with_ticks(&self, id: ComponentId) -> Option<(*mut dyn Resource, *mut ChangeTicks)> {
101 let data = self.resources.get(id.index())?;
102 Some((data.as_ptr(), data.change_ticks.get()))
103 }
104}