1use serde::de::{Error, SeqAccess, Visitor};
17use serde::ser::SerializeSeq;
18use serde::{Deserializer, Serializer};
19
20const PREFIX: &str = "INSPECT:";
21
22pub fn serialize<S>(
23 selectors: &Vec<fidl_fuchsia_diagnostics::Selector>,
24 serializer: S,
25) -> Result<S::Ok, S::Error>
26where
27 S: Serializer,
28{
29 let mut seq = serializer.serialize_seq(Some(selectors.len()))?;
30
31 for selector in selectors {
32 seq.serialize_element(&format!(
33 "{PREFIX}{}",
34 &selectors::selector_to_string(selector, selectors::SelectorDisplayOptions::default())
35 .map_err(serde::ser::Error::custom)?
36 ))?;
37 }
38
39 seq.end()
40}
41
42pub fn deserialize<'de, D>(
43 deserializer: D,
44) -> Result<Vec<fidl_fuchsia_diagnostics::Selector>, D::Error>
45where
46 D: Deserializer<'de>,
47{
48 deserializer.deserialize_seq(SelectorsVisitor)
49}
50
51struct SelectorsVisitor;
52
53impl<'de> Visitor<'de> for SelectorsVisitor {
54 type Value = Vec<fidl_fuchsia_diagnostics::Selector>;
55
56 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 write!(formatter, "should be a list of string selectors starting with {}", PREFIX)
58 }
59
60 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
61 where
62 A: SeqAccess<'de>,
63 {
64 let mut selectors = Vec::new();
65 while let Some(v) = seq.next_element::<String>()? {
66 if v.len() < PREFIX.len() || &v[..PREFIX.len()] != PREFIX {
67 return Err(A::Error::custom(format!(
68 "Expected selector with prefix \"{}\", got \"{v}\"",
69 PREFIX
70 )));
71 } else {
72 selectors.push(
73 selectors::parse_selector::<selectors::VerboseError>(&v[PREFIX.len()..])
74 .map_err(|e| A::Error::custom(e))?,
75 );
76 }
77 }
78 Ok(selectors)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use fidl_fuchsia_diagnostics::Selector;
86 use pretty_assertions::assert_eq;
87 use serde::{Deserialize, Serialize};
88 use test_case::test_case;
89
90 #[derive(Debug, Serialize, Deserialize, PartialEq)]
91 #[serde(transparent)]
92 struct TestConfig {
93 #[serde(with = "crate::inspect")]
94 selectors: Vec<Selector>,
95 }
96
97 #[test_case("a/b:c:d" ; "with_basic_full_selector")]
98 #[test_case("a/b:c" ; "with_basic_partial_selector")]
99 #[test_case(r"a/b:c/d\/e:f" ; "with_escaped_forward_slash")]
100 #[test_case(r"a/b:[name=cd-e]f:g" ; "with_non_default_name")]
101 #[test_case(r#"a:[name="bc-d"]e:f"# ; "with_unneeded_name_quotes")]
102 #[test_case(r#"a:[name="b[]c"]d:e"# ; "with_needed_name_quotes")]
103 #[test_case("a/b:[...]c:d" ; "with_all_names")]
104 #[test_case(r#"a/b:[name=c, name="d", name="f[]g"]h:i"# ; "with_name_list")]
105 #[test_case(r"a\:b/c:d:e" ; "with_collection")]
106 #[test_case(r"a/b/c*d:e:f" ; "with_wildcard_component")]
107 #[test_case(r"a/b:c*/d:e" ; "with_wildcard_tree")]
108 #[test_case(r"a/b:c\*/d:e" ; "with_escaped_wildcard_tree")]
109 #[test_case(r"a/b/c/d:e/f:g*" ; "with_wildcard_property")]
110 #[test_case("a/b/c/d:e/f/g/h:k" ; "with_deep_nesting")]
111 #[fuchsia::test]
112 fn test_serialization(selector: &str) {
113 let selector_escaped = serde_json::to_string(&format!("{PREFIX}{selector}")).unwrap();
115
116 let deserialized: TestConfig =
117 serde_json::from_str(&format!("[{selector_escaped}]")).unwrap();
118 let serialized = serde_json::to_string(&deserialized).unwrap();
119 let deserialized_again: TestConfig = serde_json::from_str(&serialized).unwrap();
120 assert_eq!(deserialized, deserialized_again);
121 assert_eq!(deserialized.selectors, vec![selectors::parse_verbose(selector).unwrap()]);
122 }
123}