use core::{
mem::{self, MaybeUninit},
num::NonZero,
};
use crate::ffi::binding;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Action {
None,
Ip(
NonZero<usize>,
),
Retry,
}
impl Action {
#[inline]
pub const fn encode(self) -> binding::mirilla_except_action {
let mut target_storage = MaybeUninit::<binding::mirilla_except_action>::zeroed();
let target_base = target_storage.as_mut_ptr().cast::<u8>();
let target_tag = target_base
.wrapping_add(mem::offset_of!(binding::mirilla_except_action, tag))
.cast::<u16>();
match self {
Self::None => {
unsafe {
target_tag.write(binding::MIRILLA_EXCEPT_ACTION_NONE as u16);
}
}
Self::Ip(target_address) => {
let address = target_address.get() as binding::virtual_address_t;
let ip = binding::mirilla_except_action_ip_context { address };
let action_context = binding::mirilla_except_action_context { ip };
let target_context = target_base
.wrapping_add(mem::offset_of!(binding::mirilla_except_action, context))
.cast::<binding::mirilla_except_action_context>();
unsafe { target_context.write(action_context) };
unsafe {
target_tag.write(binding::MIRILLA_EXCEPT_ACTION_IP as u16);
}
}
Self::Retry => {
unsafe {
target_tag.write(binding::MIRILLA_EXCEPT_ACTION_RETRY as u16);
}
}
}
unsafe { target_storage.assume_init() }
}
}