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
use std::{any::Any, ffi::c_void, fmt, io::Error as IoError, sync::Arc};
mod fatptr;
#[derive(Debug)]
pub enum Error {
Io(IoError),
Cast,
Encoding,
}
impl From<IoError> for Error {
#[inline(always)]
fn from(x: IoError) -> Error {
Error::Io(x)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Io(e) => fmt::Display::fmt(e, f),
Error::Cast => write!(f, "wrapper cast failed"),
Error::Encoding => write!(
f,
"byte sequence is not representable in the platform encoding"
),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[must_use]
pub struct Object {
pub data: *const c_void,
pub meta: usize,
}
pub struct FFIResult {
pub data: Object,
pub is_success: bool,
}
pub type RealOptObj = Option<Arc<dyn Any + Send + Sync>>;
impl Object {
pub fn is_null(&self) -> bool {
self.data.is_null() && self.meta == 0
}
}
impl From<RealOptObj> for Object {
fn from(x: RealOptObj) -> Object {
match x {
Some(y) => unsafe {
let [data, meta] = crate::fatptr::decomp(Arc::into_raw(y));
Object {
data: data as *const c_void,
meta,
}
},
None => Object {
data: std::ptr::null(),
meta: 0,
},
}
}
}
impl Into<RealOptObj> for Object {
fn into(self) -> RealOptObj {
if !self.is_null() {
Some(unsafe { Arc::from_raw(crate::fatptr::recomp([self.data as usize, self.meta])) })
} else {
None
}
}
}
impl From<Result<Object, Object>> for FFIResult {
#[inline]
fn from(x: Result<Object, Object>) -> FFIResult {
let is_success = x.is_ok();
FFIResult {
data: match x {
Ok(y) | Err(y) => y,
},
is_success,
}
}
}
#[inline]
pub fn wrap<T>(x: T) -> Object
where
T: Send + Sync + 'static,
{
Some(Arc::new(x) as Arc<dyn Any + Send + Sync + 'static>).into()
}
#[inline]
pub fn wrapres<T, E>(x: Result<T, E>) -> FFIResult
where
T: Send + Sync + 'static,
E: Send + Sync + 'static,
{
x.map(wrap::<T>).map_err(wrap::<E>).into()
}