scope_lock/extended/
func.rs

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}