use core::cell::UnsafeCell;
const ALIGN: usize = 1;
struct Header(UnsafeCell<[u32; 3]>);
unsafe impl Sync for Header {}
static HEADER: Header = Header(UnsafeCell::new([0; 3]));
pub fn alloc(len: u32) -> *mut u8 {
if len == 0 {
return ALIGN as *mut u8; }
let layout = core::alloc::Layout::from_size_align(len as usize, ALIGN)
.expect("a byte layout is always valid");
unsafe { std::alloc::alloc(layout) }
}
pub unsafe fn dealloc(ptr: *mut u8, len: u32) {
if len == 0 {
return;
}
let layout = core::alloc::Layout::from_size_align(len as usize, ALIGN)
.expect("a byte layout is always valid");
unsafe { std::alloc::dealloc(ptr, layout) }
}
pub unsafe fn dispatch<F, E>(
src_ptr: *const u8,
src_len: u32,
cfg_ptr: *const u8,
cfg_len: u32,
handler: F,
) -> *const u32
where
F: FnOnce(&str, &str) -> Result<String, E>,
E: core::fmt::Display,
{
let src = unsafe { core::slice::from_raw_parts(src_ptr, src_len as usize) };
let cfg = unsafe { core::slice::from_raw_parts(cfg_ptr, cfg_len as usize) };
let (text, ok) = match (core::str::from_utf8(src), core::str::from_utf8(cfg)) {
(Ok(src), Ok(cfg)) => match handler(src, cfg) {
Ok(out) => (out, 1),
Err(e) => (e.to_string(), 0),
},
_ => ("source and config must both be utf-8".to_owned(), 0),
};
publish(text, ok)
}
fn publish(text: String, ok: u32) -> *const u32 {
let bytes = text.as_bytes();
let len = bytes.len() as u32;
let out = alloc(len);
if len > 0 {
unsafe { core::ptr::copy_nonoverlapping(bytes.as_ptr(), out, len as usize) };
}
let header = HEADER.0.get();
unsafe { *header = [out as u32, len, ok] };
header.cast()
}