use core::alloc::Layout;
use core::marker::PhantomData;
use core::ptr::NonNull;
use crate::constructor::{Construct, Opaque, PinConstruct, Slot};
#[must_use = "constructor must be initialized"]
pub struct Closure<T, F>(F, PhantomData<T>);
unsafe impl<T, U, F> PinConstruct for Closure<T, F>
where
U: ?Sized,
F: FnOnce(Slot<T>) -> &mut Opaque<U>,
{
type Object = U;
fn layout(&self) -> Layout {
Layout::new::<T>()
}
unsafe fn construct(self, slot: Slot) -> NonNull<Self::Object> {
let ptr = (self.0)(slot.cast());
NonNull::from(ptr.as_mut())
}
}
unsafe impl<T, U, F> Construct for Closure<T, F>
where
U: ?Sized,
F: FnOnce(Slot<T>) -> &mut Opaque<U>,
{
}
#[inline(always)]
pub fn from_closure<T, U, F>(f: F) -> Closure<T, F>
where
U: ?Sized,
F: FnOnce(Slot<T>) -> &mut Opaque<U>,
{
Closure(f, PhantomData)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::{randstr, OpqStrFut};
use crate::PinDynify;
#[pollster::test]
async fn from_closure_works() {
let inp = randstr(8..64);
let init = from_closure(|slot| slot.write(async { inp.clone() }) as &mut OpqStrFut);
assert_eq!(init.pin_boxed().await, inp);
}
}