rskit_config/strict/
raw.rs1use std::collections::BTreeMap;
2
3use rskit_errors::{AppError, AppResult};
4use serde::de::DeserializeOwned;
5
6pub type RawValue = serde_json::Value;
11
12pub type RawTable = BTreeMap<String, RawValue>;
19
20pub fn deserialize_subtree<T>(field: &str, value: RawValue) -> AppResult<T>
25where
26 T: DeserializeOwned,
27{
28 T::deserialize(value).map_err(|error| {
29 AppError::invalid_input(field, format!("invalid '{field}' configuration: {error}"))
30 })
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36 use serde::Deserialize;
37
38 #[derive(Debug, Deserialize, PartialEq, Eq)]
39 #[serde(deny_unknown_fields)]
40 struct Sub {
41 enabled: bool,
42 retries: u16,
43 }
44
45 #[test]
46 fn deserialize_subtree_parses_typed_value() {
47 let value: RawValue = serde_json::json!({ "enabled": true, "retries": 3 });
48
49 let sub: Sub = deserialize_subtree("driver", value).unwrap();
50
51 assert_eq!(
52 sub,
53 Sub {
54 enabled: true,
55 retries: 3
56 }
57 );
58 }
59
60 #[test]
61 fn deserialize_subtree_rejects_unknown_field_with_named_error() {
62 let value: RawValue = serde_json::json!({ "enabled": true, "retries": 3, "extra": 1 });
63
64 let err = deserialize_subtree::<Sub>("driver", value).unwrap_err();
65
66 assert!(err.to_string().contains("driver"));
67 assert!(err.to_string().contains("unknown field"));
68 }
69}