grafbase_sdk/types/
configuration.rs1use serde::Deserialize;
2
3use crate::SdkError;
4
5pub struct Configuration(Vec<u8>);
7
8impl Configuration {
9 pub(crate) fn new(config: Vec<u8>) -> Self {
11 Self(config)
12 }
13
14 pub fn deserialize<'de, T>(&'de self) -> Result<T, SdkError>
20 where
21 T: Deserialize<'de>,
22 {
23 let mut deserializer = minicbor_serde::Deserializer::new(&self.0);
24 serde_path_to_error::deserialize(&mut deserializer).map_err(|err| {
25 if err.path().iter().len() == 0
26 || err
27 .path()
28 .iter()
29 .all(|seg| matches!(seg, serde_path_to_error::Segment::Unknown))
30 {
31 let inner_err = err.into_inner();
32 format!("Failed to deserialize configuration: {inner_err}").into()
33 } else {
34 format!("Failed to deserialize configuration at {err}").into()
35 }
36 })
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use serde::{Deserialize, Serialize};
44
45 #[derive(Debug, Serialize, Deserialize)]
46 struct TestConfig<S> {
47 name: String,
48 settings: S,
49 }
50
51 #[derive(Debug, Serialize, Deserialize)]
52 struct Settings {
53 enabled: bool,
54 count: u32,
55 }
56
57 #[derive(Debug, Serialize, Deserialize)]
58 struct InvalidSettings {
59 enabled: String,
60 count: u32,
61 }
62
63 #[test]
64 fn test_deserialize() {
65 let config_bytes = crate::cbor::to_vec(TestConfig {
67 name: "test".to_string(),
68 settings: Settings {
69 enabled: true,
70 count: 42,
71 },
72 })
73 .unwrap();
74 let configuration = Configuration::new(config_bytes);
75 let result: TestConfig<Settings> = configuration.deserialize().unwrap();
76 assert_eq!(result.name, "test");
77 assert!(result.settings.enabled);
78 assert_eq!(result.settings.count, 42);
79
80 let invalid_bytes = crate::cbor::to_vec(&TestConfig {
82 name: "test".to_string(),
83 settings: InvalidSettings {
84 enabled: "not_a_bool".to_string(),
85 count: 42,
86 },
87 })
88 .unwrap();
89 let invalid_configuration = Configuration::new(invalid_bytes);
90 let err = invalid_configuration.deserialize::<TestConfig<Settings>>().unwrap_err();
91
92 insta::assert_snapshot!(err, @"Failed to deserialize configuration at settings.enabled: unexpected type string at position 29: expected bool");
93
94 let invalid_bytes = crate::cbor::to_vec(serde_json::Value::Null).unwrap();
96 let invalid_configuration = Configuration::new(invalid_bytes);
97 let err = invalid_configuration.deserialize::<TestConfig<Settings>>().unwrap_err();
98
99 insta::assert_snapshot!(err, @"Failed to deserialize configuration: unexpected type null at position 0: expected map");
100 }
101}