use crate::context::{CURRENT_UNARY_RESULT, HostContext};
use crate::types::{ForeignBytes, ResponsePayload, UnaryResultSlot};
use nylon_ring::{NrBufferLease, NrBytes, NrOwnedBytes, 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.remove_state(sid);
return NrStatus::Ok;
}
let mut stream_status = None;
crate::context::CURRENT_STREAM_FRAME.with(|cell| {
let ptr = cell.get();
if !ptr.is_null() {
let slot: &mut crate::context::StreamFrameSlot = unsafe { &mut *ptr };
if slot.sid == sid
&& let Some(data) = data_vec.take()
{
let terminal = status.is_terminal();
match slot
.chan
.try_send(crate::types::StreamFrame { status, data })
{
Ok(()) => {
if terminal {
slot.terminal_seen = true;
}
stream_status = Some(NrStatus::Ok);
}
Err(_rejected_frame) => stream_status = Some(NrStatus::Backpressure),
}
}
}
});
if let Some(status) = stream_status {
return status;
}
let data = data_vec.take().expect("fast path did not consume payload");
crate::context::dispatch_pending(ctx, sid, status, ResponsePayload::Owned(data))
}
pub(crate) unsafe extern "C" fn send_result_owned_callback(
host_ctx: *mut c_void,
sid: u64,
status: NrStatus,
payload: NrOwnedBytes,
) -> NrStatus {
let foreign = ForeignBytes::from_abi(payload);
if host_ctx.is_null() {
return NrStatus::Invalid;
}
let ctx = unsafe { &*host_ctx.cast::<HostContext>() };
let mut payload = Some(ResponsePayload::Foreign(foreign));
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(payload) = payload.take()
{
slot.result = Some((status, payload.into_vec()));
handled_fast = true;
}
}
});
if handled_fast {
ctx.remove_state(sid);
return NrStatus::Ok;
}
let payload = payload.take().expect("fast path did not consume payload");
crate::context::dispatch_pending(ctx, sid, status, payload)
}
pub(crate) unsafe extern "C" fn acquire_result_buffer_callback(
host_ctx: *mut c_void,
sid: u64,
capacity: u64,
) -> NrBufferLease {
if host_ctx.is_null() {
return NrBufferLease::failed();
}
let ctx = unsafe { &*host_ctx.cast::<HostContext>() };
let mut fast_lease = None;
CURRENT_UNARY_RESULT.with(|cell| {
let ptr = cell.get();
if !ptr.is_null() {
let slot: &mut UnaryResultSlot = unsafe { &mut *ptr };
if slot.sid == sid {
if slot.lease.is_none() && slot.result.is_none() {
let Ok(capacity) = usize::try_from(capacity) else {
fast_lease = Some(NrBufferLease::failed());
return;
};
let mut buffer: Vec<u8> = Vec::with_capacity(capacity);
fast_lease = Some(NrBufferLease {
ptr: buffer.as_mut_ptr(),
cap: buffer.capacity() as u64,
token: buffer.as_ptr() as u64,
});
slot.lease = Some(buffer);
} else {
fast_lease = Some(NrBufferLease::failed());
}
}
}
});
if let Some(lease) = fast_lease {
return lease;
}
crate::context::acquire_pending_lease(ctx, sid, capacity)
}
pub(crate) unsafe extern "C" fn commit_result_buffer_callback(
host_ctx: *mut c_void,
sid: u64,
status: NrStatus,
token: u64,
initialized_len: u64,
) -> NrStatus {
if host_ctx.is_null() {
return NrStatus::Invalid;
}
let ctx = unsafe { &*host_ctx.cast::<HostContext>() };
let mut fast_status = None;
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(mut buffer) = slot.lease.take() else {
fast_status = Some(NrStatus::Invalid);
return;
};
if buffer.as_ptr() as u64 != token || initialized_len > buffer.capacity() as u64 {
slot.lease = Some(buffer);
fast_status = Some(NrStatus::Invalid);
return;
}
if slot.result.is_some() {
fast_status = Some(NrStatus::Invalid);
return;
}
unsafe { buffer.set_len(initialized_len as usize) };
slot.result = Some((status, buffer));
fast_status = Some(NrStatus::Ok);
}
}
});
if let Some(status) = fast_status {
if status == NrStatus::Ok {
ctx.remove_state(sid);
}
return status;
}
crate::context::commit_pending_lease(ctx, sid, status, token, initialized_len)
}
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.set_state(sid, 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()
}