extern crate alloc;
use core::ffi::{c_char, c_void};
use crate::platform::{ConsoleLevel, ConsoleProvider};
use super::{ConsoleCallbackWrapper, TsRunConsoleFn, TsRunConsoleLevel, TsRunContext, TsRunResult};
pub struct FfiConsoleProvider {
ctx_ptr: *mut c_void,
}
impl FfiConsoleProvider {
pub fn new(ctx_ptr: *mut c_void) -> Self {
Self { ctx_ptr }
}
fn get_callback(&self) -> Option<&ConsoleCallbackWrapper> {
if self.ctx_ptr.is_null() {
return None;
}
let ctx = unsafe { &*(self.ctx_ptr as *const TsRunContext) };
ctx.console_callback.as_ref()
}
}
impl ConsoleProvider for FfiConsoleProvider {
fn write(&self, level: ConsoleLevel, message: &str) {
let Some(wrapper) = self.get_callback() else {
return; };
let c_level = match level {
ConsoleLevel::Log => TsRunConsoleLevel::Log,
ConsoleLevel::Info => TsRunConsoleLevel::Info,
ConsoleLevel::Debug => TsRunConsoleLevel::Debug,
ConsoleLevel::Warn => TsRunConsoleLevel::Warn,
ConsoleLevel::Error => TsRunConsoleLevel::Error,
};
(wrapper.callback)(
c_level,
message.as_ptr() as *const c_char,
message.len(),
wrapper.userdata,
);
}
fn clear(&self) {
let Some(wrapper) = self.get_callback() else {
return;
};
(wrapper.callback)(TsRunConsoleLevel::Clear, c"".as_ptr(), 0, wrapper.userdata);
}
}
#[unsafe(no_mangle)]
pub extern "C" fn tsrun_set_console(
ctx: *mut TsRunContext,
func: Option<TsRunConsoleFn>,
userdata: *mut c_void,
) -> TsRunResult {
let ctx = match unsafe { ctx.as_mut() } {
Some(c) => c,
None => {
return TsRunResult {
ok: false,
error: c"NULL context".as_ptr(),
};
}
};
ctx.clear_error();
ctx.console_callback = func.map(|callback| ConsoleCallbackWrapper { callback, userdata });
TsRunResult::success()
}