use std::sync::Arc;
use anyhow::Context;
use cxx::UniquePtr;
use serde::{Deserialize, Serialize};
use crate::{rpc_ffi, RpcRequestHandler};
unsafe impl Send for rpc_ffi::RpcClient {}
unsafe impl Sync for rpc_ffi::RpcClient {}
unsafe impl Send for rpc_ffi::RpcServer {}
unsafe impl Sync for rpc_ffi::RpcServer {}
pub struct RpcClient {
inner: Arc<UniquePtr<rpc_ffi::RpcClient>>,
}
impl RpcClient {
pub fn new(service: &str) -> anyhow::Result<Self> {
let inner = rpc_ffi::new_rpc_client(service);
if inner.is_null() {
log::error!("ffi::new_rpc_client({service}) 返回空指针");
anyhow::bail!("创建 RpcClient({service}) 失败");
}
Ok(Self { inner: Arc::new(inner) })
}
pub fn register_api(&self, api_id: i32) { self.inner.register_api(api_id); }
pub async fn call(&self, api_id: i32, request: String) -> anyhow::Result<RpcResponse> {
let inner = self.inner.clone();
tokio::task::spawn_blocking(move || {
let raw = inner.call(api_id, &request);
if raw.is_empty() {
log::warn!("RPC call({api_id}) 返回空响应");
}
serde_json::from_str(&raw).context("解析 RPC 响应失败")
}).await.context("RPC spawn_blocking 失败")?
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct RpcResponse { pub code: i32, #[serde(default)] pub data: String }
pub struct RpcServer {
inner: Arc<UniquePtr<rpc_ffi::RpcServer>>,
}
impl RpcServer {
pub fn new(service: &str) -> anyhow::Result<Self> {
let inner = rpc_ffi::new_rpc_server(service);
if inner.is_null() {
log::error!("ffi::new_rpc_server({service}) 返回空指针");
anyhow::bail!("创建 RpcServer({service}) 失败");
}
Ok(Self { inner: Arc::new(inner) })
}
pub fn register_handler(&self, api_id: i32, handler: impl Fn(&str) -> String + Send + 'static) {
self.inner.register_handler(api_id, Box::new(RpcRequestHandler::new(handler)));
}
pub async fn start(self: Arc<Self>) {
if let Err(e) = tokio::task::spawn_blocking(move || self.inner.start()).await {
log::error!("RPC 服务线程异常退出: {e}");
}
}
}