1use std::{any::Any, ffi::c_void, fmt, io::Error as IoError, sync::Arc};
2
3mod fatptr;
4
5#[derive(Debug)]
7pub enum Error {
8 Io(IoError),
9 Cast,
10 Encoding,
11}
12
13impl From<IoError> for Error {
14 #[inline(always)]
15 fn from(x: IoError) -> Error {
16 Error::Io(x)
17 }
18}
19
20impl fmt::Display for Error {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 Error::Io(e) => fmt::Display::fmt(e, f),
24 Error::Cast => write!(f, "wrapper cast failed"),
25 Error::Encoding => write!(
26 f,
27 "byte sequence is not representable in the platform encoding"
28 ),
29 }
30 }
31}
32
33#[derive(Copy, Clone, Debug, PartialEq, Eq)]
35#[must_use]
36pub struct Object {
37 pub data: *const c_void,
38 pub meta: usize,
39}
40
41pub struct FFIResult {
42 pub data: Object,
43 pub is_success: bool,
45}
46
47pub type RealOptObj = Option<Arc<dyn Any + Send + Sync>>;
48
49impl Object {
50 pub fn is_null(&self) -> bool {
51 self.data.is_null() && self.meta == 0
52 }
53}
54
55impl From<RealOptObj> for Object {
56 fn from(x: RealOptObj) -> Object {
57 match x {
58 Some(y) => unsafe {
59 let [data, meta] = crate::fatptr::decomp(Arc::into_raw(y));
60 Object {
61 data: data as *const c_void,
62 meta,
63 }
64 },
65 None => Object {
66 data: std::ptr::null(),
67 meta: 0,
68 },
69 }
70 }
71}
72
73impl Into<RealOptObj> for Object {
74 fn into(self) -> RealOptObj {
75 if !self.is_null() {
76 Some(unsafe { Arc::from_raw(crate::fatptr::recomp([self.data as usize, self.meta])) })
77 } else {
78 None
79 }
80 }
81}
82
83impl From<Result<Object, Object>> for FFIResult {
84 #[inline]
85 fn from(x: Result<Object, Object>) -> FFIResult {
86 let is_success = x.is_ok();
87 FFIResult {
88 data: match x {
89 Ok(y) | Err(y) => y,
90 },
91 is_success,
92 }
93 }
94}
95
96#[inline]
97pub fn wrap<T>(x: T) -> Object
98where
99 T: Send + Sync + 'static,
100{
101 Some(Arc::new(x) as Arc<dyn Any + Send + Sync + 'static>).into()
102}
103
104#[inline]
105pub fn wrapres<T, E>(x: Result<T, E>) -> FFIResult
106where
107 T: Send + Sync + 'static,
108 E: Send + Sync + 'static,
109{
110 x.map(wrap::<T>).map_err(wrap::<E>).into()
111}