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
use crate::prelude_lib::*;
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u8)]
pub enum Access {
Read,
Write,
}
pub unsafe trait Extract: Sized {
fn each_resource(f: &mut dyn FnMut(TypeId, Access));
type Owned;
unsafe fn extract(universe: &Universe, rez: &mut Rez) -> Self::Owned;
unsafe fn convert(universe: &Universe, owned: *mut Self::Owned) -> Self;
type Cleanup: Cleaner<Self>;
}
pub unsafe trait Cleaner<E: Extract> {
fn pre_cleanup(owned: E::Owned, universe: &Universe) -> Self;
fn post_cleanup(self, universe: &Universe);
}
unsafe impl<E: Extract> Cleaner<E> for () {
fn pre_cleanup(_owned: E::Owned, _universe: &Universe) -> Self {}
fn post_cleanup(self, _universe: &Universe) {}
}
pub unsafe trait ExtractOwned {
type Ty: Any;
const ACC: Access;
unsafe fn extract(universe: &Universe, rez: &mut Rez) -> Self;
}
unsafe impl<X> Extract for X
where
X: ExtractOwned,
{
fn each_resource(f: &mut dyn FnMut(TypeId, Access)) {
f(TypeId::of::<X::Ty>(), X::ACC)
}
type Owned = Option<X>;
unsafe fn extract(universe: &Universe, rez: &mut Rez) -> Self::Owned {
Some(X::extract(universe, rez))
}
unsafe fn convert(_universe: &Universe, owned: *mut Self::Owned) -> X {
(*owned).take().unwrap()
}
type Cleanup = ();
}
#[derive(Debug)]
pub struct Rez {
vals: &'static [(*mut dyn Any, Access)],
}
impl Rez {
pub(crate) fn new(vals: &'static [(*mut dyn Any, Access)]) -> Self {
Rez { vals }
}
pub unsafe fn take_ref<'b>(&mut self) -> &'b dyn Any {
let (v, a): (*mut dyn Any, Access) = self.vals[0];
assert_eq!(a, Access::Read, "asked for Access::Write but used take_ref");
self.vals = &self.vals[1..];
&mut *v
}
pub unsafe fn take_mut<'b>(&mut self) -> &'b mut dyn Any {
let (v, a): (*mut dyn Any, Access) = self.vals[0];
assert_eq!(a, Access::Write, "asked for Access::Read but used take_mut");
self.vals = &self.vals[1..];
&mut *v
}
pub unsafe fn take_ref_downcast<'b, T: Any>(&mut self) -> &'b T {
let got: &dyn Any = self.take_ref();
got.downcast_ref().unwrap()
}
pub unsafe fn take_mut_downcast<'b, T: Any>(&mut self) -> &'b mut T {
let got: &mut dyn Any = self.take_mut();
got.downcast_mut().unwrap()
}
}