fcplug_rclib/
abi.rs

1use std::convert::Infallible;
2use std::fmt::{Debug, Display, Formatter};
3use std::ops::FromResidual;
4
5use flatbuffers::FlatBufferBuilder;
6#[cfg(debug_assertions)]
7use tracing::error;
8
9#[no_mangle]
10pub extern "C" fn no_mangle_types(_: Buffer, _: FFIResult) {
11    unimplemented!()
12}
13
14#[no_mangle]
15pub extern "C" fn free_buffer(free_type: OriginType, free_ptr: usize) {
16    unsafe {
17        match free_type {
18            OriginType::Vec => {
19                #[cfg(debug_assertions)]   println!("OriginType::Vec, free_ptr={}", free_ptr);
20                let ptr = free_ptr as *mut Vec<u8>;
21                if ptr.is_null() {
22                    return;
23                }
24                let _ = Box::from_raw(ptr);
25            }
26            OriginType::FlatBuffer => {
27                #[cfg(debug_assertions)] println!("OriginType::FlatBuffer, free_ptr={}", free_ptr);
28                let ptr = free_ptr as *mut FlatBufferBuilder;
29                if ptr.is_null() {
30                    return;
31                }
32                let _ = Box::from_raw(ptr);
33            }
34        };
35    }
36}
37
38pub fn callback<'a, Request, Response, F>(_ffi_method_name: &'static str, method_fn: F, args: &'a Buffer) -> FFIResult
39    where Request: ABIRequest<'a>,
40          Response: ABIResponse,
41          F: Fn(Request) -> ABIResult<Response> {
42    let args_obj = match Request::try_from_bytes(args.read().unwrap_or_default()) {
43        Ok(args_obj) => args_obj,
44        Err(err) => return FFIResult::err(ResultCode::Decode, Some(err)),
45    };
46
47    #[cfg(debug_assertions)]
48        let txt = format!("invoking method={}, args_bytes={:?}, args_obj={:?}", _ffi_method_name, args.read(), args_obj);
49
50    let res_obj: ABIResult<Response> = method_fn(args_obj);
51
52    #[cfg(debug_assertions)]
53        let txt = format!("{}, abi_result={:?}", txt, res_obj);
54
55    let res = FFIResult::from(res_obj);
56
57    #[cfg(debug_assertions)]
58    println!("{}, ffi_result={:?}", txt, res);
59
60    res
61}
62
63#[derive(Copy, Clone, Debug)]
64#[repr(C)]
65pub struct Buffer {
66    pub ptr: *mut u8,
67    pub len: usize,
68    pub cap: usize,
69}
70
71impl Display for Buffer {
72    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
73        write!(f, "{:?}", self.read())
74    }
75}
76
77impl Buffer {
78    pub const fn null() -> Self {
79        Self {
80            ptr: std::ptr::null_mut(),
81            len: 0,
82            cap: 0,
83        }
84    }
85
86    /// read provides a reference to the included data to be parsed or copied elsewhere
87    /// data is only guaranteed to live as long as the Buffer
88    /// (or the scope of the extern "C" call it came from)
89    pub fn read(&self) -> Option<&[u8]> {
90        if self.is_empty() {
91            None
92        } else {
93            unsafe { Some(std::slice::from_raw_parts(self.ptr, self.len)) }
94        }
95    }
96
97
98    pub(crate) fn is_empty(&self) -> bool {
99        self.ptr.is_null() || self.len == 0 || self.cap == 0
100    }
101}
102
103#[derive(Copy, Clone, Debug)]
104#[repr(C)]
105pub struct LeakBuffer {
106    pub(crate) free_type: OriginType,
107    pub(crate) free_ptr: usize,
108    pub(crate) buffer: Buffer,
109}
110
111
112impl LeakBuffer {
113    pub unsafe fn mem_free(self) {
114        free_buffer(self.free_type, self.free_ptr)
115    }
116
117    pub const fn null() -> Self {
118        Self {
119            free_type: OriginType::Vec,
120            free_ptr: 0,
121            buffer: Buffer::null(),
122        }
123    }
124
125    /// this releases our memory to the caller
126    pub(crate) fn from_vec(mut v: Vec<u8>) -> Self {
127        let mut buf = Self {
128            free_type: OriginType::Vec,
129            free_ptr: 0,
130            buffer: Buffer {
131                ptr: v.as_mut_ptr(),
132                len: v.len(),
133                cap: v.capacity(),
134            },
135        };
136        buf.free_ptr = Box::into_raw(Box::new(v)) as usize;
137        // mem::forget(v);
138        buf
139    }
140    pub(crate) fn is_empty(&self) -> bool {
141        self.free_ptr == 0 || self.buffer.is_empty()
142    }
143    pub fn read(&self) -> Option<&[u8]> {
144        if self.is_empty() {
145            None
146        } else {
147            unsafe { Some(std::slice::from_raw_parts(self.buffer.ptr, self.buffer.len)) }
148        }
149    }
150    // pub(crate) fn consume_vec(self) -> Vec<u8> {
151    //     match self.free_type {
152    //         OriginType::Vec => {
153    //             unsafe { *Box::from_raw(self.free_ptr as *mut Vec<u8>) }
154    //         }
155    //         OriginType::FlatBuffer => {
156    //             let v = self.read().map_or_else(Vec::new, |v| v.to_owned());
157    //             unsafe { self.mem_free(); }
158    //             v
159    //         }
160    //     }
161    // }
162    pub fn buffer(&self) -> Buffer {
163        self.buffer
164    }
165}
166
167
168#[derive(Debug, Clone, Copy)]
169#[repr(C)]
170pub enum ResultCode {
171    NoError = 0,
172    Decode = 1,
173    Encode = 2,
174}
175
176#[allow(dead_code)]
177#[derive(Debug, Clone, Copy)]
178#[repr(C)]
179pub enum OriginType {
180    Vec = 0,
181    FlatBuffer = 1,
182}
183
184#[derive(Debug)]
185#[repr(C)]
186pub struct FFIResult {
187    pub code: ResultCode,
188    pub data: LeakBuffer,
189}
190
191impl FFIResult {
192    pub fn ok(data: LeakBuffer) -> Self {
193        Self { code: ResultCode::NoError, data }
194    }
195    pub(crate) fn err<E: Debug>(code: ResultCode, _err: Option<E>) -> Self {
196        #[cfg(debug_assertions)]{
197            if let Some(err) = _err {
198                error!("{:?}", err);
199            }
200        }
201        Self { code, data: LeakBuffer::null() }
202    }
203}
204
205pub type ABIResult<T> = Result<T, ResultCode>;
206
207impl<T: ABIResponse> From<ABIResult<T>> for FFIResult {
208    fn from(value: ABIResult<T>) -> Self {
209        match value {
210            Ok(v) => match v.try_into_buffer() {
211                Ok(v) => Self::ok(v),
212                Err(e) => Self::err(ResultCode::Encode, Some(e)),
213            },
214            Err(e) => Self::err(ResultCode::Encode, Some(e))
215        }
216    }
217}
218
219impl<'a, T: ABIRequest<'a>> From<&'a FFIResult> for ABIResult<T> {
220    fn from(value: &'a FFIResult) -> Self {
221        match value.code {
222            ResultCode::NoError => {
223                ABIRequest::try_from_bytes(value.data.read().unwrap_or_default())
224                    .map_err(|_err| {
225                        #[cfg(debug_assertions)]{
226                            error!("{:?}", _err);
227                        }
228                        ResultCode::Decode
229                    })
230            }
231            code => Err(code)
232        }
233    }
234}
235
236pub trait ABIMessage<'a>: ABIRequest<'a> + ABIResponse {}
237
238pub trait ABIRequest<'a>: Debug {
239    type DecodeError: Debug;
240    fn try_from_bytes(buf: &'a [u8]) -> Result<Self, Self::DecodeError> where Self: Sized;
241}
242
243pub trait ABIResponse: Debug {
244    type EncodeError: Debug;
245    const ORIGIN_TYPE_FOR_FREE: OriginType;
246    fn try_into_buffer(self) -> Result<LeakBuffer, Self::EncodeError>;
247}
248
249impl FromResidual<Result<Infallible, ResultCode>> for FFIResult {
250    fn from_residual(residual: Result<Infallible, ResultCode>) -> Self {
251        Self { code: residual.unwrap_err(), data: LeakBuffer::null() }
252    }
253}
254
255#[test]
256fn test_free() {
257    let buf = LeakBuffer::from_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8]);
258    println!("{:?}", buf.read());
259    {
260        println!("{:?}", unsafe { Vec::from_raw_parts(buf.buffer.ptr, buf.buffer.len, buf.buffer.cap) });
261    }
262    println!("{:?}", buf.read());
263}