use openvino_genai_sys::{ov_genai_streaming_status_e, streamer_callback};
use std::ffi::CStr;
use std::os::raw::{c_char, c_void};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StreamingStatus {
Running,
Stop,
Cancel,
}
impl From<StreamingStatus> for ov_genai_streaming_status_e {
fn from(status: StreamingStatus) -> Self {
match status {
StreamingStatus::Running => {
ov_genai_streaming_status_e::OV_GENAI_STREAMING_STATUS_RUNNING
}
StreamingStatus::Stop => ov_genai_streaming_status_e::OV_GENAI_STREAMING_STATUS_STOP,
StreamingStatus::Cancel => {
ov_genai_streaming_status_e::OV_GENAI_STREAMING_STATUS_CANCEL
}
}
}
}
pub struct Streamer {
callback_ptr: *mut Box<dyn FnMut(&str) -> StreamingStatus>,
}
unsafe extern "C" fn trampoline(
str_: *const c_char,
args: *mut c_void,
) -> ov_genai_streaming_status_e {
let callback = &mut *(args.cast::<Box<dyn FnMut(&str) -> StreamingStatus>>());
let c_str = CStr::from_ptr(str_);
let s = c_str.to_string_lossy();
callback(&s).into()
}
impl Drop for Streamer {
fn drop(&mut self) {
unsafe {
drop(Box::from_raw(self.callback_ptr));
}
}
}
impl Streamer {
pub fn new<F>(callback: F) -> Self
where
F: FnMut(&str) -> StreamingStatus + 'static,
{
let boxed: Box<dyn FnMut(&str) -> StreamingStatus> = Box::new(callback);
let callback_ptr = Box::into_raw(Box::new(boxed));
Self { callback_ptr }
}
pub(crate) fn as_raw(&self) -> streamer_callback {
streamer_callback {
callback_func: Some(trampoline),
args: self.callback_ptr.cast::<c_void>(),
}
}
}