use serde::{Deserialize, Serialize};
use serde_json::Value;
use super::subscribe::{METHOD_EVENTS_SUBSCRIBE, SubscribeParams};
use crate::uds::server::JSONRPC_VERSION;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum SubscribeFrameError {
#[error("events.subscribe frame is not a JSON-RPC request: {0}")]
Malformed(#[source] serde_json::Error),
#[error("events.subscribe frame has jsonrpc {found:?}; expected \"2.0\"")]
UnsupportedVersion {
found: String,
},
#[error("frame calls {found:?}, not \"events.subscribe\"")]
WrongMethod {
found: String,
},
#[error("events.subscribe answers only as a stream; send \"stream\": true")]
NotStreaming,
#[error("events.subscribe params rejected: {0}")]
InvalidParams(#[source] serde_json::Error),
}
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct SubscribeRequest {
jsonrpc: &'static str,
pub id: Value,
method: &'static str,
stream: bool,
pub params: SubscribeParams,
}
#[derive(Deserialize)]
struct WireRequest {
#[serde(default)]
jsonrpc: String,
#[serde(default)]
id: Value,
method: String,
#[serde(default)]
stream: bool,
#[serde(default)]
params: Value,
}
impl SubscribeRequest {
pub fn new(id: impl Into<Value>, params: SubscribeParams) -> Self {
Self {
jsonrpc: JSONRPC_VERSION,
id: id.into(),
method: METHOD_EVENTS_SUBSCRIBE,
stream: true,
params,
}
}
pub fn decode(frame: &[u8]) -> Result<Self, SubscribeFrameError> {
let wire: WireRequest =
serde_json::from_slice(frame).map_err(SubscribeFrameError::Malformed)?;
if wire.jsonrpc != JSONRPC_VERSION {
return Err(SubscribeFrameError::UnsupportedVersion {
found: wire.jsonrpc,
});
}
if wire.method != METHOD_EVENTS_SUBSCRIBE {
return Err(SubscribeFrameError::WrongMethod { found: wire.method });
}
if !wire.stream {
return Err(SubscribeFrameError::NotStreaming);
}
let params =
serde_json::from_value(wire.params).map_err(SubscribeFrameError::InvalidParams)?;
Ok(Self::new(wire.id, params))
}
}