use crate::error::{KunQuantError, Result};
use crate::executor::Executor;
use crate::ffi;
use crate::library::Module;
use std::collections::HashMap;
use std::ffi::CString;
pub struct StreamContext<'a> {
handle: ffi::KunStreamContextHandle,
num_stocks: usize,
_executor: &'a Executor,
_module: &'a Module<'a>,
buffer_handles: HashMap<String, usize>,
}
impl<'a> StreamContext<'a> {
pub fn new(executor: &'a Executor, module: &'a Module<'a>, num_stocks: usize) -> Result<Self> {
if num_stocks % 8 != 0 {
return Err(KunQuantError::InvalidStockCount { num_stocks });
}
let handle =
unsafe { ffi::kunCreateStream(executor.handle(), module.handle(), num_stocks) };
if handle.is_null() {
return Err(KunQuantError::StreamCreationFailed);
}
Ok(StreamContext {
handle,
num_stocks,
_executor: executor,
_module: module,
buffer_handles: HashMap::new(),
})
}
pub fn get_buffer_handle<N: AsRef<str>>(&mut self, name: N) -> Result<usize> {
let name_str = name.as_ref();
if let Some(&handle) = self.buffer_handles.get(name_str) {
return Ok(handle);
}
let c_name = CString::new(name_str)?;
let handle = unsafe { ffi::kunQueryBufferHandle(self.handle, c_name.as_ptr()) };
if handle == usize::MAX {
return Err(KunQuantError::BufferHandleNotFound {
name: name_str.to_string(),
});
}
self.buffer_handles.insert(name_str.to_string(), handle);
Ok(handle)
}
pub fn get_current_buffer<N: AsRef<str>>(&mut self, name: N) -> Result<&[f32]> {
let handle = self.get_buffer_handle(name)?;
let ptr = unsafe { ffi::kunStreamGetCurrentBuffer(self.handle, handle) };
if ptr.is_null() {
return Err(KunQuantError::NullPointer);
}
Ok(unsafe { std::slice::from_raw_parts(ptr, self.num_stocks) })
}
pub fn push_data<N: AsRef<str>>(&mut self, name: N, data: &[f32]) -> Result<()> {
if data.len() != self.num_stocks {
return Err(KunQuantError::BufferSizeMismatch {
name: name.as_ref().to_string(),
expected: self.num_stocks,
actual: data.len(),
});
}
let handle = self.get_buffer_handle(name)?;
unsafe {
ffi::kunStreamPushData(self.handle, handle, data.as_ptr());
}
Ok(())
}
pub fn run(&self) -> Result<()> {
if self.handle.is_null() {
return Err(KunQuantError::NullPointer);
}
unsafe {
ffi::kunStreamRun(self.handle);
}
Ok(())
}
pub fn num_stocks(&self) -> usize {
self.num_stocks
}
}
impl<'a> Drop for StreamContext<'a> {
fn drop(&mut self) {
if !self.handle.is_null() {
unsafe {
ffi::kunDestoryStream(self.handle);
}
}
}
}