use crate::compressor::TemporalTensorCompressor;
use crate::segment;
use crate::tier_policy::TierPolicy;
static mut STORE: Option<Vec<Option<TemporalTensorCompressor>>> = None;
fn store_init() {
unsafe {
if STORE.is_none() {
STORE = Some(Vec::new());
}
}
}
fn with_store<F, R>(f: F) -> R
where
F: FnOnce(&mut Vec<Option<TemporalTensorCompressor>>) -> R,
{
store_init();
unsafe { f(STORE.as_mut().unwrap()) }
}
fn with_compressor<F>(handle: u32, f: F)
where
F: FnOnce(&mut TemporalTensorCompressor),
{
with_store(|store| {
let idx = handle as usize;
if idx < store.len() {
if let Some(comp) = store[idx].as_mut() {
f(comp);
}
}
});
}
#[no_mangle]
pub extern "C" fn ttc_create(len: u32, now_ts: u32, out_handle: *mut u32) {
let policy = TierPolicy::default();
let comp = TemporalTensorCompressor::new(policy, len, now_ts);
with_store(|store| {
for (i, slot) in store.iter_mut().enumerate() {
if slot.is_none() {
*slot = Some(comp);
if !out_handle.is_null() {
unsafe { *out_handle = i as u32 };
}
return;
}
}
let idx = store.len();
store.push(Some(comp));
if !out_handle.is_null() {
unsafe { *out_handle = idx as u32 };
}
});
}
#[no_mangle]
pub extern "C" fn ttc_create_with_policy(
len: u32,
now_ts: u32,
hot_min_score: u32,
warm_min_score: u32,
warm_bits: u8,
drift_pct_q8: u32,
group_len: u32,
out_handle: *mut u32,
) {
let policy = TierPolicy {
hot_min_score,
warm_min_score,
warm_bits,
drift_pct_q8,
group_len,
};
let comp = TemporalTensorCompressor::new(policy, len, now_ts);
with_store(|store| {
for (i, slot) in store.iter_mut().enumerate() {
if slot.is_none() {
*slot = Some(comp);
if !out_handle.is_null() {
unsafe { *out_handle = i as u32 };
}
return;
}
}
let idx = store.len();
store.push(Some(comp));
if !out_handle.is_null() {
unsafe { *out_handle = idx as u32 };
}
});
}
#[no_mangle]
pub extern "C" fn ttc_free(handle: u32) {
with_store(|store| {
let idx = handle as usize;
if idx < store.len() {
store[idx] = None;
}
});
}
#[no_mangle]
pub extern "C" fn ttc_touch(handle: u32, now_ts: u32) {
with_compressor(handle, |comp| comp.touch(now_ts));
}
#[no_mangle]
pub extern "C" fn ttc_set_access(handle: u32, access_count: u32, last_access_ts: u32) {
with_compressor(handle, |comp| comp.set_access(access_count, last_access_ts));
}
#[no_mangle]
pub extern "C" fn ttc_push_frame(
handle: u32,
now_ts: u32,
in_ptr: *const f32,
len: u32,
out_ptr: *mut u8,
out_cap: u32,
out_written: *mut u32,
) {
if out_written.is_null() {
return;
}
unsafe { *out_written = 0 };
if in_ptr.is_null() || out_ptr.is_null() {
return;
}
let frame = unsafe { std::slice::from_raw_parts(in_ptr, len as usize) };
let mut seg = Vec::new();
with_compressor(handle, |comp| {
comp.push_frame(frame, now_ts, &mut seg);
});
if seg.is_empty() || (seg.len() as u32) > out_cap {
return;
}
unsafe {
let out = std::slice::from_raw_parts_mut(out_ptr, out_cap as usize);
out[..seg.len()].copy_from_slice(&seg);
*out_written = seg.len() as u32;
}
}
#[no_mangle]
pub extern "C" fn ttc_flush(handle: u32, out_ptr: *mut u8, out_cap: u32, out_written: *mut u32) {
if out_written.is_null() {
return;
}
unsafe { *out_written = 0 };
let mut seg = Vec::new();
with_compressor(handle, |comp| {
comp.flush(&mut seg);
});
if seg.is_empty() || out_ptr.is_null() || (seg.len() as u32) > out_cap {
return;
}
unsafe {
let out = std::slice::from_raw_parts_mut(out_ptr, out_cap as usize);
out[..seg.len()].copy_from_slice(&seg);
*out_written = seg.len() as u32;
}
}
#[no_mangle]
pub extern "C" fn ttc_decode_segment(
seg_ptr: *const u8,
seg_len: u32,
out_ptr: *mut f32,
out_cap_f32: u32,
out_written_f32: *mut u32,
) {
if out_written_f32.is_null() {
return;
}
unsafe { *out_written_f32 = 0 };
if seg_ptr.is_null() || out_ptr.is_null() {
return;
}
let seg = unsafe { std::slice::from_raw_parts(seg_ptr, seg_len as usize) };
let mut values = Vec::new();
segment::decode(seg, &mut values);
if values.is_empty() || (values.len() as u32) > out_cap_f32 {
return;
}
unsafe {
let out = std::slice::from_raw_parts_mut(out_ptr, out_cap_f32 as usize);
out[..values.len()].copy_from_slice(&values);
*out_written_f32 = values.len() as u32;
}
}
#[no_mangle]
pub extern "C" fn ttc_alloc(size: u32, out_ptr: *mut u32) {
if out_ptr.is_null() {
return;
}
let mut v: Vec<u8> = Vec::with_capacity(size as usize);
let p = v.as_mut_ptr();
std::mem::forget(v);
unsafe {
*out_ptr = p as u32;
}
}
#[no_mangle]
pub extern "C" fn ttc_dealloc(ptr: u32, cap: u32) {
if ptr == 0 || cap == 0 {
return;
}
unsafe {
let _ = Vec::<u8>::from_raw_parts(ptr as *mut u8, 0, cap as usize);
}
}