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) };
49 let mut tctx = FFITransformContext::new(ctx);
50
51 match wrapper.transform.transform(&mut tctx, borrowed_input) {
52 Ok(()) => 0,
53 Err(e) => {
54 error!(?e, "Transform failed");
55 -2
56 }
57 }
58 }));
59
60 let code = result.unwrap_or_else(|e| {
61 error!(?e, "Panic in ffi_transform");
62 -99
63 });
64 if code < 0 {
65 error!(code, "ffi_transform failed - aborting");
66 abort();
67 }
68 code
69}
70
71pub unsafe extern "C" fn ffi_transform_destroy<T: FFITransform>(instance: *mut c_void) {
75 if instance.is_null() {
76 return;
77 }
78
79 let result = catch_unwind(AssertUnwindSafe(|| unsafe {
80 let _wrapper = Box::from_raw(instance as *mut TransformWrapper<T>);
81 }));
82
83 if let Err(e) = result {
84 error!(?e, "Panic in ffi_transform_destroy - aborting");
85 abort();
86 }
87}
88
89pub fn create_transform_vtable<T: FFITransform>() -> TransformVTableFFI {
90 TransformVTableFFI {
91 transform: ffi_transform::<T>,
92 destroy: ffi_transform_destroy::<T>,
93 }
94}