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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#![no_std]

#[cfg(feature = "std")]
extern crate std;

mod utils;
pub(crate) use utils::*;

mod refs;
pub use refs::*;

use core::marker::PhantomPinned;
use core::ops::DerefMut;
use core::pin::Pin;

use pin_project::{pin_project, UnsafeUnpin};
use stable_deref_trait::StableDeref;

/// A Self-Referential Helper.
#[pin_project(UnsafeUnpin)]
pub struct SelfReference<'a, T, R>
where
    for<'this> R: RefDef<'this>,
    for<'this> <R as RefDef<'this>>::Type: 'a,
{
    // SAFETY-NOTE: 'static lifetime is only for placeholder because there is no like 'this or 'phantom lifetime on rust.
    //              using referential object as 'static lifetime is unsound! NEVER use it.
    #[pin]
    referential: <R as RefDef<'a>>::Type,
    #[pin]
    object: T,

    __private: PhantomPinned,
}

impl<'a, T, R> SelfReference<'a, T, R>
where
    for<'this> R: RefDef<'this>,
    for<'this> <R as RefDef<'this>>::Type: 'a,
{
    /// You will "never" able to hold object before its pinned.
    /// try initializing as empty static object. (using Option, NonNull or Empty enum field)
    pub fn new<F>(object: T, init: F) -> Self
    where
        F: FnOnce() -> <R as RefDef<'static>>::Type,
    {
        let referential = unsafe { detach_lifetime_ref::<R>((init)()) };

        Self {
            object,
            referential,
            __private: PhantomPinned,
        }
    }

    pub fn new_stable<F>(mut object: T, init: F) -> Self
    where
        T: StableDeref + DerefMut,
        F: FnOnce(&mut T::Target) -> <R as RefDef<'_>>::Type,
    {
        let referential = unsafe { detach_lifetime_ref::<R>((init)(object.deref_mut())) };

        Self {
            object,
            referential,
            __private: PhantomPinned,
        }
    }

    /// reset referenceial object using object.
    /// object is now pinned so initializing referential type is safe.
    /// This is also useful when you consumed your own reference. (like in AsyncIterator)
    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);
    }

    /// get pinned mutable referencial object that has self lifetime.
    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) }
    }

    /// get pinned referencial object that has self lifetime.
    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<'a, T, R> SelfReference<'a, T, R>
where
    for<'this> R: RefDef<'this>,
    for<'this> <R as RefDef<'this>>::Type: 'a,
    for<'this> <R as RefDef<'this>>::Type: Unpin,
{
    /// get mutable referencial object that has self lifetime.
    pub fn get_mut<'s>(self: Pin<&'s mut Self>) -> &'s mut <R as RefDef<'s>>::Type {
        self.pin_mut().get_mut()
    }

    /// get referencial object that has self lifetime.
    pub fn get_ref<'s>(self: Pin<&'s Self>) -> &'s <R as RefDef<'s>>::Type {
        self.pin_ref().get_ref()
    }
}

impl<'a, T, R> SelfReference<'a, T, R>
where
    for<'this> R: RefDef<'this>,
    for<'this> <R as RefDef<'this>>::Type: 'a,
    T: Unpin,
{
    /// reset referenceial object using unpinned object.
    /// object is now pinned so initializing referential type is safe.
    /// This is also useful when you consumed your own reference. (like in AsyncIterator)
    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);
    }
}

unsafe impl<'a, T, R> UnsafeUnpin for SelfReference<'a, T, R>
where
    for<'this> R: RefDef<'this>,
    for<'this> <R as RefDef<'this>>::Type: 'a,
    T: StableDeref,
{
}