1pub mod fermented;
2
3use std::collections::{BTreeMap, HashMap};
4use std::ffi::CString;
5use std::hash::Hash;
6use std::mem;
7use std::os::raw::c_char;
8
9pub trait FFIConversionFrom<T> {
12 unsafe fn ffi_from_const(ffi: *const Self) -> T;
14 unsafe fn ffi_from(ffi: *mut Self) -> T {
16 Self::ffi_from_const(ffi.cast_const())
17 }
18 unsafe fn ffi_from_opt(ffi: *mut Self) -> Option<T> {
20 (!ffi.is_null())
21 .then(|| Self::ffi_from(ffi))
22 }
23}
24
25pub trait FFIConversionTo<T> {
26 unsafe fn ffi_to_const(obj: T) -> *const Self;
28 unsafe fn ffi_to(obj: T) -> *mut Self {
30 Self::ffi_to_const(obj)
31 .cast_mut()
32 }
33 unsafe fn ffi_to_opt(obj: Option<T>) -> *mut Self where Self: Sized {
35 if let Some(o) = obj {
36 Self::ffi_to(o)
37 } else {
38 std::ptr::null_mut()
39 }
40 }
41}
42pub fn black_hole<T>(_obj: T) {}
43pub fn bypass<T>(obj: T) -> T { obj }
44
45pub fn boxed<T>(obj: T) -> *mut T {
46 Box::into_raw(Box::new(obj))
47}
48pub fn boxed_vec<T>(vec: Vec<T>) -> *mut T {
49 let mut slice = vec.into_boxed_slice();
50 let ptr = slice.as_mut_ptr();
51 mem::forget(slice);
52 ptr
53}
54pub fn boxed_arr<const N: usize, T: Clone>(arr: [T; N]) -> *mut T {
55 boxed_vec(arr.to_vec())
56}
57pub fn boxed_slice<T: Clone>(slice: &[T]) -> *mut T {
58 boxed_vec(slice.to_vec())
59}
60
61pub unsafe fn unbox_any<T: ?Sized>(any: *mut T) {
63 if !any.is_null() {
64 let _ = Box::from_raw(any);
65 }
66}
67pub unsafe fn unbox_any_opt<T: ?Sized>(any: *mut T) {
69 if !any.is_null() {
70 let _ = Box::from_raw(any);
71 }
72}
73
74pub unsafe fn unbox_string(data: *mut c_char) {
76 if data.is_null() {
77 return;
78 }
79 let _ = CString::from_raw(data);
80}
81
82pub unsafe fn unbox_any_vec<T>(vec: Vec<*mut T>) {
84 if vec.is_empty() {
86 return;
87 }
88 for &x in vec.iter() {
89 unbox_any(x);
90 }
91}
92pub unsafe fn unbox_any_vec_composer<T, U: Fn(*mut T)>(vec: Vec<*mut T>, composer: U) {
94 if vec.is_empty() {
95 return;
96 }
97 for &x in vec.iter() {
98 composer(x);
99 }
100}
101
102pub unsafe fn unbox_any_vec_ptr<T>(ptr: *mut *mut T, count: usize) {
104 unbox_group(ptr, count, unbox_any);
105}
106
107pub unsafe fn unbox_vec_ptr<T>(ptr: *mut T, count: usize) -> Vec<T> {
109 Vec::from_raw_parts(ptr, count, count)
110}
111
112pub unsafe fn unbox_group<T>(ptr: *mut T, count: usize, item_destructor: unsafe fn(T)) {
116 if ptr.is_null() || count == 0 {
117 return;
118 }
119 let vec_of_ptr = unbox_vec_ptr(ptr, count);
121 if vec_of_ptr.is_empty() {
122 return;
123 }
124 for item in vec_of_ptr {
125 item_destructor(item);
126 }
127}
128
129
130pub unsafe fn from_opt_primitive<T: Copy>(ptr: *mut T) -> Option<T> {
132 (!ptr.is_null()).then(|| *ptr)
133}
134
135pub unsafe fn to_opt_primitive<T>(obj: Option<T>) -> *mut T {
137 obj.map_or(std::ptr::null_mut(), |o| boxed(o))
138}
139
140pub unsafe fn from_opt_opaque<T>(ptr: *mut T) -> Option<T> {
142 (!ptr.is_null()).then(|| std::ptr::read(ptr))
143}
144
145pub unsafe fn to_opt_opaque<T>(obj: Option<T>) -> *mut T {
147 obj.map_or(std::ptr::null_mut(), |o| boxed(o))
148}
149
150pub unsafe fn destroy_opt_primitive<T: Copy>(ptr: *mut T) {
152 if !ptr.is_null() {
153 unbox_any(ptr);
154 }
155}
156
157pub trait FFIMapConversion {
158 type Key;
159 type Value;
160 fn new() -> Self;
161 fn insert(&mut self, key: Self::Key, value: Self::Value);
162 fn count(&self) -> usize;
163}
164
165impl<K: Ord, V> FFIMapConversion for BTreeMap<K, V> {
166 type Key = K;
167 type Value = V;
168 fn new() -> Self { BTreeMap::new() }
169 fn insert(&mut self, key: K, value: V) { BTreeMap::insert(self, key, value); }
170
171 fn count(&self) -> usize {
172 self.len()
173 }
174}
175
176impl<K: Hash + Eq, V> FFIMapConversion for HashMap<K, V> {
177 type Key = K;
178 type Value = V;
179 fn new() -> Self { HashMap::new() }
180 fn insert(&mut self, key: K, value: V) { HashMap::insert(self, key, value); }
181
182 fn count(&self) -> usize {
183 self.len()
184 }
185}
186
187impl<K: Hash + Eq, V> FFIMapConversion for indexmap::IndexMap<K, V> {
188 type Key = K;
189 type Value = V;
190 fn new() -> Self { indexmap::IndexMap::new() }
191 fn insert(&mut self, key: K, value: V) { indexmap::IndexMap::insert(self, key, value); }
192
193 fn count(&self) -> usize {
194 self.len()
195 }
196}
197
198impl FFIMapConversion for serde_json::Map<String, serde_json::Value> {
199 type Key = String;
200 type Value = serde_json::Value;
201
202 fn new() -> Self {
203 serde_json::Map::new()
204 }
205
206 fn insert(&mut self, key: Self::Key, value: Self::Value) {
207 serde_json::Map::insert(self, key, value);
208 }
209
210 fn count(&self) -> usize {
211 self.len()
212 }
213}
214
215pub unsafe fn from_group<Iter, FFIType, TargetType>(
217 count: usize,
218 ptr: *mut FFIType,
219 mut converter: impl FnMut(*mut FFIType) -> TargetType,
220) -> Iter
221where Iter: FromIterator<TargetType> {
222 (0..count)
223 .map(|i| converter(ptr.add(i)))
224 .collect()
225}
226
227pub unsafe fn from_primitive_group<Iter, T: Copy>(ptr: *mut T, count: usize) -> Iter
229where Iter: FromIterator<T> {
230 from_group(count, ptr, |p| *p)
231}
232pub unsafe fn from_opt_primitive_group<Iter, T: Copy>(ptr: *mut *mut T, count: usize) -> Iter
234where Iter: FromIterator<Option<T>> {
235 from_group(count, ptr, |p| {
236 let inner = *p;
237 (!inner.is_null()).then(|| *inner)
238 })
239}
240
241pub unsafe fn from_opt_opaque_group<Iter, T>(ptr: *mut *mut T, count: usize) -> Iter
243where Iter: FromIterator<Option<T>> {
244 from_group(count, ptr, |p| {
245 let inner = *p;
246 (!inner.is_null()).then(|| std::ptr::read(inner))
247 })
248}
249pub unsafe fn from_opaque_group<Iter, T>(ptr: *mut *mut T, count: usize) -> Iter
251where Iter: FromIterator<T> {
252 from_group(count, ptr, |p| std::ptr::read(*p))
253}
254
255pub unsafe fn from_complex_group<Iter, T, FFI>(ptr: *mut *mut FFI, count: usize) -> Iter
257where Iter: FromIterator<T>,
258 FFI: FFIConversionFrom<T> {
259 from_group(count, ptr, |p| FFIConversionFrom::ffi_from(*p))
260}
261
262pub unsafe fn from_opt_complex_group<Iter, T, FFI>(ptr: *mut *mut FFI, count: usize) -> Iter
264where
265 Iter: FromIterator<Option<T>>,
266 FFI: FFIConversionFrom<T>,
267{
268 from_group(count, ptr, |p| FFIConversionFrom::ffi_from_opt(*p))
269}
270
271pub unsafe fn to_group<Iter, TargetType, FFIType>(iter: Iter, converter: fn(TargetType) -> FFIType) -> *mut FFIType
273 where Iter: Iterator<Item=TargetType> {
274 boxed_vec(iter.map(converter).collect())
275}
276
277pub unsafe fn to_complex_group<Iter, TargetType, FFIType>(iter: Iter) -> *mut *mut FFIType
279 where Iter: Iterator<Item=TargetType>,
280 FFIType: FFIConversionTo<TargetType> {
281 to_group(iter, |o| <FFIType as FFIConversionTo<TargetType>>::ffi_to(o))
282}
283pub unsafe fn to_opt_complex_group<Iter, TargetType, FFIType>(iter: Iter) -> *mut *mut FFIType
285 where Iter: Iterator<Item=Option<TargetType>>,
286 FFIType: FFIConversionTo<TargetType> {
287 to_group(iter, |o| <FFIType as FFIConversionTo<TargetType>>::ffi_to_opt(o))
288}
289
290pub unsafe fn to_primitive_group<Iter, TargetType>(iter: Iter) -> *mut TargetType
292 where Iter: Iterator<Item=TargetType>,
293 TargetType: Copy {
294 to_group(iter, |o| o)
295}
296pub unsafe fn to_opt_primitive_group<Iter, TargetType>(iter: Iter) -> *mut *mut TargetType
298 where Iter: Iterator<Item=Option<TargetType>>,
299 Vec<*mut TargetType>: FromIterator<*mut TargetType> {
300 to_group(iter, |o| o.map_or(std::ptr::null_mut(), |o| boxed(o)))
301}
302pub unsafe fn to_opt_opaque_group<Iter, TargetType>(iter: Iter) -> *mut *mut TargetType
304 where Iter: Iterator<Item=Option<TargetType>>,
305 Vec<*mut TargetType>: FromIterator<*mut TargetType> {
306 to_group(iter, |o| o.map_or(std::ptr::null_mut(), |o| boxed(o)))
307}
308pub unsafe fn to_opaque_group<Iter, TargetType>(iter: Iter) -> *mut *mut TargetType
310 where Iter: Iterator<Item=TargetType>,
311 Vec<*mut TargetType>: FromIterator<*mut TargetType> {
312 to_group(iter, |o| boxed(o))
313}
314
315
316pub fn to_map<TargetKey, TargetValue, FFIKey, FFIValue, Map, ToKey, ToValue>(obj: Map, key_converter: ToKey, value_converter: ToValue) -> (usize, *mut FFIKey, *mut FFIValue)
317where Map: FFIMapConversion<Key=TargetKey, Value=TargetValue> + IntoIterator<Item= (TargetKey, TargetValue)>,
318 ToKey: Fn(TargetKey) -> FFIKey,
319 ToValue: Fn(TargetValue) -> FFIValue {
320 let count = obj.count();
321 let (keys, values) = obj.into_iter().map(|(key, value)| (key_converter(key), value_converter(value))).unzip();
322 (count, boxed_vec(keys), boxed_vec(values))
323}
324
325pub unsafe fn fold_to_map<M, K, V, K2, V2>(
327 count: usize,
328 keys: *mut K,
329 values: *mut V,
330 key_converter: impl Fn(K) -> K2,
331 value_converter: impl Fn(V) -> V2) -> M
332 where
333 M: FFIMapConversion<Key=K2, Value=V2>,
334 K: Copy,
335 V: Copy {
336 (0..count).fold(M::new(), |mut acc, i| {
337 let key = key_converter(*keys.add(i));
338 let value = value_converter(*values.add(i));
339 acc.insert(key, value);
340 acc
341 })
342}
343
344pub unsafe fn fold_to_vec<M, V: Copy, V2>(count: usize, values: *mut V, value_converter: impl Fn(V) -> V2) -> Vec<V2> {
346 (0..count)
347 .map(|i| value_converter(*values.add(i)))
348 .collect()
349}
350
351pub unsafe fn fold_to_result<T, E, T2, E2>(
360 ok: *mut T,
361 ok_converter: impl Fn(*mut T) -> T2,
362 error: *mut E,
363 error_converter: impl Fn(*mut E) -> E2,
364) -> Result<T2, E2> {
365 if !error.is_null() {
366 Err(error_converter(error))
367 } else if !ok.is_null() {
368 Ok(ok_converter(ok))
369 } else {
370 Err(error_converter(error))
371 }
372}
373
374pub unsafe fn fold_to_result_prefer_ok<T, E, T2, E2>(
378 ok: *mut T,
379 ok_converter: impl Fn(*mut T) -> T2,
380 error: *mut E,
381 error_converter: impl Fn(*mut E) -> E2,
382) -> Result<T2, E2> {
383 if error.is_null() {
384 Ok(ok_converter(ok))
385 } else {
386 Err(error_converter(error))
387 }
388}
389pub unsafe fn to_result<T, E, T2, E2>(
391 result: Result<T2, E2>,
392 ok_converter: impl Fn(T2) -> *mut T,
393 error_converter: impl Fn(E2) -> *mut E,
394) -> (*mut T, *mut E) {
395 match result {
396 Ok(o) => (ok_converter(o), std::ptr::null_mut()),
397 Err(o) => (std::ptr::null_mut(), error_converter(o))
398 }
399}
400
401#[macro_export]
424macro_rules! impl_custom_conversion {
425 ($RustType:ty, $FFIType:ty, $from:expr, $to:expr) => {
426 impl From<&$FFIType> for $RustType {
427 fn from(value: &$FFIType) -> Self {
428 $from(value)
429 }
430 }
431 impl From<&$RustType> for $FFIType {
432 fn from(value: &$RustType) -> Self {
433 $to(value)
434 }
435 }
436
437 impl ferment::FFIConversionFrom<$RustType> for $FFIType {
438 unsafe fn ffi_from_const(ffi: *const Self) -> $RustType {
439 <$RustType>::from(&*ffi)
440 }
441 }
442 impl ferment::FFIConversionTo<$RustType> for $FFIType {
443 unsafe fn ffi_to_const(obj: $RustType) -> *const Self {
444 ferment::boxed(<$FFIType>::from(&obj))
445 }
446 }
447 };
448}
449
450#[macro_export]
451macro_rules! impl_custom_conversion2 {
452 ($RustType:ty, $FFIType:ident { $($field_name:ident: $field_type:ty),* $(,)? }, $from:expr, $to:expr) => {
453 #[allow(non_camel_case_types)]
454 #[ferment_macro::register($RustType)]
455 pub struct $FFIType {
456 $(pub $field_name: $field_type),*
457 }
458 impl From<&$FFIType> for $RustType {
459 fn from(value: &$FFIType) -> Self {
460 $from(value)
461 }
462 }
463 impl From<&$RustType> for $FFIType {
464 fn from(value: &$RustType) -> Self {
465 $to(value)
466 }
467 }
468 impl ferment::FFIConversionFrom<$RustType> for $FFIType {
469 unsafe fn ffi_from_const(ffi: *const Self) -> $RustType {
470 <$RustType>::from(&*ffi)
471 }
472 }
473 impl ferment::FFIConversionTo<$RustType> for $FFIType {
474 unsafe fn ffi_to_const(obj: $RustType) -> *const Self {
475 ferment::boxed(<$FFIType>::from(&obj))
476 }
477 }
478 };
479}
480#[macro_export]
481macro_rules! impl_cloneable_ferment {
482 ($ty:path, $ffitype:ident) => {
483 impl ferment::FFIConversionFrom<$ty> for $ffitype {
484 unsafe fn ffi_from_const(ffi: *const Self) -> $ty {
485 let ffi = &*ffi;
486 let raw = &*ffi.0;
487 raw.clone()
488 }
489 }
490 impl ferment::FFIConversionTo<$ty> for $ffitype {
491 unsafe fn ffi_to_const(obj: $ty) -> *const Self {
492 ferment::boxed(Self(ferment::boxed(obj)))
493 }
494 }
495 impl Drop for $ffitype {
496 fn drop(&mut self) {
497 unsafe {
498 ferment::unbox_any(self.0);
499 }
500 }
501 }
502 };
503}
504
505pub unsafe fn to_arc<T: ?Sized>(obj: std::sync::Arc<T>) -> *mut T {
507 std::sync::Arc::into_raw(obj).cast_mut()
508}
509pub unsafe fn from_arc<T: ?Sized>(obj: *const T) -> std::sync::Arc<T> {
511 std::sync::Arc::from_raw(obj)
512}