use std::ffi::CStr;
use std::marker::PhantomData;
use std::os::raw::{c_char, c_int, c_long, c_uint, c_void};
use std::rc::Rc;
use crate::sys;
#[derive(Copy, Clone)]
pub struct Opaque {
ptr: *mut c_void,
_not_send_sync: PhantomData<Rc<()>>,
}
impl Opaque {
pub(crate) fn new(ptr: *mut c_void) -> Self {
Self {
ptr,
_not_send_sync: PhantomData,
}
}
pub fn as_ptr(self) -> *mut c_void {
self.ptr
}
pub fn is_null(self) -> bool {
self.ptr.is_null()
}
pub unsafe fn cast_ref<T>(&self) -> Option<&T> {
unsafe { self.ptr.cast::<T>().as_ref() }
}
pub unsafe fn cast_mut<T>(&mut self) -> Option<&mut T> {
unsafe { self.ptr.cast::<T>().as_mut() }
}
}
#[derive(Copy, Clone)]
pub struct ErrorHandler(pub(crate) sys::riscv_error_func_t);
impl ErrorHandler {
pub const fn clear() -> Self {
Self(None)
}
pub unsafe fn new(
handler: unsafe extern "C" fn(*mut c_void, c_int, *const c_char, c_long),
) -> Self {
Self(Some(handler))
}
}
#[derive(Copy, Clone)]
pub struct StdoutHandler(pub(crate) sys::riscv_stdout_func_t);
impl StdoutHandler {
pub const fn clear() -> Self {
Self(None)
}
pub unsafe fn new(
handler: unsafe extern "C" fn(*mut c_void, *const c_char, c_uint),
) -> Self {
Self(Some(handler))
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ErrorType {
GeneralException,
MachineException,
MachineTimeout,
Unknown(i32),
}
impl ErrorType {
pub(crate) fn from_raw(code: c_int) -> Self {
match code {
sys::RISCV_ERROR_TYPE_GENERAL_EXCEPTION => Self::GeneralException,
sys::RISCV_ERROR_TYPE_MACHINE_EXCEPTION => Self::MachineException,
sys::RISCV_ERROR_TYPE_MACHINE_TIMEOUT => Self::MachineTimeout,
_ => Self::Unknown(code),
}
}
pub fn as_raw(self) -> i32 {
match self {
Self::GeneralException => sys::RISCV_ERROR_TYPE_GENERAL_EXCEPTION,
Self::MachineException => sys::RISCV_ERROR_TYPE_MACHINE_EXCEPTION,
Self::MachineTimeout => sys::RISCV_ERROR_TYPE_MACHINE_TIMEOUT,
Self::Unknown(code) => code,
}
}
}
pub struct ErrorContext<'a> {
error_type: ErrorType,
message: Option<&'a CStr>,
data: c_long,
opaque: Opaque,
}
impl<'a> ErrorContext<'a> {
#[doc(hidden)]
pub unsafe fn from_raw(
opaque: *mut c_void,
error_type: c_int,
msg: *const c_char,
data: c_long,
) -> Self {
let message = if msg.is_null() {
None
} else {
Some(unsafe { CStr::from_ptr(msg) })
};
Self {
error_type: ErrorType::from_raw(error_type),
message,
data,
opaque: Opaque::new(opaque),
}
}
pub fn error_type(&self) -> ErrorType {
self.error_type
}
pub fn message(&self) -> Option<&'a CStr> {
self.message
}
pub fn data(&self) -> c_long {
self.data
}
pub fn opaque(&self) -> Opaque {
self.opaque
}
}
pub struct StdoutContext<'a> {
data: &'a [u8],
opaque: Opaque,
}
impl<'a> StdoutContext<'a> {
#[doc(hidden)]
pub unsafe fn from_raw(opaque: *mut c_void, msg: *const c_char, len: c_uint) -> Self {
let data = if msg.is_null() || len == 0 {
&[]
} else {
unsafe { std::slice::from_raw_parts(msg as *const u8, len as usize) }
};
Self {
data,
opaque: Opaque::new(opaque),
}
}
pub fn data(&self) -> &'a [u8] {
self.data
}
pub fn opaque(&self) -> Opaque {
self.opaque
}
}