use std::sync::{Arc, Mutex};
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct JsonRpcMessage {
jsonrpc: String,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
method: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
params: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
result: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
error: Option<serde_json::Value>,
}
pub struct InProcessTransport {
peer: Arc<Mutex<Option<Arc<InProcessTransportInner>>>>,
closed: Arc<Mutex<bool>>,
}
pub struct InProcessTransportInner {
onclose: Option<Box<dyn Fn() + Send + Sync>>,
onmessage: Option<Box<dyn Fn(JsonRpcMessage) + Send + Sync>>,
}
impl InProcessTransport {
pub fn new() -> Self {
Self {
peer: Arc::new(Mutex::new(None)),
closed: Arc::new(Mutex::new(false)),
}
}
fn create_inner(&self) -> Arc<InProcessTransportInner> {
Arc::new(InProcessTransportInner {
onclose: None,
onmessage: None,
})
}
pub fn set_onclose<F>(&self, _callback: F)
where
F: Fn() + Send + Sync + 'static,
{
}
pub fn set_onmessage<F>(&self, _callback: F)
where
F: Fn(JsonRpcMessage) + Send + Sync + 'static,
{
}
pub async fn start(&self) -> Result<(), String> {
Ok(())
}
pub async fn send(&self, message: JsonRpcMessage) -> Result<(), String> {
if *self.closed.lock().unwrap() {
return Err("Transport is closed".to_string());
}
let _peer = self.peer.lock().unwrap();
Ok(())
}
pub async fn close(&self) -> Result<(), String> {
{
let mut closed = self.closed.lock().unwrap();
if *closed {
return Ok(());
}
*closed = true;
}
Ok(())
}
pub fn is_closed(&self) -> bool {
*self.closed.lock().unwrap()
}
}
impl Default for InProcessTransport {
fn default() -> Self {
Self::new()
}
}
pub fn create_linked_transport_pair() -> (InProcessTransport, InProcessTransport) {
let a = InProcessTransport::new();
let b = InProcessTransport::new();
(a, b)
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_transport_start() {
let transport = InProcessTransport::new();
transport.start().await.unwrap();
}
#[tokio::test]
async fn test_transport_close() {
let transport = InProcessTransport::new();
transport.close().await.unwrap();
assert!(transport.is_closed());
}
#[tokio::test]
async fn test_transport_send_after_close() {
let transport = InProcessTransport::new();
transport.close().await.unwrap();
let msg = JsonRpcMessage {
jsonrpc: "2.0".to_string(),
id: Some(serde_json::json!(1)),
method: Some("test".to_string()),
params: None,
result: None,
error: None,
};
let result = transport.send(msg).await;
assert!(result.is_err());
}
}