1use core::marker::PhantomData;
2use core::mem;
3use core::ptr;
4
5use crate::Extender;
6use crate::pointer_like::erased_static::{fn_call, fn_call_mut, fn_call_once, fn_drop};
7use crate::pointer_like::{PointerDeref, PointerDerefMut, PointerIntoInner};
8
9use super::{UnsafeAssertSend, UnsafeAssertSync};
10
11impl<'scope, 'env> Extender<'scope, 'env> {
12 pub fn fn_once<'extended, P, I, O>(
13 &'scope self,
14 f: P,
15 ) -> impl FnOnce(I) -> O + Send + Sync + 'extended
16 where
17 'extended: 'scope,
18 P: PointerIntoInner + Send,
19 P::Pointee: FnOnce(I) -> O,
20 I: Send + 'extended,
21 O: Send + 'extended,
22 {
23 let f = unsafe {
24 self.associate_reference(UnsafeAssertSync(UnsafeAssertSend(
25 extend_fn_once_unchecked(f),
26 )))
27 };
28 move |i| {
29 let f = f;
30 f.inner.0.0(i)
31 }
32 }
33
34 pub fn fn_mut<'extended, P, I, O>(
35 &'scope self,
36 f: P,
37 ) -> impl FnMut(I) -> O + Send + Sync + 'extended
38 where
39 'extended: 'scope,
40 P: PointerDerefMut + Send,
41 P::Pointee: FnMut(I) -> O,
42 I: Send + 'extended,
43 O: Send + 'extended,
44 {
45 let mut f = unsafe {
46 self.associate_reference(UnsafeAssertSync(UnsafeAssertSend(extend_fn_mut_unchecked(
47 f,
48 ))))
49 };
50 move |i| {
51 let f = &mut f;
52 f.inner.0.0(i)
53 }
54 }
55
56 pub fn fn_<'extended, P, I, O>(&'scope self, f: P) -> impl Fn(I) -> O + Send + Sync + 'extended
57 where
58 'extended: 'scope,
59 P: PointerDeref + Send,
60 P::Pointee: Fn(I) -> O + Sync,
61 I: Send + 'extended,
62 O: Send + 'extended,
63 {
64 let f = unsafe {
65 self.associate_reference(UnsafeAssertSync(UnsafeAssertSend(extend_fn_unchecked(f))))
66 };
67 move |i| {
68 let f = &f;
69 f.inner.0.0(i)
70 }
71 }
72
73 pub fn fn_unsync<'extended, P, I, O>(&'scope self, f: P) -> impl Fn(I) -> O + Send + 'extended
74 where
75 'extended: 'scope,
76 P: PointerDeref + Send,
77 P::Pointee: Fn(I) -> O,
78 I: Send + 'extended,
79 O: Send + 'extended,
80 {
81 let f = unsafe { self.associate_reference(UnsafeAssertSend(extend_fn_unchecked(f))) };
82 move |i| {
83 let f = &f;
84 f.inner.0(i)
85 }
86 }
87}
88
89pub unsafe fn extend_fn_once_unchecked<'a, F, I, O>(f: F) -> impl FnOnce(I) -> O + 'a
90where
91 F: PointerIntoInner,
92 F::Pointee: FnOnce(I) -> O,
93 I: 'a,
94 O: 'a,
95{
96 let f = unsafe {
97 ErasedFn {
98 ptr: ptr::NonNull::new_unchecked(f.into_ptr() as *mut ()),
99 call: fn_call_once::<F, I, O>(),
100 drop: fn_drop::<F>(),
101 _marker: PhantomData,
102 }
103 };
104 move |i| f.call_once(i)
105}
106
107pub unsafe fn extend_fn_mut_unchecked<'a, F, I, O>(f: F) -> impl FnMut(I) -> O + 'a
108where
109 F: PointerDerefMut,
110 F::Pointee: FnMut(I) -> O,
111 I: 'a,
112 O: 'a,
113{
114 let mut f = unsafe {
115 ErasedFn {
116 ptr: ptr::NonNull::new_unchecked(f.into_ptr() as *mut ()),
117 call: fn_call_mut::<F, I, O>(),
118 drop: fn_drop::<F>(),
119 _marker: PhantomData,
120 }
121 };
122 move |i| f.call_mut(i)
123}
124
125pub unsafe fn extend_fn_unchecked<'a, F, I, O>(f: F) -> impl Fn(I) -> O + 'a
126where
127 F: PointerDeref,
128 F::Pointee: Fn(I) -> O,
129 I: 'a,
130 O: 'a,
131{
132 let f = unsafe {
133 ErasedFn {
134 ptr: ptr::NonNull::new_unchecked(f.into_ptr() as *mut ()),
135 call: fn_call::<F, I, O>(),
136 drop: fn_drop::<F>(),
137 _marker: PhantomData,
138 }
139 };
140 move |i| f.call(i)
141}
142
143struct ErasedFn<C, I, O, D: Fn(*mut ())> {
144 ptr: ptr::NonNull<()>,
145 drop: D,
146 call: C,
147 _marker: PhantomData<fn(I) -> O>,
148}
149
150impl<C, I, O, D: Fn(*mut ())> ErasedFn<C, I, O, D>
151where
152 C: Fn(*mut (), I) -> O,
153{
154 fn call_once(self, input: I) -> O {
155 let this = mem::ManuallyDrop::new(self);
156 (this.call)(this.ptr.as_ptr(), input)
157 }
158
159 fn call_mut(&mut self, input: I) -> O {
160 (self.call)(self.ptr.as_ptr(), input)
161 }
162}
163
164impl<C, I, O, D: Fn(*mut ())> ErasedFn<C, I, O, D>
165where
166 C: Fn(*const (), I) -> O,
167{
168 fn call(&self, input: I) -> O {
169 (self.call)(self.ptr.as_ptr(), input)
170 }
171}
172
173impl<C, I, O, D: Fn(*mut ())> Drop for ErasedFn<C, I, O, D> {
174 fn drop(&mut self) {
175 (self.drop)(self.ptr.as_ptr())
176 }
177}