casper_json_rpc/request/
params.rs1use std::fmt::{self, Display, Formatter};
2
3use serde_json::{Map, Value};
4
5use super::ErrorOrRejection;
6use crate::error::{Error, ReservedErrorCode};
7
8#[derive(Clone, Eq, PartialEq, Debug)]
19pub enum Params {
20 Array(Vec<Value>),
22 Object(Map<String, Value>),
24}
25
26impl Params {
27 pub(super) fn try_from(request_id: &Value, params: Value) -> Result<Self, ErrorOrRejection> {
28 let err_invalid_request = |additional_info: &str| {
29 let error = Error::new(ReservedErrorCode::InvalidRequest, additional_info);
30 Err(ErrorOrRejection::Error {
31 id: request_id.clone(),
32 error,
33 })
34 };
35
36 match params {
37 Value::Null => Ok(Params::Array(vec![])),
38 Value::Bool(false) => err_invalid_request(
39 "If present, 'params' must be an Array or Object, but was 'false'",
40 ),
41 Value::Bool(true) => err_invalid_request(
42 "If present, 'params' must be an Array or Object, but was 'true'",
43 ),
44 Value::Number(_) => err_invalid_request(
45 "If present, 'params' must be an Array or Object, but was a Number",
46 ),
47 Value::String(_) => err_invalid_request(
48 "If present, 'params' must be an Array or Object, but was a String",
49 ),
50 Value::Array(array) => Ok(Params::Array(array)),
51 Value::Object(map) => Ok(Params::Object(map)),
52 }
53 }
54
55 pub fn is_array(&self) -> bool {
57 self.as_array().is_some()
58 }
59
60 pub fn as_array(&self) -> Option<&Vec<Value>> {
62 match self {
63 Params::Array(array) => Some(array),
64 _ => None,
65 }
66 }
67
68 pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
71 match self {
72 Params::Array(array) => Some(array),
73 _ => None,
74 }
75 }
76
77 pub fn is_object(&self) -> bool {
79 self.as_object().is_some()
80 }
81
82 pub fn as_object(&self) -> Option<&Map<String, Value>> {
84 match self {
85 Params::Object(map) => Some(map),
86 _ => None,
87 }
88 }
89
90 pub fn as_object_mut(&mut self) -> Option<&mut Map<String, Value>> {
93 match self {
94 Params::Object(map) => Some(map),
95 _ => None,
96 }
97 }
98
99 pub fn is_empty(&self) -> bool {
101 match self {
102 Params::Array(array) => array.is_empty(),
103 Params::Object(map) => map.is_empty(),
104 }
105 }
106}
107
108impl Display for Params {
109 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
110 Display::fmt(&Value::from(self.clone()), formatter)
111 }
112}
113
114impl Default for Params {
116 fn default() -> Self {
117 Params::Array(vec![])
118 }
119}
120
121impl From<Params> for Value {
122 fn from(params: Params) -> Self {
123 match params {
124 Params::Array(array) => Value::Array(array),
125 Params::Object(map) => Value::Object(map),
126 }
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 fn should_fail_to_convert_invalid_params(bad_params: Value, expected_invalid_type_msg: &str) {
135 let original_id = Value::from(1_i8);
136 match Params::try_from(&original_id, bad_params).unwrap_err() {
137 ErrorOrRejection::Error { id, error } => {
138 assert_eq!(id, original_id);
139 let expected_error = format!(
140 r#"{{"code":-32600,"message":"Invalid Request","data":"If present, 'params' must be an Array or Object, but was {}"}}"#,
141 expected_invalid_type_msg
142 );
143 assert_eq!(serde_json::to_string(&error).unwrap(), expected_error);
144 }
145 other => panic!("unexpected: {:?}", other),
146 }
147 }
148
149 #[test]
150 fn should_convert_params_from_null() {
151 let original_id = Value::from(1_i8);
152
153 let params = Params::try_from(&original_id, Value::Null).unwrap();
154 assert!(matches!(params, Params::Array(v) if v.is_empty()));
155 }
156
157 #[test]
158 fn should_fail_to_convert_params_from_false() {
159 should_fail_to_convert_invalid_params(Value::Bool(false), "'false'")
160 }
161
162 #[test]
163 fn should_fail_to_convert_params_from_true() {
164 should_fail_to_convert_invalid_params(Value::Bool(true), "'true'")
165 }
166
167 #[test]
168 fn should_fail_to_convert_params_from_a_number() {
169 should_fail_to_convert_invalid_params(Value::from(9_u8), "a Number")
170 }
171
172 #[test]
173 fn should_fail_to_convert_params_from_a_string() {
174 should_fail_to_convert_invalid_params(Value::from("s"), "a String")
175 }
176
177 #[test]
178 fn should_convert_params_from_an_array() {
179 let original_id = Value::from(1_i8);
180
181 let params = Params::try_from(&original_id, Value::Array(vec![])).unwrap();
182 assert!(matches!(params, Params::Array(v) if v.is_empty()));
183
184 let array = vec![Value::from(9_i16), Value::Bool(false)];
185 let params = Params::try_from(&original_id, Value::Array(array.clone())).unwrap();
186 assert!(matches!(params, Params::Array(v) if v == array));
187 }
188
189 #[test]
190 fn should_convert_params_from_an_object() {
191 let original_id = Value::from(1_i8);
192
193 let params = Params::try_from(&original_id, Value::Object(Map::new())).unwrap();
194 assert!(matches!(params, Params::Object(v) if v.is_empty()));
195
196 let mut map = Map::new();
197 map.insert("a".to_string(), Value::from(9_i16));
198 map.insert("b".to_string(), Value::Bool(false));
199 let params = Params::try_from(&original_id, Value::Object(map.clone())).unwrap();
200 assert!(matches!(params, Params::Object(v) if v == map));
201 }
202}