jsonrpc_base/
request.rs

1use super::{helpers, Error};
2use alloc::string::{String, ToString};
3use core::{fmt, str::FromStr};
4use serde::{Deserialize, Serialize};
5use serde_json::{Number, Value};
6
7/// JSON-RPC request
8#[derive(Serialize, Deserialize, Debug, Clone)]
9pub struct Request {
10    /// Protocol header
11    pub jsonrpc: String,
12    /// Request ID
13    pub id: Value,
14    /// Method name
15    pub method: String,
16
17    /// Optional method arguments
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub params: Option<Value>,
20}
21
22impl Request {
23    /// Create a new request with the provided method.
24    ///
25    /// Will generate a random ID, if the feature `uuid` is enabled. Otherwise, set the ID to `0`.
26    pub fn new<M>(method: M) -> Self
27    where
28        M: ToString,
29    {
30        #[cfg(feature = "uuid")]
31        let id = Value::String(uuid::Uuid::new_v4().to_string());
32
33        #[cfg(not(feature = "uuid"))]
34        let id = Value::Number(0.into());
35
36        Request {
37            id,
38            jsonrpc: "2.0".to_string(),
39            method: method.to_string(),
40            params: None,
41        }
42    }
43
44    /// Replace the method ID with the provided numeric value
45    pub fn with_id<I>(mut self, id: I) -> Self
46    where
47        I: Into<Number>,
48    {
49        self.id = Value::Number(id.into());
50        self
51    }
52
53    /// Replace the method ID with the provided string
54    pub fn with_id_string<I>(mut self, id: I) -> Self
55    where
56        I: ToString,
57    {
58        self.id = Value::String(id.to_string());
59        self
60    }
61
62    /// Replace the methods arguments with the provided value
63    pub fn with_params<P>(self, params: P) -> Result<Self, Error>
64    where
65        P: Serialize,
66    {
67        serde_json::to_value(params)
68            .map_err(|e| Error {
69                code: Error::PARSE_ERROR,
70                message: e.to_string(),
71                data: None,
72            })
73            .map(|params| self.with_params_value(params))
74    }
75
76    /// Replace the methods arguments with the parsed value
77    pub fn with_params_value(mut self, params: Value) -> Self {
78        self.params = Some(params);
79        self
80    }
81
82    /// Split the request into its ID and message
83    pub fn prepare(&self) -> (Value, String) {
84        let id = self.id.clone();
85        let message = self.to_string();
86        (id, message)
87    }
88
89    /// Parse a message into the request, returning the remainder string
90    pub fn parse(s: &str) -> Result<(Self, &str), Error> {
91        let (message, remainder) = helpers::get_content_length(s)?;
92        let request = Request::parse_json(message)?;
93        Ok((request, remainder))
94    }
95
96    /// Parse a request from the provided JSON
97    pub fn parse_json(json: &str) -> Result<Self, Error> {
98        serde_json::from_str(json).map_err(|e| Error {
99            code: Error::INVALID_REQUEST,
100            message: e.to_string(),
101            data: Some(Value::String(json.to_string())),
102        })
103    }
104}
105
106impl FromStr for Request {
107    type Err = Error;
108
109    fn from_str(s: &str) -> Result<Self, Self::Err> {
110        Self::parse(s).map(|(json, _)| json)
111    }
112}
113
114impl fmt::Display for Request {
115    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116        serde_json::to_string(&self)
117            .map_err(|_| fmt::Error)
118            .and_then(|m| write!(f, "Content-Length: {}\r\n\r\n{}", m.len(), m))
119    }
120}
121
122#[cfg(feature = "std")]
123mod io {
124    use super::*;
125    use std::io::prelude::*;
126
127    impl Request {
128        /// Read a request from a reader.
129        ///
130        /// Returns the number of consumed bytes and the request.
131        pub fn try_from_reader<R>(reader: R) -> Result<(usize, Self), Error>
132        where
133            R: Read,
134        {
135            let (n, contents) = helpers::get_content_from_reader(reader)?;
136            let request = Request::parse_json(&contents)?;
137            Ok((n, request))
138        }
139
140        /// Write a request to a writer and return the number of bytes written.
141        pub fn try_to_writer<W>(&self, mut writer: W) -> Result<usize, Error>
142        where
143            W: Write,
144        {
145            writer
146                .write(self.to_string().as_bytes())
147                .map_err(|e| Error {
148                    code: Error::PARSE_ERROR,
149                    message: e.to_string(),
150                    data: serde_json::to_value(&self).ok(),
151                })
152        }
153    }
154}