1use fidl_fuchsia_driver_metadata as fmetadata;
6use std::collections::BTreeMap;
7
8#[derive(Debug, thiserror::Error)]
10pub enum Error {
11 #[error("Missing key in dictionary entry")]
12 MissingKey,
13 #[error("Missing value in dictionary entry")]
14 MissingValue,
15 #[error("Custom error: {0}")]
16 Custom(String),
17}
18
19impl serde::de::Error for Error {
20 fn custom<T: std::fmt::Display>(msg: T) -> Self {
21 Error::Custom(msg.to_string())
22 }
23}
24
25pub fn from_dictionary<T>(dict: fmetadata::Dictionary) -> Result<T, Error>
27where
28 T: serde::de::DeserializeOwned,
29{
30 let mut entries = BTreeMap::new();
31 if let Some(e) = dict.entries {
32 for entry in e {
33 entries.insert(entry.key, entry.value);
34 }
35 }
36 let deserializer = DictionaryDeserializer { entries: &entries, prefix: "".to_string() };
37 let result = T::deserialize(deserializer)?;
38 Ok(result)
39}
40
41fn bytes_from_seq<'de, A>(mut seq: A) -> Result<Vec<u8>, A::Error>
42where
43 A: serde::de::SeqAccess<'de>,
44{
45 let mut bytes = Vec::new();
46 while let Some(val) = seq.next_element::<i64>()? {
47 let b = (val as u32).to_be_bytes();
48 bytes.extend_from_slice(&b);
49 }
50 Ok(bytes)
51}
52
53#[derive(Debug, PartialEq, Clone)]
56pub struct StringVec(pub Vec<String>);
57
58impl<'de> serde::Deserialize<'de> for StringVec {
59 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60 where
61 D: serde::Deserializer<'de>,
62 {
63 struct Visitor;
64 impl<'de> serde::de::Visitor<'de> for Visitor {
65 type Value = Vec<String>;
66 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 formatter.write_str("a sequence of integers representing concatenated strings")
68 }
69 fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
70 where
71 A: serde::de::SeqAccess<'de>,
72 {
73 let bytes = bytes_from_seq(seq)?;
74 let strings = bytes
75 .split(|&b| b == 0)
76 .filter(|s| !s.is_empty())
77 .map(|s| String::from_utf8_lossy(s).to_string())
78 .collect();
79 Ok(strings)
80 }
81 }
82 Ok(StringVec(deserializer.deserialize_seq(Visitor)?))
83 }
84}
85
86impl std::ops::Deref for StringVec {
87 type Target = Vec<String>;
88 fn deref(&self) -> &Self::Target {
89 &self.0
90 }
91}
92
93struct DictionaryDeserializer<'a> {
94 entries: &'a BTreeMap<String, fmetadata::DictionaryValue>,
95 prefix: String,
96}
97
98impl<'de, 'a> serde::Deserializer<'de> for DictionaryDeserializer<'a> {
99 type Error = Error;
100
101 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
102 where
103 V: serde::de::Visitor<'de>,
104 {
105 if let Some(val) = self.entries.get(&self.prefix) {
106 match val {
107 fmetadata::DictionaryValue::Int64(i) => visitor.visit_i64(*i),
108 fmetadata::DictionaryValue::Int64Vec(v) => {
109 visitor.visit_seq(SeqDeserializer { vec: v.clone(), index: 0 })
110 }
111 _ => Err(Error::Custom("Unsupported value type".to_string())),
112 }
113 } else {
114 visitor.visit_map(MapDeserializer::new(self.entries, &self.prefix))
115 }
116 }
117
118 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
119 where
120 V: serde::de::Visitor<'de>,
121 {
122 if let Some(val) = self.entries.get(&self.prefix) {
123 if let fmetadata::DictionaryValue::Int64Vec(v) = val {
124 let mut bytes = Vec::new();
125 for val in v {
126 let b = (*val as u32).to_be_bytes();
127 bytes.extend_from_slice(&b);
128 }
129 if let Some(null_pos) = bytes.iter().position(|&b| b == 0) {
130 bytes.truncate(null_pos);
131 }
132 let s = String::from_utf8_lossy(&bytes).to_string();
133 return visitor.visit_string(s);
134 }
135 }
136 self.deserialize_any(visitor)
137 }
138
139 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
140 where
141 V: serde::de::Visitor<'de>,
142 {
143 self.deserialize_string(visitor)
144 }
145
146 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
147 where
148 V: serde::de::Visitor<'de>,
149 {
150 if let Some(val) = self.entries.get(&self.prefix) {
151 if let fmetadata::DictionaryValue::Int64Vec(v) = val {
152 if v.is_empty() {
153 return visitor.visit_bool(true);
154 }
155 }
156 }
157 self.deserialize_any(visitor)
158 }
159
160 serde::forward_to_deserialize_any! {
161 i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char
162 bytes byte_buf option unit unit_struct newtype_struct seq tuple
163 tuple_struct map struct enum identifier ignored_any
164 }
165}
166
167struct MapDeserializer<'a> {
168 entries: &'a BTreeMap<String, fmetadata::DictionaryValue>,
169 prefix: String,
170 keys: Vec<String>,
171 current_index: usize,
172}
173
174impl<'a> MapDeserializer<'a> {
175 fn new(entries: &'a BTreeMap<String, fmetadata::DictionaryValue>, prefix: &str) -> Self {
176 let mut keys = std::collections::HashSet::new();
177 let prefix_with_dot =
178 if prefix.is_empty() { "".to_string() } else { format!("{}.", prefix) };
179
180 for k in entries.keys() {
181 if k.starts_with(&prefix_with_dot) || prefix.is_empty() {
182 let stripped =
183 if prefix.is_empty() { k.as_str() } else { &k[prefix_with_dot.len()..] };
184 let child_key = match stripped.find('.') {
185 Some(idx) => &stripped[..idx],
186 None => stripped,
187 };
188 keys.insert(child_key.to_string());
189 }
190 }
191 let mut keys_vec: Vec<String> = keys.into_iter().collect();
192 keys_vec.sort();
193 Self { entries, prefix: prefix.to_string(), keys: keys_vec, current_index: 0 }
194 }
195}
196
197impl<'de, 'a> serde::de::MapAccess<'de> for MapDeserializer<'a> {
198 type Error = Error;
199
200 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
201 where
202 K: serde::de::DeserializeSeed<'de>,
203 {
204 if self.current_index >= self.keys.len() {
205 return Ok(None);
206 }
207 let key = &self.keys[self.current_index];
208 seed.deserialize(KeyDeserializer { key: key.clone() }).map(Some)
209 }
210
211 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
212 where
213 V: serde::de::DeserializeSeed<'de>,
214 {
215 let key = &self.keys[self.current_index];
216 self.current_index += 1;
217
218 let new_prefix =
219 if self.prefix.is_empty() { key.clone() } else { format!("{}.{}", self.prefix, key) };
220
221 seed.deserialize(DictionaryDeserializer { entries: self.entries, prefix: new_prefix })
222 }
223}
224
225struct KeyDeserializer {
226 key: String,
227}
228
229impl<'de> serde::Deserializer<'de> for KeyDeserializer {
230 type Error = Error;
231
232 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
233 where
234 V: serde::de::Visitor<'de>,
235 {
236 visitor.visit_string(self.key)
237 }
238
239 serde::forward_to_deserialize_any! {
240 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
241 bytes byte_buf option unit unit_struct newtype_struct seq tuple
242 tuple_struct map struct enum identifier ignored_any
243 }
244}
245
246struct SeqDeserializer {
247 vec: Vec<i64>,
248 index: usize,
249}
250
251impl<'de> serde::de::SeqAccess<'de> for SeqDeserializer {
252 type Error = Error;
253
254 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
255 where
256 T: serde::de::DeserializeSeed<'de>,
257 {
258 if self.index >= self.vec.len() {
259 return Ok(None);
260 }
261 let val = self.vec[self.index];
262 self.index += 1;
263 seed.deserialize(I64Deserializer { val }).map(Some)
264 }
265}
266
267struct I64Deserializer {
268 val: i64,
269}
270
271impl<'de> serde::Deserializer<'de> for I64Deserializer {
272 type Error = Error;
273
274 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
275 where
276 V: serde::de::Visitor<'de>,
277 {
278 visitor.visit_i64(self.val)
279 }
280
281 serde::forward_to_deserialize_any! {
282 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
283 bytes byte_buf option unit unit_struct newtype_struct seq tuple
284 tuple_struct map struct enum identifier ignored_any
285 }
286}
287
288#[cfg(test)]
289mod tests {
290 use super::*;
291 use serde::Deserialize;
292
293 #[derive(Deserialize, Debug, PartialEq)]
294 struct MyConfig {
295 test_str: String,
296 test_int: i64,
297 test_vec: StringVec,
298 nested: NestedConfig,
299 }
300
301 #[derive(Deserialize, Debug, PartialEq)]
302 struct NestedConfig {
303 inner_val: String,
304 }
305
306 #[test]
307 fn test_deserialization() {
308 let mut entries = Vec::new();
309
310 let str_val1 = i64::from(u32::from_be_bytes([104, 101, 108, 108]));
312 let str_val2 = i64::from(u32::from_be_bytes([111, 0, 0, 0]));
313
314 entries.push(fmetadata::DictionaryEntry {
315 key: "test_str".to_string(),
316 value: fmetadata::DictionaryValue::Int64Vec(vec![str_val1, str_val2]),
317 });
318 entries.push(fmetadata::DictionaryEntry {
319 key: "test_int".to_string(),
320 value: fmetadata::DictionaryValue::Int64(42),
321 });
322
323 let vec_val = i64::from(u32::from_be_bytes([97, 0, 98, 0]));
325 entries.push(fmetadata::DictionaryEntry {
326 key: "test_vec".to_string(),
327 value: fmetadata::DictionaryValue::Int64Vec(vec![vec_val]),
328 });
329
330 let sec_val1 = i64::from(u32::from_be_bytes([115, 101, 99, 114]));
332 let sec_val2 = i64::from(u32::from_be_bytes([101, 116, 0, 0]));
333
334 entries.push(fmetadata::DictionaryEntry {
335 key: "nested.inner_val".to_string(),
336 value: fmetadata::DictionaryValue::Int64Vec(vec![sec_val1, sec_val2]),
337 });
338
339 let dict = fmetadata::Dictionary { entries: Some(entries), ..Default::default() };
340
341 let config: MyConfig = from_dictionary(dict).unwrap();
342 assert_eq!(
343 config,
344 MyConfig {
345 test_str: "hello".to_string(),
346 test_int: 42,
347 test_vec: StringVec(vec!["a".to_string(), "b".to_string()]),
348 nested: NestedConfig { inner_val: "secret".to_string() },
349 }
350 );
351 }
352
353 #[derive(Deserialize, Debug, PartialEq)]
354 struct BoolConfig {
355 test_bool: bool,
356 }
357
358 #[test]
359 fn test_bool_deserialization() {
360 let mut entries = Vec::new();
361 entries.push(fmetadata::DictionaryEntry {
362 key: "test_bool".to_string(),
363 value: fmetadata::DictionaryValue::Int64Vec(vec![]),
364 });
365
366 let dict = fmetadata::Dictionary { entries: Some(entries), ..Default::default() };
367
368 let config: BoolConfig = from_dictionary(dict).unwrap();
369 assert_eq!(config, BoolConfig { test_bool: true });
370 }
371}