#![deny(unsafe_op_in_unsafe_fn)]
use std::cell::RefCell;
thread_local! {
static OUT: RefCell<Vec<u8>> = const { RefCell::new(Vec::new()) };
}
#[no_mangle]
pub extern "C" fn techne_alloc(len: usize) -> *mut u8 {
Box::into_raw(vec![0u8; len].into_boxed_slice()).cast()
}
unsafe fn take(ptr: *mut u8, len: usize) -> Box<[u8]> {
unsafe { Box::from_raw(std::ptr::slice_from_raw_parts_mut(ptr, len)) }
}
#[no_mangle]
pub unsafe extern "C" fn techne_call(name: *mut u8, name_len: usize, args: *mut u8, args_len: usize) -> usize {
let (name, args) = unsafe { (take(name, name_len), take(args, args_len)) };
let answer = std::str::from_utf8(&name).map_err(|e| e.to_string()).and_then(|name| {
let args = serde_json::from_slice(&args).map_err(|e| format!("arguments: {e}"))?;
crate::call(name, &args)
});
let out = match answer {
Ok(v) => serde_json::json!({ "ok": v }),
Err(e) => serde_json::json!({ "err": e }),
};
OUT.with(|o| {
let mut o = o.borrow_mut();
*o = out.to_string().into_bytes();
o.len()
})
}
#[no_mangle]
pub extern "C" fn techne_out_ptr() -> *const u8 {
OUT.with(|o| o.borrow().as_ptr())
}