|
|
|
@@ -1,21 +1,106 @@ |
|
|
|
use std::ptr; |
|
|
|
use dora_node_api::{DoraNode, Input}; |
|
|
|
use futures::{executor::block_on, Stream, StreamExt}; |
|
|
|
use std::{pin::Pin, ptr, slice}; |
|
|
|
|
|
|
|
use dora_node_api::DoraNode; |
|
|
|
use futures::executor::block_on; |
|
|
|
struct DoraContext { |
|
|
|
node: &'static DoraNode, |
|
|
|
inputs: Pin<Box<dyn futures::Stream<Item = Input>>>, |
|
|
|
} |
|
|
|
|
|
|
|
pub extern "C" fn init_dora_node_from_env() -> *mut () { |
|
|
|
let node = match block_on(DoraNode::init_from_env()) { |
|
|
|
pub extern "C" fn init_dora_context_from_env() -> *mut () { |
|
|
|
let context = match block_on(async { |
|
|
|
let node = DoraNode::init_from_env().await?; |
|
|
|
let node = Box::leak(Box::new(node)); |
|
|
|
let inputs: Pin<Box<dyn Stream<Item = Input>>> = Box::pin(node.inputs().await?); |
|
|
|
Ok(DoraContext { node, inputs }) |
|
|
|
}) { |
|
|
|
Ok(n) => n, |
|
|
|
Err(err) => { |
|
|
|
let err: eyre::Error = err; |
|
|
|
eprintln!("{err:?}"); |
|
|
|
return ptr::null_mut(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
Box::into_raw(Box::new(node)).cast() |
|
|
|
Box::into_raw(Box::new(context)).cast() |
|
|
|
} |
|
|
|
|
|
|
|
pub extern "C" fn free_dora_context(context: *mut ()) { |
|
|
|
let context: Box<DoraContext> = unsafe { Box::from_raw(context.cast()) }; |
|
|
|
// drop all fields except for `node` |
|
|
|
let DoraContext { node, .. } = *context; |
|
|
|
// convert the `'static` reference back to a Box, then drop it |
|
|
|
let _ = unsafe { Box::from_raw(node as *const DoraNode as *mut DoraNode) }; |
|
|
|
} |
|
|
|
|
|
|
|
pub extern "C" fn dora_next_input(context: *mut ()) -> *mut () { |
|
|
|
let context: &mut DoraContext = unsafe { &mut *context.cast() }; |
|
|
|
match block_on(context.inputs.next()) { |
|
|
|
Some(input) => Box::into_raw(Box::new(input)).cast(), |
|
|
|
None => ptr::null_mut(), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pub extern "C" fn read_dora_input_id( |
|
|
|
input: *const (), |
|
|
|
out_ptr: *mut *const u8, |
|
|
|
out_len: *mut usize, |
|
|
|
) { |
|
|
|
let input: &Input = unsafe { &*input.cast() }; |
|
|
|
let id = input.id.as_str().as_bytes(); |
|
|
|
let ptr = id.as_ptr(); |
|
|
|
let len = id.len(); |
|
|
|
unsafe { |
|
|
|
*out_ptr = ptr; |
|
|
|
*out_len = len; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pub extern "C" fn read_dora_input_data( |
|
|
|
input: *const (), |
|
|
|
out_ptr: *mut *const u8, |
|
|
|
out_len: *mut usize, |
|
|
|
) { |
|
|
|
let input: &Input = unsafe { &*input.cast() }; |
|
|
|
let data = input.data.as_slice(); |
|
|
|
let ptr = data.as_ptr(); |
|
|
|
let len = data.len(); |
|
|
|
unsafe { |
|
|
|
*out_ptr = ptr; |
|
|
|
*out_len = len; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pub extern "C" fn free_dora_input(input: *mut ()) { |
|
|
|
let _: Box<Input> = unsafe { Box::from_raw(input.cast()) }; |
|
|
|
} |
|
|
|
|
|
|
|
pub extern "C" fn dora_send_output( |
|
|
|
context: *mut (), |
|
|
|
id_ptr: *const u8, |
|
|
|
id_len: usize, |
|
|
|
data_ptr: *const u8, |
|
|
|
data_len: usize, |
|
|
|
) -> isize { |
|
|
|
match try_send_output(context, id_ptr, id_len, data_ptr, data_len) { |
|
|
|
Ok(()) => 0, |
|
|
|
Err(err) => { |
|
|
|
eprintln!("{err:?}"); |
|
|
|
-1 |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pub extern "C" fn free_dora_node(node: *mut ()) { |
|
|
|
let node: Box<DoraNode> = unsafe { Box::from_raw(node.cast()) }; |
|
|
|
let _ = node; |
|
|
|
fn try_send_output( |
|
|
|
context: *mut (), |
|
|
|
id_ptr: *const u8, |
|
|
|
id_len: usize, |
|
|
|
data_ptr: *const u8, |
|
|
|
data_len: usize, |
|
|
|
) -> eyre::Result<()> { |
|
|
|
let context: &mut DoraContext = unsafe { &mut *context.cast() }; |
|
|
|
let id = std::str::from_utf8(unsafe { slice::from_raw_parts(id_ptr, id_len) })?; |
|
|
|
let output_id = id.to_owned().into(); |
|
|
|
let data = unsafe { slice::from_raw_parts(data_ptr, data_len) }; |
|
|
|
block_on(context.node.send_output(&output_id, data)) |
|
|
|
} |