1use serde::de::DeserializeOwned;
7use serde_json::Value;
8
9use crate::RuntimeError;
10
11pub fn deser_params<T: DeserializeOwned>(params: Value) -> Result<T, RuntimeError> {
17 serde_json::from_value(params)
18 .map_err(|e| RuntimeError::InvalidInput(format!("bad params: {e}")))
19}
20
21#[cfg(test)]
22mod tests {
23 use serde::Deserialize;
24 use serde_json::json;
25
26 use crate::{deser_params, RuntimeError};
27
28 #[derive(Debug, Deserialize, PartialEq)]
29 #[serde(deny_unknown_fields)]
30 struct Sample {
31 name: String,
32 #[serde(default)]
33 count: u32,
34 }
35
36 fn serde_message(params: &serde_json::Value) -> String {
38 serde_json::from_value::<Sample>(params.clone())
39 .expect_err("these params must not deserialize")
40 .to_string()
41 }
42
43 #[test]
44 fn missing_required_field_gives_bad_params_invalid_input() {
45 let params = json!({"count": 3});
46 let want = serde_message(¶ms);
47 assert!(want.contains("missing field `name`"), "{want}");
48
49 let err = deser_params::<Sample>(params).unwrap_err();
50 let RuntimeError::InvalidInput(message) = err else {
51 panic!("expected InvalidInput, got {err:?}");
52 };
53 assert!(message.starts_with("bad params: "), "{message}");
54 assert_eq!(message, format!("bad params: {want}"));
55 }
56
57 #[test]
58 fn unknown_field_under_deny_unknown_fields_gives_bad_params_invalid_input() {
59 let params = json!({"name": "alpha", "extra": true});
60 let want = serde_message(¶ms);
61 assert!(want.contains("unknown field `extra`"), "{want}");
62
63 let err = deser_params::<Sample>(params).unwrap_err();
64 let RuntimeError::InvalidInput(message) = err else {
65 panic!("expected InvalidInput, got {err:?}");
66 };
67 assert!(message.starts_with("bad params: "), "{message}");
68 assert_eq!(message, format!("bad params: {want}"));
69 }
70
71 #[test]
72 fn valid_params_deserialize_into_the_requested_type() {
73 let params = json!({"name": "alpha", "count": 3});
74 let parsed: Sample = deser_params(params).unwrap();
75 let expected = Sample {
76 name: "alpha".to_string(),
77 count: 3,
78 };
79 assert_eq!(parsed, expected);
80
81 let params = json!({"name": "beta"});
82 let defaulted: Sample = deser_params(params).unwrap();
83 let expected_default = Sample {
84 name: "beta".to_string(),
85 count: 0,
86 };
87 assert_eq!(defaulted, expected_default);
88 }
89}