smol_jsonrpc/
request.rs

1use alloc::string::String;
2use serde_json::json;
3
4use crate::{id_from_value, Error, ErrorCode, Result};
5
6/// A JSON-RPC request object
7#[repr(C)]
8#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
9pub struct Request {
10    jsonrpc: serde_json::Value,
11    id: Option<serde_json::Value>,
12    method: Option<serde_json::Value>,
13    params: Option<serde_json::Value>,
14}
15
16impl Request {
17    /// Creates a new [Request].
18    pub fn new() -> Self {
19        Self {
20            jsonrpc: json!(String::from("2.0")),
21            id: None,
22            method: None,
23            params: None,
24        }
25    }
26
27    /// Creates a new [Request] with all [null](serde_json::Value::Null) fields.
28    pub fn new_null() -> Self {
29        Self {
30            jsonrpc: serde_json::Value::Null,
31            id: None,
32            method: None,
33            params: None,
34        }
35    }
36
37    /// Gets the JSON-RPC identifier string.
38    ///
39    /// This value should always be `"2.0"`, but may also be [null](serde_json::Value::Null) or malformed.
40    pub fn jsonrpc(&self) -> Option<&str> {
41        self.jsonrpc.as_str()
42    }
43
44    /// Gets the ID.
45    pub fn id(&self) -> Option<u64> {
46        self.id.as_ref().map(|id| id_from_value(id).unwrap_or(0))
47    }
48
49    /// Sets the ID.
50    pub fn set_id(&mut self, id: u64) {
51        self.id = Some(json!(id));
52    }
53
54    /// Builder function to set ID.
55    pub fn with_id(mut self, id: u64) -> Self {
56        self.set_id(id);
57        self
58    }
59
60    /// Gets the method.
61    pub fn method(&self) -> Option<&str> {
62        if let Some(m) = self.method.as_ref() {
63            m.as_str()
64        } else {
65            None
66        }
67    }
68
69    /// Sets the method.
70    pub fn set_method(&mut self, method: &str) {
71        self.method = Some(json!(String::from(method)));
72    }
73
74    /// Builder function to set method.
75    pub fn with_method(mut self, method: &str) -> Self {
76        self.set_method(method);
77        self
78    }
79
80    /// Gets whether the params field is [null](serde_json::Value::Null).
81    pub fn params_is_null(&self) -> bool {
82        self.params.is_none()
83    }
84
85    /// Gets the [Request] parameters.
86    ///
87    /// Attempts to parse the parameter as the provided type, returns `Err(_)` on failure.
88    pub fn params<T: for<'de> serde::Deserialize<'de>>(&self) -> Result<T> {
89        if let Some(p) = self.params.as_ref() {
90            serde_json::from_value::<T>(p.clone()).map_err(|err| err.into())
91        } else {
92            Err(Error::new()
93                .with_code(ErrorCode::InvalidParams)
94                .with_message("null Params field"))
95        }
96    }
97
98    /// Sets the [Request] parameters.
99    pub fn set_params<T: serde::Serialize>(&mut self, params: T) {
100        self.params = Some(json!(params));
101    }
102
103    /// Builder function to set the [Request] parameters.
104    pub fn with_params<T: serde::Serialize>(mut self, params: T) -> Self {
105        self.set_params(params);
106        self
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_request() -> Result<()> {
116        let exp_request =
117            "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"test_method\",\"params\":null}";
118        let exp_params_request =
119            "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"test_params\",\"params\":[0,1,2,3]}";
120
121        let request = Request::new().with_id(1).with_method("test_method");
122
123        let params_request = Request::new()
124            .with_id(1)
125            .with_method("test_params")
126            .with_params([0, 1, 2, 3]);
127
128        assert_eq!(serde_json::to_string(&request)?.as_str(), exp_request);
129        assert_eq!(
130            serde_json::to_string(&params_request)?.as_str(),
131            exp_params_request
132        );
133
134        Ok(())
135    }
136}