use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use serde::{Serialize, Deserialize, de::DeserializeOwned};
use crate::error::{Error, Result};
use crate::communication::{RpcChannel, CommunicationChannel, StringHandlerFunction, ByteHandlerFunction};
pub struct JsonRpcChannel {
#[allow(dead_code)]
channel: Arc<dyn CommunicationChannel>,
host_functions: Mutex<HashMap<String, StringHandlerFunction>>,
#[allow(dead_code)]
call_id: Mutex<u64>,
}
impl JsonRpcChannel {
pub fn new(channel: Arc<dyn CommunicationChannel>) -> Self {
Self {
channel,
host_functions: Mutex::new(HashMap::new()),
call_id: Mutex::new(0),
}
}
#[allow(dead_code)]
fn next_call_id(&self) -> u64 {
let mut id = self.call_id.lock().unwrap();
*id += 1;
*id
}
#[allow(dead_code)]
fn serialize<T: Serialize>(&self, value: &T) -> Result<String> {
serde_json::to_string(value)
.map_err(|e| Error::Json(e))
}
#[allow(dead_code)]
fn deserialize<T: DeserializeOwned>(&self, data: &str) -> Result<T> {
serde_json::from_str(data)
.map_err(|e| Error::Json(e))
}
}
#[derive(Debug, Serialize, Deserialize)]
struct RpcRequest {
id: u64,
method: String,
params: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct RpcResponse {
id: u64,
result: Option<String>,
error: Option<String>,
}
impl RpcChannel for JsonRpcChannel {
fn register_host_function_json(
&mut self,
name: &str,
function: StringHandlerFunction,
) -> Result<()> {
let mut functions = self.host_functions.lock().unwrap();
functions.insert(name.to_string(), function);
Ok(())
}
fn call_guest_function_json(
&self,
function_name: &str,
params_json: &str,
) -> Result<String> {
let _request = RpcRequest {
id: 1,
method: function_name.to_string(),
params: serde_json::from_str(params_json).map_err(|e| Error::Json(e))?,
};
let response = RpcResponse {
id: 1,
result: Some("mock_result".to_string()),
error: None,
};
serde_json::to_string(&response).map_err(|e| Error::Json(e))
}
fn register_host_function_msgpack(
&mut self,
name: &str,
function: ByteHandlerFunction,
) -> Result<()> {
let json_function = move |params_json: &str| -> Result<String> {
let params_bytes = params_json.as_bytes();
let result_bytes = function(params_bytes)?;
Ok(String::from_utf8_lossy(&result_bytes).to_string())
};
self.register_host_function_json(name, Box::new(json_function))
}
fn call_guest_function_msgpack(
&self,
function_name: &str,
params_msgpack: &[u8],
) -> Result<Vec<u8>> {
let params_json = String::from_utf8_lossy(params_msgpack);
let result_json = self.call_guest_function_json(function_name, ¶ms_json)?;
Ok(result_json.into_bytes())
}
}
pub struct RpcFactory {
channel_factory: Arc<dyn crate::communication::CommunicationFactory>,
}
impl RpcFactory {
pub fn new(channel_factory: Arc<dyn crate::communication::CommunicationFactory>) -> Self {
Self {
channel_factory,
}
}
pub fn create_channel(&self, _name: &str) -> Result<Arc<dyn RpcChannel>> {
let channel = self.channel_factory.create_channel()?;
let rpc_channel = JsonRpcChannel::new(channel);
Ok(Arc::new(rpc_channel))
}
}