use serde::{Deserialize, Serialize};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[derive(Debug, Serialize, Deserialize)]
pub struct Request {
pub cmd: String,
#[serde(default)]
pub args: serde_json::Value,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Response {
pub ok: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
impl Response {
pub fn ok(data: impl Into<serde_json::Value>) -> Self {
Self {
ok: true,
data: Some(data.into()),
error: None,
}
}
pub fn ok_text(msg: impl Into<String>) -> Self {
Self::ok(serde_json::Value::String(msg.into()))
}
pub fn err(msg: impl Into<String>) -> Self {
Self {
ok: false,
data: None,
error: Some(msg.into()),
}
}
}
pub async fn write_msg<W: AsyncWriteExt + Unpin>(
writer: &mut W,
msg: &impl Serialize,
) -> std::io::Result<()> {
let payload = serde_json::to_vec(msg).map_err(|e| std::io::Error::other(e.to_string()))?;
let len = (payload.len() as u32).to_be_bytes();
writer.write_all(&len).await?;
writer.write_all(&payload).await?;
writer.flush().await?;
Ok(())
}
pub async fn read_msg<R: AsyncReadExt + Unpin, T: for<'de> Deserialize<'de>>(
reader: &mut R,
) -> std::io::Result<T> {
let mut len_buf = [0u8; 4];
reader.read_exact(&mut len_buf).await?;
let len = u32::from_be_bytes(len_buf) as usize;
if len > 64 * 1024 * 1024 {
return Err(std::io::Error::other("message too large (>64MB)"));
}
let mut buf = vec![0u8; len];
reader.read_exact(&mut buf).await?;
serde_json::from_slice(&buf).map_err(|e| std::io::Error::other(e.to_string()))
}