1#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "README.md" ) ) ]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![deny(missing_docs)]
4
5use serde::{Deserialize, Serialize};
6
7const JSONRPC_VERSION: &str = "2.0";
8
9#[cfg(feature = "canonical")]
10const VERSION_HEADER: Option<()> = Some(());
11#[cfg(not(feature = "canonical"))]
12const VERSION_HEADER: Option<()> = None;
13
14#[cfg(feature = "canonical")]
15const ERR_INVALID_PROTOCOL_VERSION: &str = "Invalid protocol version";
16
17#[cfg(feature = "std")]
18pub type Id = serde_json::Value;
20#[cfg(not(feature = "std"))]
21pub type Id = u32;
23
24#[cfg(feature = "std")]
25type String = std::string::String;
26#[cfg(not(feature = "std"))]
27type String = heapless::String<128>;
28
29#[cfg(feature = "std")]
30pub mod client;
32#[cfg(feature = "std")]
33pub mod dataformat;
35pub mod request;
37pub mod response;
39#[cfg(feature = "std")]
40pub mod server;
42pub mod tools;
44
45fn de_validate_version<'de, D>(deserializer: D) -> Result<Option<()>, D::Error>
46where
47 D: serde::Deserializer<'de>,
48{
49 let version: Option<&str> = Deserialize::deserialize(deserializer)?;
50 #[cfg(feature = "canonical")]
51 if version.map_or(false, |v| v != JSONRPC_VERSION) {
52 return Err(serde::de::Error::custom(ERR_INVALID_PROTOCOL_VERSION));
53 }
54 Ok(version.map(|_| ()))
55}
56
57#[allow(clippy::trivially_copy_pass_by_ref)]
58fn serialize_version<S>(_: &Option<()>, serializer: S) -> Result<S::Ok, S::Error>
59where
60 S: serde::Serializer,
61{
62 JSONRPC_VERSION.serialize(serializer)
63}
64
65const RPC_ERROR_PARSE_ERROR: i16 = -32700;
66const RPC_ERROR_INVALID_REQUEST: i16 = -32600;
67const RPC_ERROR_METHOD_NOT_FOUND: i16 = -32601;
68const RPC_ERROR_INVALID_PARAMS: i16 = -32602;
69const RPC_ERROR_INTERNAL_ERROR: i16 = -32603;
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum RpcErrorKind {
74 ParseError,
76 InvalidRequest,
78 MethodNotFound,
80 InvalidParams,
82 InternalError,
84 Custom(i16),
86}
87
88#[cfg(feature = "std")]
89impl core::fmt::Display for RpcErrorKind {
90 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91 write!(f, "{}", i16::from(*self))
92 }
93}
94
95impl From<i16> for RpcErrorKind {
96 fn from(code: i16) -> Self {
97 match code {
98 RPC_ERROR_PARSE_ERROR => RpcErrorKind::ParseError,
99 RPC_ERROR_INVALID_REQUEST => RpcErrorKind::InvalidRequest,
100 RPC_ERROR_METHOD_NOT_FOUND => RpcErrorKind::MethodNotFound,
101 RPC_ERROR_INVALID_PARAMS => RpcErrorKind::InvalidParams,
102 RPC_ERROR_INTERNAL_ERROR => RpcErrorKind::InternalError,
103 _ => RpcErrorKind::Custom(code),
104 }
105 }
106}
107
108impl From<RpcErrorKind> for i16 {
109 fn from(code: RpcErrorKind) -> Self {
110 match code {
111 RpcErrorKind::ParseError => RPC_ERROR_PARSE_ERROR,
112 RpcErrorKind::InvalidRequest => RPC_ERROR_INVALID_REQUEST,
113 RpcErrorKind::MethodNotFound => RPC_ERROR_METHOD_NOT_FOUND,
114 RpcErrorKind::InvalidParams => RPC_ERROR_INVALID_PARAMS,
115 RpcErrorKind::InternalError => RPC_ERROR_INTERNAL_ERROR,
116 RpcErrorKind::Custom(code) => code,
117 }
118 }
119}
120
121impl Serialize for RpcErrorKind {
122 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
123 where
124 S: serde::Serializer,
125 {
126 i16::from(*self).serialize(serializer)
127 }
128}
129
130impl<'de> Deserialize<'de> for RpcErrorKind {
131 fn deserialize<D>(deserializer: D) -> Result<RpcErrorKind, D::Error>
132 where
133 D: serde::Deserializer<'de>,
134 {
135 i16::deserialize(deserializer).map(RpcErrorKind::from)
136 }
137}
138
139#[derive(Serialize, Deserialize, Debug)]
141pub struct RpcError {
142 #[serde(rename = "code")]
143 kind: RpcErrorKind,
144 #[serde(skip_serializing_if = "Option::is_none")]
145 message: Option<String>,
146}
147
148impl RpcError {
149 pub fn new0(kind: RpcErrorKind) -> Self {
151 Self {
152 kind,
153 message: None,
154 }
155 }
156 pub fn new(kind: RpcErrorKind, message: String) -> Self {
159 Self {
160 kind,
161 message: Some(message),
162 }
163 }
164 pub fn kind(&self) -> RpcErrorKind {
166 self.kind
167 }
168 pub fn message(&self) -> Option<&str> {
170 self.message.as_deref()
171 }
172}
173
174#[cfg(feature = "std")]
175impl core::fmt::Display for RpcError {
176 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177 if let Some(message) = &self.message {
178 write!(f, "{} ({})", message, self.kind)
179 } else {
180 write!(f, "{}", self.kind)
181 }
182 }
183}
184
185#[cfg(feature = "std")]
186impl std::error::Error for RpcError {}
187
188pub type RpcResult<R> = Result<R, RpcError>;