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 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 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 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 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}