reifydb_sdk/transform/
wrapper.rs1use std::{
5 ffi::c_void,
6 panic::{AssertUnwindSafe, catch_unwind},
7 process::abort,
8};
9
10use reifydb_abi::{context::context::ContextFFI, data::column::ColumnsFFI, transform::vtable::TransformVTableFFI};
11use tracing::error;
12
13use crate::{
14 operator::change::BorrowedColumns,
15 transform::{FFITransform, context::FFITransformContext},
16};
17
18pub struct TransformWrapper<T: FFITransform> {
19 transform: T,
20}
21
22impl<T: FFITransform> TransformWrapper<T> {
23 pub fn new(transform: T) -> Self {
24 Self {
25 transform,
26 }
27 }
28
29 pub fn from_ptr(ptr: *mut c_void) -> &'static mut Self {
30 unsafe { &mut *(ptr as *mut Self) }
31 }
32}
33
34pub unsafe extern "C" fn ffi_transform<T: FFITransform>(
40 instance: *mut c_void,
41 ctx: *mut ContextFFI,
42 input: *const ColumnsFFI,
43) -> i32 {
44 let result = catch_unwind(AssertUnwindSafe(|| {
45 let wrapper = TransformWrapper::<T>::from_ptr(instance);
46
47 let borrowed_input = unsafe { BorrowedColumns::from_ffi(input) };
48 let mut tctx = FFITransformContext::new(ctx);
49
50 match wrapper.transform.transform(&mut tctx, borrowed_input) {
51 Ok(()) => 0,
52 Err(e) => {
53 error!(?e, "Transform failed");
54 -2
55 }
56 }
57 }));
58
59 let code = result.unwrap_or_else(|e| {
60 error!(?e, "Panic in ffi_transform");
61 -99
62 });
63 if code < 0 {
64 error!(code, "ffi_transform failed - aborting");
65 abort();
66 }
67 code
68}
69
70pub unsafe extern "C" fn ffi_transform_destroy<T: FFITransform>(instance: *mut c_void) {
74 if instance.is_null() {
75 return;
76 }
77
78 let result = catch_unwind(AssertUnwindSafe(|| unsafe {
79 let _wrapper = Box::from_raw(instance as *mut TransformWrapper<T>);
80 }));
81
82 if let Err(e) = result {
83 error!(?e, "Panic in ffi_transform_destroy - aborting");
84 abort();
85 }
86}
87
88pub fn create_transform_vtable<T: FFITransform>() -> TransformVTableFFI {
89 TransformVTableFFI {
90 transform: ffi_transform::<T>,
91 destroy: ffi_transform_destroy::<T>,
92 }
93}