1use bytes::{BufMut, Bytes};
2use serde_derive::{Deserialize, Serialize};
3use serde_json::Value;
4
5use crate::parse::{generate_request_headers, split_bytes};
6use crate::response::Error;
7use crate::types::Params;
8
9#[derive(Default, Debug, Clone, Serialize, Deserialize)]
10pub struct Request {
11 jsonrpc: String,
12 method: String,
13 id: String,
14 params: Params,
15}
16
17impl Request {
18 pub fn new(method: String, id: String, params: Params) -> Self {
19 let jsonrpc = "2.0".into();
20
21 Request {
22 jsonrpc,
23 method,
24 id,
25 params,
26 }
27 }
28
29 pub fn parse_from_json(value: Value) -> Result<Self, Error> {
30 let id = if let Some(id) = value.get("id") {
31 if id.is_number() {
32 id.as_u64().unwrap_or(0).to_string()
33 } else if id.is_string() {
34 id.as_str().unwrap().into()
35 } else {
36 " ".into()
37 }
38 } else {
39 " ".into()
40 };
41
42 if value.get("result").is_some() || value.get("error").is_some() {
44 return Err(Error::InvalidRequest("".into(), id));
45 }
46
47 if value.get("method").is_none() {
48 return Err(Error::MethodNotFound("".into(), id));
49 }
50
51 let method = value.get("method").unwrap().as_str().unwrap().into();
52
53 let params = if let Some(params) = value.get("params") {
54 params.clone()
55 } else {
56 Value::Null
57 };
58
59 let jsonrpc = "2.0".into();
60
61 Ok(Request {
62 jsonrpc,
63 method,
64 id,
65 params,
66 })
67 }
68
69 pub fn parse(bytes: Bytes) -> Result<Self, Error> {
70 split_bytes(bytes).and_then(|value| Request::parse_from_json(value))
71 }
72
73 pub fn parse_from_json_bytes(bytes: Bytes) -> Result<Self, Error> {
74 serde_json::from_slice(&bytes[..])
75 .or(Err(Error::ParseError(None)))
76 .and_then(|value| Request::parse_from_json(value))
77 }
78
79 pub fn deparse(&self) -> Bytes {
80 let body = serde_json::to_string(&self).unwrap();
81
82 let body_bytes = body.as_bytes();
83
84 let mut headers =
85 generate_request_headers("Hyperdrive_RPC_Request".into(), body_bytes.len());
86 headers.put(body_bytes);
87 headers.freeze()
88 }
89
90 pub fn method(&self) -> &String {
91 &self.method
92 }
93
94 pub fn params(&self) -> &Params {
95 &self.params
96 }
97
98 pub fn id(&self) -> &String {
99 &self.id
100 }
101}