use crate::error::NylonRingHostError;
use crate::stream_channel::{StreamChannelReceiver, StreamSender};
use crate::{PluginCallGuard, context, context::HostContext};
use dashmap::DashMap;
use nylon_ring::NrStatus;
use rustc_hash::FxBuildHasher;
use std::collections::HashMap;
use std::sync::Arc;
use std::task::Waker;
pub type Result<T> = std::result::Result<T, NylonRingHostError>;
#[derive(Debug)]
pub(crate) enum Pending {
Unary(UnaryPending),
Stream(StreamSender),
}
#[derive(Debug)]
pub(crate) enum UnaryPending {
Waiting(Option<Waker>),
Ready(NrStatus, Vec<u8>),
}
impl UnaryPending {
pub(crate) const fn waiting() -> Self {
Self::Waiting(None)
}
}
#[derive(Debug)]
pub struct StreamFrame {
pub status: NrStatus,
pub data: Vec<u8>,
}
pub struct StreamReceiver {
inner: StreamChannelReceiver,
host_ctx: Option<Arc<HostContext>>,
sid: u64,
call_guard: Option<PluginCallGuard>,
}
impl StreamReceiver {
pub(crate) fn new(
inner: StreamChannelReceiver,
host_ctx: Option<Arc<HostContext>>,
sid: u64,
call_guard: Option<PluginCallGuard>,
) -> Self {
debug_assert!(
host_ctx.is_some() || call_guard.is_some(),
"stream receiver needs a context source"
);
Self {
inner,
host_ctx,
sid,
call_guard,
}
}
fn host_ctx(&self) -> &HostContext {
match (&self.call_guard, &self.host_ctx) {
(Some(guard), _) => &guard.plugin.host_ctx,
(None, Some(host_ctx)) => host_ctx,
(None, None) => unreachable!("checked at construction"),
}
}
pub async fn recv(&mut self) -> Option<StreamFrame> {
self.inner.recv().await
}
}
impl Drop for StreamReceiver {
fn drop(&mut self) {
context::cleanup_sid(self.host_ctx(), self.sid);
self.inner.recycle();
}
}
pub(crate) type FastPendingMap = DashMap<u64, Pending, FxBuildHasher>;
pub(crate) type FastStateMap = DashMap<u64, HashMap<String, Vec<u8>>, FxBuildHasher>;
pub(crate) struct UnaryResultSlot {
pub(crate) sid: u64,
pub(crate) result: Option<(NrStatus, Vec<u8>)>,
}