1 use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
2 use serde::ser::{Serialize, Serializer};
3 use std::collections::HashSet;
4 use std::fmt;
5 
6 #[derive(Debug, Clone, Eq, PartialEq)]
7 struct Names {
8     inner: HashSet<String>,
9 }
10 
11 impl Serialize for Names {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,12     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
13     where
14         S: Serializer,
15     {
16         let mut names: Vec<_> = self.inner.iter().collect();
17         names.sort();
18         names.serialize(serializer)
19     }
20 }
21 
22 impl<'de> Deserialize<'de> for Names {
deserialize<D>(deserializer: D) -> Result<Names, D::Error> where D: Deserializer<'de>,23     fn deserialize<D>(deserializer: D) -> Result<Names, D::Error>
24     where
25         D: Deserializer<'de>,
26     {
27         deserializer.deserialize_any(NamesVisitor)
28     }
29 }
30 
31 struct NamesVisitor;
32 
33 impl<'de> Visitor<'de> for NamesVisitor {
34     type Value = Names;
35 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result36     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
37         formatter.write_str("names or list of names")
38     }
39 
visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: serde::de::Error,40     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
41     where
42         E: serde::de::Error,
43     {
44         let mut out = HashSet::new();
45         out.insert(v.to_string());
46         Ok(Names { inner: out })
47     }
48 
visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> where A: SeqAccess<'de>,49     fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
50     where
51         A: SeqAccess<'de>,
52     {
53         let mut out: HashSet<String> = HashSet::new();
54 
55         // FIXME: Change `&str` to String to make the error go away
56         while let Some(s) = seq.next_element::<&str>()? {
57             out.insert(s.to_string());
58         }
59         Ok(Names { inner: out })
60     }
61 }
62 
63 #[test]
64 #[ignore]
65 /// This test is an almost exact replica of the "string or struct" example
66 /// in the [serde guide](https://serde.rs/string-or-struct.html)
67 ///
68 /// FIXME: it currently breaks. If you explicitly select `String` instead
69 /// of `&str` in the FIXME above, it works.
test_visitor()70 fn test_visitor() {
71     let single = r#"
72 ---
73 "foo"
74 "#;
75     let single_expected = Names {
76         inner: {
77             let mut i = HashSet::new();
78             i.insert("foo".into());
79             i
80         },
81     };
82     let multi = r#"
83 ---
84 - "foo"
85 - "bar"
86 "#;
87     let multi_expected = Names {
88         inner: {
89             let mut i = HashSet::new();
90             i.insert("foo".into());
91             i.insert("bar".into());
92             i
93         },
94     };
95 
96     let result: Names = serde_yaml::from_str(single).expect("didn't deserialize");
97     assert_eq!(result, single_expected);
98 
99     let result: Names = serde_yaml::from_str(multi).expect("didn't deserialize");
100     assert_eq!(result, multi_expected);
101 }
102