fcplug_callee/
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 mut 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_mut().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_obj={:?}", _ffi_method_name, 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    /// read_mut provides a reference to the included data to be parsed or copied elsewhere
98    /// data is only guaranteed to live as long as the Buffer
99    /// (or the scope of the extern "C" call it came from)
100    pub fn read_mut(&mut self) -> Option<&mut [u8]> {
101        if self.is_empty() {
102            None
103        } else {
104            unsafe { Some(std::slice::from_raw_parts_mut(self.ptr, self.len)) }
105        }
106    }
107
108
109    pub(crate) fn is_empty(&self) -> bool {
110        self.ptr.is_null() || self.len == 0 || self.cap == 0
111    }
112}
113
114#[derive(Copy, Clone, Debug)]
115#[repr(C)]
116pub struct LeakBuffer {
117    pub(crate) free_type: OriginType,
118    pub(crate) free_ptr: usize,
119    pub(crate) buffer: Buffer,
120}
121
122
123impl LeakBuffer {
124    pub unsafe fn mem_free(self) {
125        free_buffer(self.free_type, self.free_ptr)
126    }
127
128    pub const fn null() -> Self {
129        Self {
130            free_type: OriginType::Vec,
131            free_ptr: 0,
132            buffer: Buffer::null(),
133        }
134    }
135
136    /// this releases our memory to the caller
137    pub(crate) fn from_vec(mut v: Vec<u8>) -> Self {
138        let mut buf = Self {
139            free_type: OriginType::Vec,
140            free_ptr: 0,
141            buffer: Buffer {
142                ptr: v.as_mut_ptr(),
143                len: v.len(),
144                cap: v.capacity(),
145            },
146        };
147        buf.free_ptr = Box::into_raw(Box::new(v)) as usize;
148        // mem::forget(v);
149        buf
150    }
151    pub(crate) fn is_empty(&self) -> bool {
152        self.free_ptr == 0 || self.buffer.is_empty()
153    }
154    pub fn read(&self) -> Option<&[u8]> {
155        if self.is_empty() {
156            None
157        } else {
158            unsafe { Some(std::slice::from_raw_parts(self.buffer.ptr, self.buffer.len)) }
159        }
160    }
161    pub fn read_mut(&mut self) -> Option<&mut [u8]> {
162        if self.is_empty() {
163            None
164        } else {
165            unsafe { Some(std::slice::from_raw_parts_mut(self.buffer.ptr, self.buffer.len)) }
166        }
167    }
168    // pub(crate) fn consume_vec(self) -> Vec<u8> {
169    //     match self.free_type {
170    //         OriginType::Vec => {
171    //             unsafe { *Box::from_raw(self.free_ptr as *mut Vec<u8>) }
172    //         }
173    //         OriginType::FlatBuffer => {
174    //             let v = self.read().map_or_else(Vec::new, |v| v.to_owned());
175    //             unsafe { self.mem_free(); }
176    //             v
177    //         }
178    //     }
179    // }
180    pub fn buffer(&self) -> Buffer {
181        self.buffer
182    }
183}
184
185
186#[derive(Debug, Clone, Copy)]
187#[repr(C)]
188pub enum ResultCode {
189    NoError = 0,
190    Decode = 1,
191    Encode = 2,
192}
193
194#[allow(dead_code)]
195#[derive(Debug, Clone, Copy)]
196#[repr(C)]
197pub enum OriginType {
198    Vec = 0,
199    FlatBuffer = 1,
200}
201
202#[derive(Debug)]
203#[repr(C)]
204pub struct FFIResult {
205    pub code: ResultCode,
206    pub data: LeakBuffer,
207}
208
209impl FFIResult {
210    pub fn ok(data: LeakBuffer) -> Self {
211        Self { code: ResultCode::NoError, data }
212    }
213    pub(crate) fn err<E: Debug>(code: ResultCode, _err: Option<E>) -> Self {
214        #[cfg(debug_assertions)]{
215            if let Some(err) = _err {
216                error!("{:?}", err);
217            }
218        }
219        Self { code, data: LeakBuffer::null() }
220    }
221}
222
223pub type ABIResult<T> = Result<T, ResultCode>;
224
225impl<T: ABIResponse> From<ABIResult<T>> for FFIResult {
226    fn from(value: ABIResult<T>) -> Self {
227        match value {
228            Ok(v) => match v.try_into_buffer() {
229                Ok(v) => Self::ok(v),
230                Err(e) => Self::err(ResultCode::Encode, Some(e)),
231            },
232            Err(e) => Self::err(ResultCode::Encode, Some(e))
233        }
234    }
235}
236
237impl<'a, T: ABIRequest<'a>> From<&'a mut FFIResult> for ABIResult<T> {
238    fn from(value: &'a mut FFIResult) -> Self {
239        match value.code {
240            ResultCode::NoError => {
241                ABIRequest::try_from_bytes(value.data.read_mut().unwrap_or_default())
242                    .map_err(|_err| {
243                        #[cfg(debug_assertions)]{
244                            error!("{:?}", _err);
245                        }
246                        ResultCode::Decode
247                    })
248            }
249            code => Err(code)
250        }
251    }
252}
253
254pub trait ABIMessage<'a>: ABIRequest<'a> + ABIResponse {}
255
256pub trait ABIRequest<'a>: Debug {
257    type DecodeError: Debug;
258    fn try_from_bytes(buf: &'a mut [u8]) -> Result<Self, Self::DecodeError> where Self: Sized;
259}
260
261pub trait ABIResponse: Debug {
262    type EncodeError: Debug;
263    const ORIGIN_TYPE_FOR_FREE: OriginType;
264    fn try_into_buffer(self) -> Result<LeakBuffer, Self::EncodeError>;
265}
266
267impl FromResidual<Result<Infallible, ResultCode>> for FFIResult {
268    fn from_residual(residual: Result<Infallible, ResultCode>) -> Self {
269        Self { code: residual.unwrap_err(), data: LeakBuffer::null() }
270    }
271}
272
273#[test]
274fn test_free() {
275    let buf = LeakBuffer::from_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8]);
276    println!("{:?}", buf.read());
277    {
278        println!("{:?}", unsafe { Vec::from_raw_parts(buf.buffer.ptr, buf.buffer.len, buf.buffer.cap) });
279    }
280    println!("{:?}", buf.read());
281}