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
#![no_std]
mod utils;
pub(crate) use utils::*;
mod refs;
pub use refs::*;
use core::marker::PhantomPinned;
use core::pin::Pin;
#[pin_project::pin_project]
pub struct SelfReference<T, R>
where
for<'this> R: RefDef<'this>,
{
#[pin]
referential: <R as RefDef<'static>>::Type,
#[pin]
object: T,
__p: PhantomPinned,
}
impl<T, R> SelfReference<T, R>
where
for<'this> R: RefDef<'this>,
{
pub fn new<F>(object: T, init: F) -> Self
where
F: FnOnce() -> <R as RefDef<'static>>::Type,
{
Self {
object,
referential: (init)(),
__p: PhantomPinned,
}
}
pub fn reset<'s, F>(self: Pin<&'s mut Self>, f: F)
where
F: FnOnce(Pin<&'s mut T>) -> <R as RefDef<'s>>::Type,
{
let mut proj = self.project();
let value = unsafe { detach_lifetime_ref::<R>((f)(proj.object)) };
proj.referential.set(value);
}
pub fn pin_mut<'s>(self: Pin<&'s mut Self>) -> Pin<&'s mut <R as RefDef<'s>>::Type> {
let referential = self.project().referential;
unsafe { detach_lifetime_pin_mut::<R>(referential) }
}
pub fn pin_ref<'s>(self: Pin<&'s Self>) -> Pin<&'s <R as RefDef<'s>>::Type> {
let referential = self.project_ref().referential;
unsafe { detach_lifetime_pin_ref::<R>(referential) }
}
}
impl<T, R> SelfReference<T, R>
where
for<'this> R: RefDef<'this>,
for<'this> <R as RefDef<'this>>::Type: Unpin,
{
pub fn get_mut<'s>(self: Pin<&'s mut Self>) -> &'s mut <R as RefDef<'s>>::Type {
self.pin_mut().get_mut()
}
pub fn get_ref<'s>(self: Pin<&'s Self>) -> &'s <R as RefDef<'s>>::Type {
self.pin_ref().get_ref()
}
}
impl<T, R> SelfReference<T, R>
where
for<'this> R: RefDef<'this>,
T: Unpin,
{
pub fn reset_unpin<'s, F>(self: Pin<&'s mut Self>, f: F)
where
F: FnOnce(&'s mut T) -> <R as RefDef<'s>>::Type,
{
let mut proj = self.project();
let value = unsafe { detach_lifetime_ref::<R>((f)(proj.object.get_mut())) };
proj.referential.set(value);
}
}