agent_client_protocol_schema/v1/
rpc.rs1use std::sync::Arc;
4
5use derive_more::{Display, From};
6use serde::{Deserialize, Serialize};
7use serde_with::skip_serializing_none;
8
9#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
19#[derive(
20 Debug, PartialEq, Clone, Hash, Eq, Deserialize, Serialize, PartialOrd, Ord, Display, From,
21)]
22#[serde(untagged)]
23#[allow(
24 clippy::exhaustive_enums,
25 reason = "This comes from the JSON-RPC specification itself"
26)]
27#[from(String, i64)]
28pub enum RequestId {
29 #[display("null")]
31 Null,
32 Number(i64),
34 Str(String),
36}
37
38#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
40#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
41#[allow(
42 clippy::exhaustive_structs,
43 reason = "This comes from the JSON-RPC specification itself"
44)]
45#[cfg_attr(feature = "schemars", schemars(rename = "{Params}", extend("x-docs-ignore" = true)))]
46#[skip_serializing_none]
47pub struct Request<Params> {
48 pub id: RequestId,
50 pub method: Arc<str>,
52 pub params: Option<Params>,
54}
55
56#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
58#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
59#[allow(
60 clippy::exhaustive_enums,
61 reason = "This comes from the JSON-RPC specification itself"
62)]
63#[serde(untagged)]
64#[cfg_attr(feature = "schemars", schemars(rename = "{Result}", extend("x-docs-ignore" = true)))]
65pub enum Response<Result, Error = super::Error> {
66 Result {
68 id: RequestId,
70 #[serde(
73 deserialize_with = "Deserialize::deserialize",
74 bound(deserialize = "Result: Deserialize<'de>")
75 )]
76 result: Result,
77 },
78 Error {
80 id: RequestId,
82 error: Error,
84 },
85}
86
87impl<R, E> Response<R, E> {
88 #[must_use]
90 pub fn new(id: impl Into<RequestId>, result: std::result::Result<R, E>) -> Self {
91 match result {
92 Ok(result) => Self::Result {
93 id: id.into(),
94 result,
95 },
96 Err(error) => Self::Error {
97 id: id.into(),
98 error,
99 },
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 use serde_json::{Number, Value};
109
110 #[test]
111 fn id_deserialization() {
112 let id = serde_json::from_value::<RequestId>(Value::Null).unwrap();
113 assert_eq!(id, RequestId::Null);
114
115 let id = serde_json::from_value::<RequestId>(Value::Number(Number::from_u128(1).unwrap()))
116 .unwrap();
117 assert_eq!(id, RequestId::Number(1));
118
119 let id = serde_json::from_value::<RequestId>(Value::Number(Number::from_i128(-1).unwrap()))
120 .unwrap();
121 assert_eq!(id, RequestId::Number(-1));
122
123 let id = serde_json::from_value::<RequestId>(Value::String("id".to_owned())).unwrap();
124 assert_eq!(id, RequestId::Str("id".to_owned()));
125 }
126
127 #[test]
128 fn id_serialization() {
129 let id = serde_json::to_value(RequestId::Null).unwrap();
130 assert_eq!(id, Value::Null);
131
132 let id = serde_json::to_value(RequestId::Number(1)).unwrap();
133 assert_eq!(id, Value::Number(Number::from_u128(1).unwrap()));
134
135 let id = serde_json::to_value(RequestId::Number(-1)).unwrap();
136 assert_eq!(id, Value::Number(Number::from_i128(-1).unwrap()));
137
138 let id = serde_json::to_value(RequestId::Str("id".to_owned())).unwrap();
139 assert_eq!(id, Value::String("id".to_owned()));
140 }
141
142 #[test]
143 fn id_display() {
144 let id = RequestId::Null;
145 assert_eq!(id.to_string(), "null");
146
147 let id = RequestId::Number(1);
148 assert_eq!(id.to_string(), "1");
149
150 let id = RequestId::Number(-1);
151 assert_eq!(id.to_string(), "-1");
152
153 let id = RequestId::Str("id".to_owned());
154 assert_eq!(id.to_string(), "id");
155 }
156}