use serde_json::Value;
use crate::error::WireError;
use crate::protocol::{
Event, JsonRpcErrorResponse, JsonRpcNotification, JsonRpcRequest, JsonRpcSuccessResponse,
RawWireMessage, Request,
};
#[derive(Debug, Clone)]
pub enum WireMessage {
Request(JsonRpcRequest<Request>),
Event(JsonRpcNotification<Event>),
SuccessResponse(JsonRpcSuccessResponse<Value>),
ErrorResponse(JsonRpcErrorResponse),
}
pub fn parse_wire_message(raw: RawWireMessage) -> Result<WireMessage, WireError> {
if let Some(method) = raw.method {
match method.as_str() {
"request" => {
let params: Value = raw.params.ok_or(WireError::InvalidPayloadType)?;
let req: JsonRpcRequest<Request> = JsonRpcRequest {
jsonrpc: raw.jsonrpc,
method,
id: raw.id.unwrap_or_default(),
params: serde_json::from_value(params).map_err(|e| {
WireError::JsonParse(format!("failed to parse request params: {e}"))
})?,
};
Ok(WireMessage::Request(req))
}
"event" => {
let params: Value = raw.params.ok_or(WireError::InvalidPayloadType)?;
let ev: Event = serde_json::from_value(params).map_err(|e| {
WireError::JsonParse(format!("failed to parse event params: {e}"))
})?;
let notification = JsonRpcNotification {
jsonrpc: raw.jsonrpc,
method,
params: ev,
};
Ok(WireMessage::Event(notification))
}
other => Err(WireError::UnknownMessageType(other.to_string())),
}
} else if raw.error.is_some() {
let id = raw.id.unwrap_or_default();
let error = raw
.error
.ok_or_else(|| WireError::Internal("error response missing error field".to_string()))?;
Ok(WireMessage::ErrorResponse(JsonRpcErrorResponse {
jsonrpc: raw.jsonrpc,
id,
error,
}))
} else if raw.result.is_some() {
let id = raw.id.unwrap_or_default();
let result = raw.result.ok_or_else(|| {
WireError::Internal("success response missing result field".to_string())
})?;
Ok(WireMessage::SuccessResponse(JsonRpcSuccessResponse {
jsonrpc: raw.jsonrpc,
id,
result,
}))
} else {
Err(WireError::UnknownMessageType(
"unrecognized wire message shape".to_string(),
))
}
}