add RocCallResult wrapper

This commit is contained in:
Folkert 2020-11-01 00:02:01 +01:00
parent 27598f6e78
commit 78c0a9f17d
2 changed files with 210 additions and 10 deletions

View file

@ -1,5 +1,8 @@
use std::ffi::CString;
use std::mem::MaybeUninit;
use std::os::raw::c_char;
use std::time::SystemTime;
use RocCallResult::*;
extern "C" {
#[link_name = "closure_1_exposed"]
@ -13,14 +16,19 @@ extern "C" {
pub fn rust_main() -> isize {
println!("Running Roc closure");
let start_time = SystemTime::now();
let (function_pointer, closure_data) = unsafe {
let mut output: MaybeUninit<(fn(i64) -> i64, i64)> = MaybeUninit::uninit();
let size = unsafe { closure_size() } as usize;
let roc_closure = unsafe {
let mut output: MaybeUninit<RocCallResult<(fn(i64) -> i64, i64)>> = MaybeUninit::uninit();
closure(output.as_mut_ptr() as _);
output.assume_init()
match output.assume_init().into() {
Ok((function_pointer, closure_data)) => move || function_pointer(closure_data),
Err(msg) => panic!("Roc failed with message: {}", msg),
}
};
let answer = function_pointer(closure_data);
let answer = roc_closure();
let end_time = SystemTime::now();
let duration = end_time.duration_since(start_time).unwrap();
@ -31,8 +39,30 @@ pub fn rust_main() -> isize {
answer
);
println!("closure size {:?}", unsafe { closure_size() });
// Exit code
0
}
#[repr(u64)]
pub enum RocCallResult<T> {
Success(T),
Failure(*mut c_char),
}
impl<T: Sized> Into<Result<T, String>> for RocCallResult<T> {
fn into(self) -> Result<T, String> {
match self {
Success(value) => Ok(value),
Failure(failure) => Err({
let raw = unsafe { CString::from_raw(failure) };
let result = format!("{:?}", raw);
// make sure rust does not try to free the Roc string
std::mem::forget(raw);
result
}),
}
}
}