mirtal-sys 0.1.0

Private native bridge for mirtal
use crate::ffi;

type CallbackResult = std::result::Result<Vec<cxx::SharedPtr<ffi::Array>>, String>;
type Callback = dyn Fn(Vec<cxx::SharedPtr<ffi::Array>>, &ffi::Stream) -> CallbackResult + Send;

pub struct GraphCallback {
    function: Box<Callback>,
}

pub fn graph_callback(
    function: impl Fn(Vec<cxx::SharedPtr<ffi::Array>>, &ffi::Stream) -> CallbackResult + Send + 'static,
) -> Box<GraphCallback> {
    Box::new(GraphCallback { function: Box::new(function) })
}

pub fn invoke_graph(
    callback: &GraphCallback,
    inputs: cxx::UniquePtr<ffi::Arrays>,
) -> std::result::Result<cxx::UniquePtr<ffi::Arrays>, String> {
    let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
        let stream = native_stream(&inputs)?;
        let values = native_arrays(&inputs)?;
        (callback.function)(values, stream)
    }));
    drop(inputs);
    let values = match result {
        Ok(values) => values?,
        Err(_) => return Err("compiled Rust graph callback panicked".into()),
    };
    let mut outputs = ffi::new_arrays();
    for value in values {
        let value = value.as_ref().ok_or_else(|| "graph returned a null array".to_owned())?;
        ffi::arrays_push(outputs.pin_mut(), value);
    }
    Ok(outputs)
}

fn native_arrays(
    arrays: &cxx::UniquePtr<ffi::Arrays>,
) -> std::result::Result<Vec<cxx::SharedPtr<ffi::Array>>, String> {
    let arrays = arrays.as_ref().ok_or_else(|| "compiled graph inputs are null".to_owned())?;
    (0..ffi::arrays_len(arrays))
        .map(|index| ffi::arrays_get(arrays, index).map_err(|error| error.to_string()))
        .collect()
}

fn native_stream(
    arrays: &cxx::UniquePtr<ffi::Arrays>,
) -> std::result::Result<&ffi::Stream, String> {
    let arrays = arrays.as_ref().ok_or_else(|| "compiled graph inputs are null".to_owned())?;
    ffi::arrays_stream(arrays).map_err(|error| error.to_string())
}