unitree_sdk2_rs 0.1.0

Unitree SDK2 的 Rust 封装:msg 驱动的 DDS 类型生成 + CDR 序列化 + 订阅/发布/RPC
use std::sync::Arc;
use anyhow::Context;
use cxx::UniquePtr;
use serde::{Deserialize, Serialize};
use crate::{rpc_ffi, RpcRequestHandler};

// ponytail: DDS 对象内部有锁,多线程安全
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); }

    /// RPC 调用(在 blocking 线程池执行,不阻塞当前任务)
    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)));
    }

    /// 启动 RPC 服务(在 blocking 线程池运行)
    pub async fn start(self: Arc<Self>) {
        if let Err(e) = tokio::task::spawn_blocking(move || self.inner.start()).await {
            log::error!("RPC 服务线程异常退出: {e}");
        }
    }
}