use std::cell::RefCell;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use crate::value::{VmError, VmValue};
use super::turn_cache;
pub type HostCallDispatchFuture<'a> =
Pin<Box<dyn Future<Output = Result<Option<VmValue>, VmError>> + Send + 'a>>;
pub fn host_call_ready(
result: Result<Option<VmValue>, VmError>,
) -> HostCallDispatchFuture<'static> {
Box::pin(async move { result })
}
pub trait HostCallBridge: Send + Sync {
fn dispatch<'a>(
&'a self,
capability: &'a str,
operation: &'a str,
params: &'a crate::value::DictMap,
) -> HostCallDispatchFuture<'a>;
fn list_tools(&self) -> Result<Option<VmValue>, VmError> {
Ok(None)
}
fn call_tool(&self, _name: &str, _args: &VmValue) -> Result<Option<VmValue>, VmError> {
Ok(None)
}
}
thread_local! {
pub(super) static HOST_CALL_BRIDGE: RefCell<Option<Arc<dyn HostCallBridge>>> =
const { RefCell::new(None) };
}
pub fn set_host_call_bridge(bridge: Arc<dyn HostCallBridge>) {
turn_cache::reset();
HOST_CALL_BRIDGE.with(|b| *b.borrow_mut() = Some(bridge));
}
pub fn clear_host_call_bridge() {
turn_cache::reset();
HOST_CALL_BRIDGE.with(|b| *b.borrow_mut() = None);
}
pub async fn dispatch_host_call_bridge(
capability: &str,
operation: &str,
params: &crate::value::DictMap,
) -> Option<Result<VmValue, VmError>> {
let bridge = HOST_CALL_BRIDGE.with(|b| b.borrow().clone())?;
match bridge.dispatch(capability, operation, params).await {
Ok(Some(value)) => Some(Ok(value)),
Ok(None) => None,
Err(error) => Some(Err(error)),
}
}