use std::sync::Arc;
use derive_more::{Display, From};
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[derive(
Debug, PartialEq, Clone, Hash, Eq, Deserialize, Serialize, PartialOrd, Ord, Display, From,
)]
#[serde(untagged)]
#[allow(
clippy::exhaustive_enums,
reason = "This comes from the JSON-RPC specification itself"
)]
#[from(String, i64)]
pub enum RequestId {
#[display("null")]
Null,
Number(i64),
Str(String),
}
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[allow(
clippy::exhaustive_structs,
reason = "This comes from the JSON-RPC specification itself"
)]
#[cfg_attr(feature = "schemars", schemars(rename = "{Params}", extend("x-docs-ignore" = true)))]
#[skip_serializing_none]
pub struct Request<Params> {
pub id: RequestId,
pub method: Arc<str>,
pub params: Option<Params>,
}
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[allow(
clippy::exhaustive_enums,
reason = "This comes from the JSON-RPC specification itself"
)]
#[serde(untagged)]
#[cfg_attr(feature = "schemars", schemars(rename = "{Result}", extend("x-docs-ignore" = true)))]
pub enum Response<Result, Error = super::Error> {
Result {
id: RequestId,
#[serde(
deserialize_with = "Deserialize::deserialize",
bound(deserialize = "Result: Deserialize<'de>")
)]
result: Result,
},
Error {
id: RequestId,
error: Error,
},
}
impl<R, E> Response<R, E> {
#[must_use]
pub fn new(id: impl Into<RequestId>, result: std::result::Result<R, E>) -> Self {
match result {
Ok(result) => Self::Result {
id: id.into(),
result,
},
Err(error) => Self::Error {
id: id.into(),
error,
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::{Number, Value};
#[test]
fn id_deserialization() {
let id = serde_json::from_value::<RequestId>(Value::Null).unwrap();
assert_eq!(id, RequestId::Null);
let id = serde_json::from_value::<RequestId>(Value::Number(Number::from_u128(1).unwrap()))
.unwrap();
assert_eq!(id, RequestId::Number(1));
let id = serde_json::from_value::<RequestId>(Value::Number(Number::from_i128(-1).unwrap()))
.unwrap();
assert_eq!(id, RequestId::Number(-1));
let id = serde_json::from_value::<RequestId>(Value::String("id".to_owned())).unwrap();
assert_eq!(id, RequestId::Str("id".to_owned()));
}
#[test]
fn id_serialization() {
let id = serde_json::to_value(RequestId::Null).unwrap();
assert_eq!(id, Value::Null);
let id = serde_json::to_value(RequestId::Number(1)).unwrap();
assert_eq!(id, Value::Number(Number::from_u128(1).unwrap()));
let id = serde_json::to_value(RequestId::Number(-1)).unwrap();
assert_eq!(id, Value::Number(Number::from_i128(-1).unwrap()));
let id = serde_json::to_value(RequestId::Str("id".to_owned())).unwrap();
assert_eq!(id, Value::String("id".to_owned()));
}
#[test]
fn id_display() {
let id = RequestId::Null;
assert_eq!(id.to_string(), "null");
let id = RequestId::Number(1);
assert_eq!(id.to_string(), "1");
let id = RequestId::Number(-1);
assert_eq!(id.to_string(), "-1");
let id = RequestId::Str("id".to_owned());
assert_eq!(id.to_string(), "id");
}
}