use crate::context::{CURRENT_UNARY_RESULT, HostContext};
use crate::types::{StreamFrame, UnaryResultSlot};
use nylon_ring::{NrBytes, NrStatus, NrStr, NrVec};
use std::ffi::c_void;
pub(crate) unsafe extern "C" fn send_result_vec_callback(
host_ctx: *mut c_void,
sid: u64,
status: NrStatus,
payload: nylon_ring::NrVec<u8>,
) -> NrStatus {
if host_ctx.is_null() {
return NrStatus::Invalid;
}
let ctx = unsafe { &*host_ctx.cast::<HostContext>() };
let mut data_vec = Some(payload.into_vec());
let mut handled_fast = false;
CURRENT_UNARY_RESULT.with(|cell| {
let ptr = cell.get();
if !ptr.is_null() {
let slot: &mut UnaryResultSlot = unsafe { &mut *ptr };
if slot.sid == sid
&& let Some(data) = data_vec.take()
{
slot.result = Some((status, data));
handled_fast = true;
}
}
});
if handled_fast {
ctx.state_per_sid.remove(&sid);
return NrStatus::Ok;
}
let data = data_vec.take().expect("fast path did not consume payload");
crate::context::dispatch_pending(ctx, sid, StreamFrame { status, data })
}
pub(crate) unsafe extern "C" fn set_state_callback(
host_ctx: *mut c_void,
sid: u64,
key: NrStr,
value: NrBytes,
) -> NrStatus {
if host_ctx.is_null() {
return NrStatus::Invalid;
}
let ctx = unsafe { &*host_ctx.cast::<HostContext>() };
let key_str = match unsafe { key.as_str() } {
Ok(key) => key.to_owned(),
Err(_) => return NrStatus::Invalid,
};
let value_vec = match unsafe { value.as_slice() } {
Ok(value) => value.to_vec(),
Err(_) => return NrStatus::Invalid,
};
ctx.state_per_sid
.entry(sid)
.or_default()
.insert(key_str, value_vec);
NrStatus::Ok
}
pub(crate) unsafe extern "C" fn get_state_callback(
host_ctx: *mut c_void,
sid: u64,
key: NrStr,
) -> NrVec<u8> {
if host_ctx.is_null() {
return NrVec::default();
}
let ctx = unsafe { &*host_ctx.cast::<HostContext>() };
let key_str = match unsafe { key.as_str() } {
Ok(key) => key,
Err(_) => return NrVec::default(),
};
if let Some(sid_state) = ctx.state_per_sid.get(&sid)
&& let Some(value) = sid_state.get(key_str)
{
return NrVec::from_vec(value.clone());
}
NrVec::default()
}