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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::{ ptr, os::raw::c_void };
mod result_impl {
use super::*;
pub unsafe extern "C" fn dealloc<T, E>(object: *mut FfiResult<T, E>) {
let object = (object as *mut *mut Result<T, E>).as_mut()
.expect("Unexpected NULL pointer");
if !object.is_null() {
let _result = Box::from_raw(*object);
*object = ptr::null_mut();
}
}
pub unsafe extern "C" fn into_ok<T, E>(object: *mut FfiResult<T, E>) -> T {
let object = (object as *mut *mut Result<T, E>).as_mut()
.expect("Unexpected NULL pointer");
assert!(!object.is_null(), "Unexpected NULL pointer");
let result = Box::from_raw(*object);
*object = ptr::null_mut();
match *result {
Err(_) => panic!("Unexpected `Err`-value in result"),
Ok(r) => r
}
}
pub unsafe extern "C" fn into_err<T, E>(object: *mut FfiResult<T, E>) -> E {
let object = (object as *mut *mut Result<T, E>).as_mut()
.expect("Unexpected NULL pointer");
assert!(!object.is_null(), "Unexpected NULL pointer");
let result = Box::from_raw(*object);
*object = ptr::null_mut();
match *result {
Ok(_) => panic!("Unexpected `Ok`-value in result"),
Err(e) => e
}
}
pub unsafe extern "C" fn is_ok<T, E>(object: *const FfiResult<T, E>) -> u8 {
let is_ok = (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: unsafe extern "C" fn(*mut Self),
pub into_ok: unsafe extern "C" fn(*mut Self) -> T,
pub into_err: unsafe extern "C" fn(*mut Self) -> E,
pub is_ok: unsafe extern "C" fn(*const Self) -> u8,
pub object: *mut c_void
}
impl<T, E> FfiResult<T, E> {
pub fn into_result(self) -> Result<T, E> {
self.into()
}
pub fn map<R>(self, f: impl FnOnce(T) -> R) -> Result<R, E> {
self.into_result().map(f)
}
pub fn map_err<R>(self, f: impl FnOnce(E) -> R) -> Result<T, R> {
self.into_result().map_err(f)
}
}
impl<T, E> Into<Result<T, E>> for FfiResult<T, E> {
fn into(mut self) -> Result<T, E> {
match unsafe{ (self.is_ok)(&self) } {
1 => Ok(unsafe{ (self.into_ok)(&mut self) }),
0 => Err(unsafe{ (self.into_err)(&mut self) }),
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) {
unsafe{ (self.dealloc)(self) }
}
}