1use std::any::TypeId;
2use std::marker::PhantomData;
3
4use hashbrown::hash_map::{Entry, HashMap};
5use mopa::Any;
6
7use crate::resource::{Resource, ResourceId};
8
9use super::World;
10
11pub struct MetaTable<T: ?Sized> {
82 fat: Vec<FatPtr>,
83 tys: Vec<TypeId>,
84 indices: HashMap<TypeId, usize>,
85 marker: PhantomData<Invariant<T>>,
86}
87
88impl<T: ?Sized> MetaTable<T> {
89 pub fn new() -> Self {
91 assert_unsized::<T>();
92
93 Default::default()
94 }
95
96 pub fn register<R>(&mut self, r: &R)
100 where
101 R: Resource,
102 T: CastFrom<R> + 'static,
103 {
104 let thin_ptr = r as *const R as usize;
105 let casted_ptr = <T as CastFrom<R>>::cast(r);
106 let thin_casted_ptr = casted_ptr as *const T as *const () as usize;
107
108 assert_eq!(
109 thin_ptr, thin_casted_ptr,
110 "Bug: `CastFrom` did not cast `self`"
111 );
112
113 let fat = unsafe { FatPtr::from_ptr(casted_ptr) };
114
115 let ty_id = TypeId::of::<R>();
116
117 let len = self.indices.len();
119 match self.indices.entry(ty_id) {
120 Entry::Occupied(occ) => {
121 let ind = *occ.get();
122
123 self.fat[ind] = fat;
124 }
125 Entry::Vacant(vac) => {
126 vac.insert(len);
127
128 self.fat.push(fat);
129 self.tys.push(ty_id);
130 }
131 }
132 }
133
134 pub fn get<'a>(&self, res: &'a dyn Resource) -> Option<&'a T> {
138 unsafe {
139 self.indices
140 .get(&Any::get_type_id(res))
141 .map(move |&ind| &*self.fat[ind].create_ptr(res as *const _ as *const ()))
142 }
143 }
144
145 pub fn get_mut<'a>(&self, res: &'a dyn Resource) -> Option<&'a mut T> {
149 unsafe {
150 self.indices.get(&Any::get_type_id(res)).map(move |&ind| {
151 &mut *(self.fat[ind].create_ptr::<T>(res as *const _ as *const ()) as *mut T)
152 })
153 }
154 }
155
156 pub fn iter<'a>(&'a self, res: &'a World) -> MetaIter<'a, T> {
158 MetaIter {
159 fat: &self.fat,
160 index: 0,
161 world: res,
162 tys: &self.tys,
163 marker: PhantomData,
164 }
165 }
166
167 pub fn iter_mut<'a>(&'a self, res: &'a World) -> MetaIterMut<'a, T> {
169 MetaIterMut {
170 fat: &self.fat,
171 index: 0,
172 world: res,
173 tys: &self.tys,
174 marker: PhantomData,
175 }
176 }
177}
178
179impl<T> Default for MetaTable<T>
180where
181 T: ?Sized,
182{
183 fn default() -> Self {
184 MetaTable {
185 fat: Default::default(),
186 indices: Default::default(),
187 tys: Default::default(),
188 marker: Default::default(),
189 }
190 }
191}
192
193struct FatPtr(usize);
194
195impl FatPtr {
196 unsafe fn from_ptr<T: ?Sized>(t: &T) -> Self {
197 use std::ptr::read;
198
199 assert_unsized::<T>();
200
201 let fat_ptr = &t as *const &T as *const usize;
202 let vtable = read::<usize>(fat_ptr.offset(1));
208
209 Self(vtable)
210 }
211
212 unsafe fn create_ptr<T: ?Sized>(&self, ptr: *const ()) -> *const T {
213 let fat_ptr: (*const (), usize) = (ptr, self.0);
214
215 *(&fat_ptr as *const (*const (), usize) as *const *const T)
216 }
217}
218
219pub unsafe trait CastFrom<T> {
252 fn cast(t: &T) -> &Self;
254
255 fn cast_mut(t: &mut T) -> &mut Self;
257}
258
259struct Invariant<T: ?Sized>(*mut T);
263
264unsafe impl<T> Send for Invariant<T> where T: ?Sized {}
265
266unsafe impl<T> Sync for Invariant<T> where T: ?Sized {}
267
268pub struct MetaIter<'a, T: ?Sized + 'a> {
270 index: usize,
271 fat: &'a [FatPtr],
272 tys: &'a [TypeId],
273 world: &'a World,
274 marker: PhantomData<Invariant<T>>,
275}
276
277impl<'a, T> Iterator for MetaIter<'a, T>
278where
279 T: ?Sized + 'a,
280{
281 type Item = &'a T;
282
283 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
284 let index = self.index;
285 self.index += 1;
286
287 let res_id: ResourceId = match self.tys.get(index) {
288 Some(&x) => x.into(),
289 None => return None,
290 };
291
292 unsafe {
294 self.world
295 .resource_raw(&res_id)
296 .map(|res| {
297 self.fat[index].create_ptr::<T>(Box::as_ref(&res.borrow())
298 as *const dyn Resource
299 as *const ())
300 })
301 .map(|ptr| &*ptr)
302 .or_else(|| self.next())
303 }
304 }
305}
306
307pub struct MetaIterMut<'a, T: ?Sized + 'a> {
309 index: usize,
310 fat: &'a [FatPtr],
311 tys: &'a [TypeId],
312 world: &'a World,
313 marker: PhantomData<Invariant<T>>,
314}
315
316impl<'a, T> Iterator for MetaIterMut<'a, T>
317where
318 T: ?Sized + 'a,
319{
320 type Item = &'a mut T;
321
322 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
323 let index = self.index;
324 self.index += 1;
325
326 let res_id: ResourceId = match self.tys.get(index) {
327 Some(&x) => x.into(),
328 None => return None,
329 };
330
331 unsafe {
333 self.world
334 .resource_raw(&res_id)
335 .map(|res| {
336 self.fat[index].create_ptr::<T>(Box::as_mut(&mut res.borrow_mut())
337 as *mut dyn Resource
338 as *const ()) as *mut T
339 })
340 .map(|ptr| &mut *ptr)
341 .or_else(|| self.next())
342 }
343 }
344}
345
346fn assert_unsized<T: ?Sized>() {
347 use std::mem::size_of;
348
349 assert_eq!(size_of::<&T>(), 2 * size_of::<usize>());
350}
351
352#[cfg(test)]
353mod tests {
354 use super::*;
355 use World;
356
357 trait Object {
358 fn method1(&self) -> i32;
359
360 fn method2(&mut self, x: i32);
361 }
362
363 unsafe impl<T> CastFrom<T> for dyn Object
364 where
365 T: Object + 'static,
366 {
367 fn cast(t: &T) -> &Self {
368 t
369 }
370
371 fn cast_mut(t: &mut T) -> &mut Self {
372 t
373 }
374 }
375
376 struct ImplementorA(i32);
377
378 impl Object for ImplementorA {
379 fn method1(&self) -> i32 {
380 self.0
381 }
382
383 fn method2(&mut self, x: i32) {
384 self.0 += x;
385 }
386 }
387
388 struct ImplementorB(i32);
389
390 impl Object for ImplementorB {
391 fn method1(&self) -> i32 {
392 self.0
393 }
394
395 fn method2(&mut self, x: i32) {
396 self.0 *= x;
397 }
398 }
399
400 #[test]
401 fn test_iter_all() {
402 let mut world = World::default();
403 world.insert(ImplementorA(3));
404 world.insert(ImplementorB(1));
405
406 let mut table = MetaTable::<dyn Object>::new();
407 table.register(&ImplementorA(125));
408 table.register(&ImplementorB(111_111));
409
410 {
411 let mut iter = table.iter(&world);
412 assert_eq!(iter.next().unwrap().method1(), 3);
413 assert_eq!(iter.next().unwrap().method1(), 1);
414 }
415
416 {
417 let mut iter_mut = table.iter_mut(&world);
418 let obj = iter_mut.next().unwrap();
419 obj.method2(3);
420 assert_eq!(obj.method1(), 6);
421 let obj = iter_mut.next().unwrap();
422 obj.method2(4);
423 assert_eq!(obj.method1(), 4);
424 }
425 }
426
427 #[test]
428 fn test_iter_all_after_removal() {
429 let mut world = World::default();
430 world.insert(ImplementorA(3));
431 world.insert(ImplementorB(1));
432
433 let mut table = MetaTable::<dyn Object>::new();
434 table.register(&ImplementorA(125));
435 table.register(&ImplementorB(111_111));
436
437 {
438 let mut iter = table.iter(&world);
439 assert_eq!(iter.next().unwrap().method1(), 3);
440 assert_eq!(iter.next().unwrap().method1(), 1);
441 }
442
443 world.remove::<ImplementorA>().unwrap();
444
445 {
446 let mut iter = table.iter(&world);
447 assert_eq!(iter.next().unwrap().method1(), 1);
448 }
449
450 world.remove::<ImplementorB>().unwrap();
451 }
452
453 struct ImplementorC;
454
455 impl Object for ImplementorC {
456 fn method1(&self) -> i32 {
457 33
458 }
459
460 fn method2(&mut self, _x: i32) {
461 unimplemented!()
462 }
463 }
464
465 struct ImplementorD;
466
467 impl Object for ImplementorD {
468 fn method1(&self) -> i32 {
469 42
470 }
471
472 fn method2(&mut self, _x: i32) {
473 unimplemented!()
474 }
475 }
476
477 #[test]
478 fn get() {
479 let mut world = World::default();
480 world.insert(ImplementorC);
481 world.insert(ImplementorD);
482
483 let mut table = MetaTable::<dyn Object>::new();
484 table.register(&ImplementorC);
485 table.register(&ImplementorD);
486
487 assert_eq!(
488 table
489 .get(&*world.resource::<ImplementorC>())
490 .unwrap()
491 .method1(),
492 33
493 );
494 assert_eq!(
495 table
496 .get(&*world.resource::<ImplementorD>())
497 .unwrap()
498 .method1(),
499 42
500 );
501
502 world.insert(table);
504 }
505}