self_reference/
lib.rs

1#![no_std]
2
3#[cfg(feature = "std")]
4extern crate std;
5
6mod utils;
7pub(crate) use utils::*;
8
9mod refs;
10pub use refs::*;
11
12use core::marker::PhantomPinned;
13use core::ops::DerefMut;
14use core::pin::Pin;
15
16use pin_project::{pin_project, UnsafeUnpin};
17use stable_deref_trait::StableDeref;
18
19/// A Self-Referential Helper.
20#[pin_project(UnsafeUnpin)]
21pub struct SelfReference<'a, T, R>
22where
23    R: RefDef + 'a,
24{
25    // SAFETY-NOTE: 'static lifetime is only for placeholder because there is no like 'this or 'phantom lifetime on rust.
26    //              using referential object as 'static lifetime is unsound! NEVER use it.
27    #[pin]
28    referential: R::Type<'a>,
29    #[pin]
30    object: T,
31
32    __private: PhantomPinned,
33}
34
35impl<'a, T, R> SelfReference<'a, T, R>
36where
37    R: RefDef + 'a,
38{
39    /// You will "never" able to hold object before its pinned.
40    /// try initializing as empty static object. (using Option, NonNull or Empty enum field)
41    pub fn new<F>(object: T, init: F) -> Self
42    where
43        R: 'static,
44        F: FnOnce() -> R::Type<'static>,
45    {
46        let referential = unsafe { detach_lifetime_ref::<R>((init)()) };
47
48        Self {
49            object,
50            referential,
51            __private: PhantomPinned,
52        }
53    }
54
55    pub fn new_stable<F>(mut object: T, init: F) -> Self
56    where
57        T: StableDeref + DerefMut,
58        F: FnOnce(&mut T::Target) -> R::Type<'_>,
59    {
60        let referential = unsafe { detach_lifetime_ref::<R>((init)(object.deref_mut())) };
61
62        Self {
63            object,
64            referential,
65            __private: PhantomPinned,
66        }
67    }
68
69    /// reset referenceial object using object.
70    /// object is now pinned so initializing referential type is safe.
71    /// This is also useful when you consumed your own reference. (like in AsyncIterator)
72    pub fn reset<'s, F>(self: Pin<&'s mut Self>, f: F)
73    where
74        F: FnOnce(Pin<&'s mut T>) -> R::Type<'s>,
75    {
76        let mut proj = self.project();
77
78        let value = unsafe { detach_lifetime_ref::<R>((f)(proj.object)) };
79        proj.referential.set(value);
80    }
81
82    /// get pinned mutable referencial object that has self lifetime.
83    pub fn pin_mut<'s>(self: Pin<&'s mut Self>) -> Pin<&'s mut R::Type<'s>> {
84        let referential = self.project().referential;
85        unsafe { detach_lifetime_pin_mut::<R>(referential) }
86    }
87
88    /// get pinned referencial object that has self lifetime.
89    pub fn pin_ref<'s>(self: Pin<&'s Self>) -> Pin<&'s R::Type<'s>> {
90        let referential = self.project_ref().referential;
91        unsafe { detach_lifetime_pin_ref::<R>(referential) }
92    }
93}
94
95impl<'a, T, R> SelfReference<'a, T, R>
96where
97    R: RefDef,
98    T: Unpin,
99{
100    /// reset referenceial object using unpinned object.
101    /// object is now pinned so initializing referential type is safe.
102    /// This is also useful when you consumed your own reference. (like in AsyncIterator)
103    pub fn reset_unpin<'s, F>(self: Pin<&'s mut Self>, f: F)
104    where
105        F: FnOnce(&'s mut T) -> R::Type<'s>,
106    {
107        let mut proj = self.project();
108
109        let value = unsafe { detach_lifetime_ref::<R>((f)(proj.object.get_mut())) };
110        proj.referential.set(value);
111    }
112}
113
114impl<'a, T, R> SelfReference<'a, T, R>
115where
116    R: RefDef,
117    T: StableDeref
118{
119    pub fn map<'s, F, N>(self, f: F) -> SelfReference<'a, T, N>
120    where
121        for<'this> <R as refs::RefDef>::Type<'this>: Unpin,
122        T: 's,
123        R: 's,
124        
125        N: RefDef + 's,
126        F: FnOnce(R::Type<'s>) -> N::Type<'s>,
127    {
128        let r = unsafe { detach_lifetime_ref::<R>(self.referential) };
129        let r = unsafe { detach_lifetime_ref::<N>((f)(r)) };
130
131        SelfReference {
132            object: self.object,
133            referential: r,
134            __private: PhantomPinned
135        }
136    }
137
138    pub fn get_ref<'s>(&'s self) -> &'s R::Type<'s> {
139        unsafe { detach_lifetime_get_ref::<R>(&self.referential) }
140    }
141
142    // get mutable reference from stable referential object.
143    pub fn get_mut<'s>(&'s mut self) -> &'s mut R::Type<'s> {
144        unsafe { detach_lifetime_get_mut::<R>(&mut self.referential) }
145    }
146
147    pub fn into_inner(self) -> T {
148        self.object
149    }
150}
151
152unsafe impl<'a, T, R> UnsafeUnpin for SelfReference<'a, T, R>
153where
154    R: RefDef,
155    T: StableDeref,
156{
157}