1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use std::cell::UnsafeCell;
use crate::{change_detection::ChangeTicks, world::ComponentId};
use super::SparseArray;
pub trait Resource: Send + Sync + 'static {}
impl<T> Resource for T where T: Send + Sync + 'static {}
impl dyn Resource {
#[inline]
pub unsafe fn downcast_ref<T: Resource>(&self) -> &T {
unsafe { &*(self as *const dyn Resource as *const T) }
}
#[inline]
pub unsafe fn downcast_mut<T: Resource>(&mut self) -> &mut T {
unsafe { &mut *(self as *mut dyn Resource as *mut T) }
}
}
pub struct ResourceData {
data: *mut dyn Resource,
change_ticks: UnsafeCell<ChangeTicks>,
}
impl ResourceData {
#[inline]
pub fn new<T: Resource>(data: T, change_tick: u32) -> Self {
Self {
data: Box::into_raw(Box::new(data)),
change_ticks: UnsafeCell::new(ChangeTicks::new(change_tick)),
}
}
#[inline]
pub fn from_boxed(data: Box<dyn Resource>, change_tick: u32) -> Self {
Self {
data: Box::into_raw(data),
change_ticks: UnsafeCell::new(ChangeTicks::new(change_tick)),
}
}
#[inline]
pub fn as_ptr(&self) -> *mut dyn Resource {
self.data
}
#[inline]
pub fn into_ptr(self) -> *mut dyn Resource {
let data = self.data;
std::mem::forget(self);
data
}
#[inline]
pub fn change_ticks(&self) -> &UnsafeCell<ChangeTicks> {
&self.change_ticks
}
#[inline]
pub fn change_ticks_mut(&mut self) -> &mut ChangeTicks {
self.change_ticks.get_mut()
}
}
impl Drop for ResourceData {
#[inline]
fn drop(&mut self) {
unsafe { Box::from_raw(self.data) };
}
}
impl std::fmt::Debug for ResourceData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ResourceData")
.field("data", &self.data)
.field("change_ticks", &self.change_ticks)
.finish()
}
}
#[derive(Default)]
pub struct Resources {
resources: SparseArray<ResourceData>,
}
impl Resources {
#[inline]
pub fn len(&self) -> usize {
self.resources.iter().count()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn contains(&self, id: ComponentId) -> bool {
self.resources.contains(id.index())
}
#[inline]
pub unsafe fn insert(
&mut self,
id: ComponentId,
resource: Box<dyn Resource>,
change_tick: u32,
) {
let data = ResourceData::from_boxed(resource, change_tick);
self.resources.insert(id.index(), data);
}
#[inline]
pub fn remove(&mut self, id: ComponentId) -> Option<*mut dyn Resource> {
Some(self.resources.remove(id.index())?.into_ptr())
}
#[inline]
pub fn get(&self, id: ComponentId) -> Option<*mut dyn Resource> {
Some(self.resources.get(id.index())?.as_ptr())
}
#[inline]
pub fn get_with_ticks(&self, id: ComponentId) -> Option<(*mut dyn Resource, *mut ChangeTicks)> {
let data = self.resources.get(id.index())?;
Some((data.as_ptr(), data.change_ticks.get()))
}
}
impl std::fmt::Debug for Resources {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Resources")
.field("len", &self.len())
.finish()
}
}