use crate::{FlowContext, TrapHandler};
use core::{
marker::PhantomData,
mem::{forget, MaybeUninit},
ops::{Deref, DerefMut},
ptr::NonNull,
};
pub type EntireHandler<T> = extern "C" fn(EntireContext<T>) -> EntireResult;
#[repr(transparent)]
pub struct EntireContext<T: 'static = ()>(NonNull<TrapHandler>, PhantomData<T>);
impl<T: 'static> EntireContext<T> {
#[inline]
pub fn split(mut self) -> (EntireContextSeparated, FastMail<T>) {
let mail = unsafe { &mut *self.0.as_mut().locate_fast_mail() };
let mut handler = self.0;
forget(self);
(
EntireContextSeparated(unsafe { handler.as_mut() }),
FastMail(mail),
)
}
}
impl<T: 'static> Drop for EntireContext<T> {
#[inline]
fn drop(&mut self) {
unsafe { (*self.0.as_mut().locate_fast_mail::<T>()).assume_init_drop() }
}
}
#[repr(transparent)]
pub struct EntireContextSeparated(&'static mut TrapHandler);
impl EntireContextSeparated {
#[inline]
pub fn regs(&mut self) -> &mut FlowContext {
unsafe { self.0.context.as_mut() }
}
#[inline]
pub fn restore(self) -> EntireResult {
EntireResult::Restore
}
}
#[repr(transparent)]
pub struct FastMail<T: 'static>(&'static mut MaybeUninit<T>);
impl<T: 'static> FastMail<T> {
#[inline]
pub fn get(self) -> T {
let ans = unsafe { core::mem::replace(self.0, MaybeUninit::uninit()).assume_init() };
forget(self);
ans
}
}
impl<T: 'static> Deref for FastMail<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { self.0.assume_init_ref() }
}
}
impl<T: 'static> DerefMut for FastMail<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.0.assume_init_mut() }
}
}
impl<T: 'static> Drop for FastMail<T> {
#[inline]
fn drop(&mut self) {
unsafe { self.0.assume_init_drop() }
}
}
#[repr(usize)]
pub enum EntireResult {
FastCall = 0,
Call = 1,
Restore = 3,
}