1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::{ ptr, os::raw::c_void };
mod result_impl {
use super::*;
pub extern "C" fn dealloc<T, E>(object: *mut *mut c_void) {
let object = unsafe{ (object as *mut *mut Result<T, E>).as_mut() }
.expect("Unexpected NULL pointer");
if !object.is_null() {
let _result = unsafe{ Box::from_raw(*object) };
*object = ptr::null_mut();
}
}
pub extern "C" fn into_ok<T, E>(object: *mut *mut c_void) -> T {
let object = unsafe{ (object as *mut *mut Result<T, E>).as_mut() }
.expect("Unexpected NULL pointer");
assert!(!object.is_null(), "Unexpected NULL pointer");
let result = unsafe{ Box::from_raw(*object) };
*object = ptr::null_mut();
match *result {
Err(_) => panic!("Unexpected `Err`-value in result"),
Ok(r) => r
}
}
pub extern "C" fn into_err<T, E>(object: *mut *mut c_void) -> E {
let object = unsafe{ (object as *mut *mut Result<T, E>).as_mut() }
.expect("Unexpected NULL pointer");
assert!(!object.is_null(), "Unexpected NULL pointer");
let result = unsafe{ Box::from_raw(*object) };
*object = ptr::null_mut();
match *result {
Ok(_) => panic!("Unexpected `Ok`-value in result"),
Err(e) => e
}
}
pub extern "C" fn is_ok<T, E>(object: *const c_void) -> u8 {
let is_ok = unsafe{ (object as *const Result<T, E>).as_ref() }
.expect("Unexpected NULL pointer")
.is_ok();
match is_ok {
true => 1,
false => 0
}
}
}
#[repr(C)]
pub struct FfiResult<T, E> {
pub dealloc: extern "C" fn(*mut *mut c_void),
pub into_ok: extern "C" fn(*mut *mut c_void) -> T,
pub into_err: extern "C" fn(*mut *mut c_void) -> E,
pub is_ok: extern "C" fn(*const c_void) -> u8,
pub object: *mut c_void
}
impl<T, E> Into<Result<T, E>> for FfiResult<T, E> {
fn into(mut self) -> Result<T, E> {
match (self.is_ok)(self.object) {
1 => Ok((self.into_ok)(&mut self.object)),
0 => Err((self.into_err)(&mut self.object)),
i => panic!("`FfiResult::is_ok` returned an invalid value ({})", i)
}
}
}
impl<T, E> From<Result<T, E>> for FfiResult<T, E> {
fn from(result: Result<T, E>) -> Self {
Self {
dealloc: result_impl::dealloc::<T, E>,
into_ok: result_impl::into_ok::<T, E>,
into_err: result_impl::into_err::<T, E>,
is_ok: result_impl::is_ok::<T, E>,
object: Box::into_raw(Box::new(result)) as *mut c_void
}
}
}
impl<T, E> Drop for FfiResult<T, E> {
fn drop(&mut self) {
(self.dealloc)(&mut self.object)
}
}