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
use std::marker::PhantomData;
use std::mem::size_of;
use std::mem::take;
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::ops::DerefMut;
pub unsafe trait Scoped<'s>
where
Self: Sized,
{
type Args;
fn enter_scope(buf: &mut MaybeUninit<Self>, args: Self::Args) -> ();
}
pub struct Scope<'s, S>(ScopeState<'s, S>)
where
S: Scoped<'s>;
enum ScopeState<'s, S>
where
S: Scoped<'s>,
{
Empty,
New(S::Args),
Uninit(MaybeUninit<S>),
Ready(Entered<'s, S>),
}
#[repr(transparent)]
pub struct Entered<'s, S>(S, PhantomData<&'s ()>);
impl<'s, S> Scope<'s, S>
where
S: Scoped<'s>,
{
pub(crate) fn new(args: S::Args) -> Self {
Self(ScopeState::New(args))
}
pub fn enter(&'s mut self) -> &'s mut Entered<S> {
assert_eq!(size_of::<S>(), size_of::<MaybeUninit<S>>());
assert_eq!(size_of::<S>(), size_of::<Entered<S>>());
use ScopeState::*;
let state = &mut self.0;
let args = match take(state) {
New(f) => f,
_ => unreachable!(),
};
*state = Uninit(MaybeUninit::uninit());
let buf = match state {
Uninit(b) => b,
_ => unreachable!(),
};
S::enter_scope(buf, args);
*state = match take(state) {
Uninit(b) => Ready(unsafe { b.assume_init() }.into()),
_ => unreachable!(),
};
match state {
Ready(v) => &mut *v,
_ => unreachable!(),
}
}
}
impl<'s, S> Default for ScopeState<'s, S>
where
S: Scoped<'s>,
{
fn default() -> Self {
Self::Empty
}
}
impl<'s, S> From<S> for Entered<'s, S> {
fn from(value: S) -> Self {
Self(value, PhantomData)
}
}
impl<'s, S> Deref for Entered<'s, S> {
type Target = S;
fn deref(&self) -> &S {
unsafe { &*(self as *const _ as *const S) }
}
}
impl<'s, S> DerefMut for Entered<'s, S> {
fn deref_mut(&mut self) -> &mut S {
unsafe { &mut *(self as *mut _ as *mut S) }
}
}