stet_core/
entity_table.rs1use crate::object::EntityId;
13
14#[derive(Clone, Debug)]
16pub struct EntityMeta {
17 pub offset: u32,
19 pub len: u32,
21 pub save_level: u16,
23 pub flags: u8,
26 pub created_after_save: u32,
30}
31
32impl EntityMeta {
33 const FLAG_GLOBAL: u8 = 1;
34 const FLAG_COW_BACKUP: u8 = 1 << 2;
35
36 pub fn is_global(&self) -> bool {
38 self.flags & Self::FLAG_GLOBAL != 0
39 }
40
41 pub fn set_global(&mut self, global: bool) {
43 if global {
44 self.flags |= Self::FLAG_GLOBAL;
45 } else {
46 self.flags &= !Self::FLAG_GLOBAL;
47 }
48 }
49
50 pub fn is_cow_backup(&self) -> bool {
58 self.flags & Self::FLAG_COW_BACKUP != 0
59 }
60
61 pub fn set_cow_backup(&mut self) {
63 self.flags |= Self::FLAG_COW_BACKUP;
64 }
65}
66
67pub struct EntityTable {
69 entries: Vec<EntityMeta>,
70}
71
72impl EntityTable {
73 pub fn new() -> Self {
75 Self {
76 entries: Vec::new(),
77 }
78 }
79
80 pub fn allocate(
83 &mut self,
84 offset: u32,
85 len: u32,
86 save_level: u16,
87 global: bool,
88 created_after_save: u32,
89 ) -> EntityId {
90 let index = self.entries.len() as u32;
91 let id = if global {
92 EntityId::global(index)
93 } else {
94 EntityId::local(index)
95 };
96 let mut flags = 0u8;
97 if global {
98 flags |= EntityMeta::FLAG_GLOBAL;
99 }
100 self.entries.push(EntityMeta {
101 offset,
102 len,
103 save_level,
104 flags,
105 created_after_save,
106 });
107 id
108 }
109
110 #[inline]
112 pub fn get(&self, id: EntityId) -> &EntityMeta {
113 &self.entries[id.raw_index()]
114 }
115
116 pub fn get_mut(&mut self, id: EntityId) -> &mut EntityMeta {
118 &mut self.entries[id.raw_index()]
119 }
120
121 #[inline]
127 pub fn get_by_index(&self, index: usize) -> &EntityMeta {
128 &self.entries[index]
129 }
130
131 pub fn len(&self) -> usize {
133 self.entries.len()
134 }
135
136 pub fn truncate(&mut self, n: usize) {
148 self.entries.truncate(n);
149 }
150
151 pub fn is_empty(&self) -> bool {
153 self.entries.is_empty()
154 }
155}
156
157impl Default for EntityTable {
158 fn default() -> Self {
159 Self::new()
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166
167 #[test]
168 fn test_allocate_and_get() {
169 let mut table = EntityTable::new();
170 let id = table.allocate(0, 10, 0, false, 0);
171 assert_eq!(id, EntityId::local(0));
172 assert!(!id.is_global());
173 let meta = table.get(id);
174 assert_eq!(meta.offset, 0);
175 assert_eq!(meta.len, 10);
176 assert_eq!(meta.save_level, 0);
177 assert!(!meta.is_global());
178 }
179
180 #[test]
181 fn test_multiple_allocations() {
182 let mut table = EntityTable::new();
183 let id0 = table.allocate(0, 5, 0, false, 0);
184 let id1 = table.allocate(5, 10, 0, true, 0);
185 assert_eq!(id0, EntityId::local(0));
186 assert_eq!(id1, EntityId::global(1));
187 assert_eq!(table.len(), 2);
188 assert!(!id0.is_global());
189 assert!(id1.is_global());
190 }
191
192 #[test]
193 fn test_get_mut() {
194 let mut table = EntityTable::new();
195 let id = table.allocate(0, 5, 0, false, 0);
196 table.get_mut(id).offset = 100;
197 assert_eq!(table.get(id).offset, 100);
198 }
199
200 #[test]
201 fn test_global_flag() {
202 let mut table = EntityTable::new();
203 let id = table.allocate(0, 5, 0, false, 0);
204 assert!(!table.get(id).is_global());
205 table.get_mut(id).set_global(true);
206 assert!(table.get(id).is_global());
207 table.get_mut(id).set_global(false);
208 assert!(!table.get(id).is_global());
209 }
210
211 #[test]
212 fn test_save_level_tracking() {
213 let mut table = EntityTable::new();
214 let id = table.allocate(0, 5, 1, false, 0);
215 assert_eq!(table.get(id).save_level, 1);
216 table.get_mut(id).save_level = 2;
217 assert_eq!(table.get(id).save_level, 2);
218 }
219
220 #[test]
221 fn test_empty_table() {
222 let table = EntityTable::new();
223 assert_eq!(table.len(), 0);
224 assert!(table.is_empty());
225 }
226
227 #[test]
228 fn test_default() {
229 let table = EntityTable::default();
230 assert!(table.is_empty());
231 }
232
233 #[test]
234 fn test_len_after_allocations() {
235 let mut table = EntityTable::new();
236 table.allocate(0, 1, 0, false, 0);
237 table.allocate(1, 2, 0, false, 0);
238 table.allocate(3, 3, 0, false, 0);
239 assert_eq!(table.len(), 3);
240 assert!(!table.is_empty());
241 }
242}