a2a_sdk/
jsonrpc.rs

1use std::fmt::Display;
2use std::sync::Arc;
3
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7// JSON RPC serde inspired by https://github.com/4t145/rmcp/
8#[allow(dead_code)]
9pub trait ConstString: Default {
10	const VALUE: &str;
11	fn as_string(&self) -> &'static str {
12		Self::VALUE
13	}
14}
15#[macro_export]
16macro_rules! const_string {
17	($name:ident = $value:literal) => {
18		#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
19		pub struct $name;
20
21		impl ConstString for $name {
22			const VALUE: &str = $value;
23		}
24
25		impl serde::Serialize for $name {
26			fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
27			where
28				S: serde::Serializer,
29			{
30				$value.serialize(serializer)
31			}
32		}
33
34		impl<'de> serde::Deserialize<'de> for $name {
35			fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
36			where
37				D: serde::Deserializer<'de>,
38			{
39				let s: String = serde::Deserialize::deserialize(deserializer)?;
40				if s == $value {
41					Ok($name)
42				} else {
43					Err(serde::de::Error::custom(format!(concat!(
44						"expect const string value \"",
45						$value,
46						"\""
47					))))
48				}
49			}
50		}
51	};
52}
53
54const_string!(JsonRpcVersion2_0 = "2.0");
55#[derive(Debug, Clone, Eq, PartialEq, Hash)]
56pub enum NumberOrString {
57	Number(u32),
58	String(Arc<str>),
59}
60
61impl NumberOrString {
62	pub fn into_json_value(self) -> Value {
63		match self {
64			NumberOrString::Number(n) => Value::Number(serde_json::Number::from(n)),
65			NumberOrString::String(s) => Value::String(s.to_string()),
66		}
67	}
68}
69
70impl std::fmt::Display for NumberOrString {
71	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72		match self {
73			NumberOrString::Number(n) => Display::fmt(&n, f),
74			NumberOrString::String(s) => Display::fmt(&s, f),
75		}
76	}
77}
78
79impl Serialize for NumberOrString {
80	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
81	where
82		S: serde::Serializer,
83	{
84		match self {
85			NumberOrString::Number(n) => n.serialize(serializer),
86			NumberOrString::String(s) => s.serialize(serializer),
87		}
88	}
89}
90
91impl<'de> Deserialize<'de> for NumberOrString {
92	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
93	where
94		D: serde::Deserializer<'de>,
95	{
96		let value: Value = Deserialize::deserialize(deserializer)?;
97		match value {
98			Value::Number(n) => Ok(NumberOrString::Number(
99				n.as_u64()
100					.ok_or(serde::de::Error::custom("Expect an integer"))? as u32,
101			)),
102			Value::String(s) => Ok(NumberOrString::String(s.into())),
103			_ => Err(serde::de::Error::custom("Expect number or string")),
104		}
105	}
106}
107
108pub type RequestId = NumberOrString;
109#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
110pub struct JsonRpcRequest<R = Request> {
111	pub jsonrpc: JsonRpcVersion2_0,
112	pub id: RequestId,
113	#[serde(flatten)]
114	pub request: R,
115}
116#[derive(Debug, Clone)]
117pub struct Request<M = String, P = JsonObject> {
118	pub method: M,
119	pub params: P,
120}
121
122impl<M, R> Serialize for Request<M, R>
123where
124	M: Serialize,
125	R: Serialize,
126{
127	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
128	where
129		S: serde::Serializer,
130	{
131		Proxy::serialize(
132			&Proxy {
133				method: &self.method,
134				params: &self.params,
135			},
136			serializer,
137		)
138	}
139}
140
141#[derive(Serialize, Deserialize)]
142struct Proxy<M, P> {
143	method: M,
144	params: P,
145}
146
147impl<'de, M, R> Deserialize<'de> for Request<M, R>
148where
149	M: Deserialize<'de>,
150	R: Deserialize<'de>,
151{
152	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
153	where
154		D: serde::Deserializer<'de>,
155	{
156		let body = Proxy::deserialize(deserializer)?;
157		Ok(Request {
158			method: body.method,
159			params: body.params,
160		})
161	}
162}
163
164pub type JsonObject<F = Value> = serde_json::Map<String, F>;
165
166#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
167pub struct JsonRpcResponse<R = JsonObject> {
168	pub jsonrpc: JsonRpcVersion2_0,
169	pub id: RequestId,
170	pub result: R,
171}