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#[pin_project(UnsafeUnpin)]
21pub struct SelfReference<'a, T, R>
22where
23 R: RefDef + 'a,
24{
25 #[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 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 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 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 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 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 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}