oasiscap/map.rs
1//! A container type for CAP >=1.1 key value maps.
2
3use serde::ser::SerializeSeq;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6/// An order-preserving `String` => `String` key/value map which supports duplicate entries.
7///
8/// `Map` is parameterized by its element type, since different CAP standards use different
9/// kinds of elements which must be serialized/deserialized differently.
10///
11/// `Map<E: MapEntry>` implements `FromIterator` for key-value `(String, String)` or `(&str, &str)`
12/// tuples:
13///
14/// ```
15/// let map: oasiscap::v1dot1::Map = [
16/// ("foo", "bar"),
17/// ("foo", "baz"),
18/// ("quxx", "flummox"),
19/// ].into_iter().collect();
20/// ```
21///
22/// `&Map<E: MapEntry>` implements `IntoIterator` for easy iteration:
23///
24/// ```
25/// # let map: oasiscap::v1dot1::Map = [
26/// # ("foo", "bar"),
27/// # ("foo", "baz"),
28/// # ("quxx", "flummox"),
29/// # ].into_iter().collect();
30/// for (key, value) in &map {
31/// println!("{:?} = {:?}", key, value);
32/// }
33/// ```
34///
35/// `Map<E: MapEntry>` implements `IntoIterator<Item=(String, String)>`, which allows easy
36/// conversion from `Map` to other kinds of containers:
37///
38/// ```
39/// # let map: oasiscap::v1dot1::Map = [
40/// # ("foo", "bar"),
41/// # ("foo", "baz"),
42/// # ("quxx", "flummox"),
43/// # ].into_iter().collect();
44/// // Just note that Map is duplicate-preserving:
45/// assert_eq!(map.get("foo"), Some("bar"));
46/// assert_eq!(map.get_all("foo").collect::<Vec<_>>(), vec!["bar", "baz"]);
47///
48/// // ...while most other containers are not:
49/// let btree_map: std::collections::BTreeMap<String, String> = map.into_iter().collect();
50/// assert_eq!(btree_map.get("foo"), Some(&"baz".into()));
51/// ```
52///
53#[derive(Debug, Clone, Eq, PartialEq)]
54pub struct Map<E>(Vec<E>);
55
56/// The behaviors needed for a map entry.
57pub trait Entry: From<(String, String)> + Into<(String, String)> {
58 /// The value name (i.e. key) of this entry.
59 fn value_name(&self) -> &str;
60
61 /// The value of this entry.
62 fn value(&self) -> &str;
63
64 /// Set the value of this entry, returning the old value.
65 fn set_value(&mut self, new_value: String) -> String;
66}
67
68impl<E: Entry> Map<E> {
69 /// Instantiate an empty map.
70 ///
71 /// # Example
72 ///
73 /// ```
74 /// let map = oasiscap::v1dot1::Map::new();
75 /// ```
76 pub fn new() -> Self {
77 Self(Vec::new())
78 }
79
80 /// Get the first value for this key, if any.
81 ///
82 /// # Example
83 ///
84 /// ```
85 /// let map: oasiscap::v1dot1::Map = [
86 /// ("foo", "bar"),
87 /// ("foo", "baz"),
88 /// ("quxx", "flummox"),
89 /// ].into_iter().collect();
90 ///
91 /// assert_eq!(map.get("foo"), Some("bar"));
92 /// ```
93 pub fn get<S: AsRef<str>>(&self, value_name: S) -> Option<&str> {
94 let value_name = value_name.as_ref();
95 self.0
96 .iter()
97 .find(|e| e.value_name() == value_name)
98 .map(|e| e.value())
99 }
100
101 /// Iterate over all the values for a given key.
102 ///
103 /// # Example
104 ///
105 /// ```
106 /// let map: oasiscap::v1dot1::Map = [
107 /// ("foo", "bar"),
108 /// ("foo", "baz"),
109 /// ("quxx", "flummox"),
110 /// ].into_iter().collect();
111 ///
112 /// assert_eq!(map.get_all("foo").collect::<Vec<&str>>(), vec!["bar", "baz"]);
113 /// ```
114 pub fn get_all<S: AsRef<str>>(&self, value_name: S) -> impl Iterator<Item = &str> {
115 self.0.iter().filter_map(move |e| {
116 if e.value_name() == value_name.as_ref() {
117 Some(e.value())
118 } else {
119 None
120 }
121 })
122 }
123
124 /// Push a new key-value entry onto an existing map.
125 ///
126 /// # Example
127 ///
128 /// ```
129 /// let mut map: oasiscap::v1dot1::Map = [
130 /// ("foo", "bar"),
131 /// ("foo", "baz"),
132 /// ("quxx", "flummox"),
133 /// ].into_iter().collect();
134 ///
135 /// map.push("foo", "waldo");
136 ///
137 /// assert_eq!(map.get_all("foo").collect::<Vec<&str>>(), vec!["bar", "baz", "waldo"]);
138 /// ```
139 pub fn push<K: Into<String>, V: Into<String>>(&mut self, value_name: K, value: V) {
140 self.0.push(E::from((value_name.into(), value.into())));
141 }
142
143 /// Returns the number of entries in the map.
144 pub fn len(&self) -> usize {
145 self.0.len()
146 }
147
148 /// Returns `true` if the map contains no entries.
149 pub fn is_empty(&self) -> bool {
150 self.0.is_empty()
151 }
152
153 /// Returns an iterator over the map.
154 #[must_use]
155 pub fn iter(&self) -> Iter<E> {
156 Iter(self.0.iter())
157 }
158}
159
160impl<E> Default for Map<E> {
161 fn default() -> Self {
162 Self(Vec::new())
163 }
164}
165
166impl<E: Entry + Serialize> Serialize for Map<E> {
167 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
168 where
169 S: Serializer,
170 {
171 let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
172 for entry in &self.0 {
173 seq.serialize_element(entry)?;
174 }
175 seq.end()
176 }
177}
178
179impl<'de, E: Entry + Deserialize<'de>> Deserialize<'de> for Map<E> {
180 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
181 where
182 D: Deserializer<'de>,
183 {
184 let entries = <Vec<E>>::deserialize(deserializer)?;
185 Ok(Self(entries))
186 }
187}
188
189impl<'a, E: Entry> FromIterator<(&'a str, &'a str)> for Map<E> {
190 fn from_iter<T: IntoIterator<Item = (&'a str, &'a str)>>(iter: T) -> Self {
191 Self(
192 iter.into_iter()
193 .map(|(value_name, value)| E::from((value_name.into(), value.into())))
194 .collect(),
195 )
196 }
197}
198
199impl<E: Entry> FromIterator<(String, String)> for Map<E> {
200 fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
201 Self(
202 iter.into_iter()
203 .map(|(value_name, value)| E::from((value_name, value)))
204 .collect(),
205 )
206 }
207}
208
209impl<E> FromIterator<E> for Map<E> {
210 fn from_iter<T: IntoIterator<Item = E>>(iter: T) -> Self {
211 Self(iter.into_iter().collect())
212 }
213}
214
215impl<'a, E: Entry> IntoIterator for &'a Map<E> {
216 type Item = (&'a str, &'a str);
217 type IntoIter = Iter<'a, E>;
218
219 fn into_iter(self) -> Self::IntoIter {
220 self.iter()
221 }
222}
223
224impl<E: Entry> IntoIterator for Map<E> {
225 type Item = (String, String);
226 type IntoIter = IntoIter<E>;
227
228 fn into_iter(self) -> Self::IntoIter {
229 IntoIter(self.0.into_iter())
230 }
231}
232
233/// An iterator over a map.
234#[derive(Debug)]
235pub struct Iter<'a, E>(std::slice::Iter<'a, E>);
236
237impl<'a, E: Entry> Iterator for Iter<'a, E> {
238 type Item = (&'a str, &'a str);
239
240 fn next(&mut self) -> Option<Self::Item> {
241 self.0.next().map(|e| (e.value_name(), e.value()))
242 }
243
244 fn size_hint(&self) -> (usize, Option<usize>) {
245 self.0.size_hint()
246 }
247}
248
249impl<'a, E: Entry> ExactSizeIterator for Iter<'a, E> {}
250
251/// An iterator that moves out of a map.
252#[derive(Debug)]
253pub struct IntoIter<E>(std::vec::IntoIter<E>);
254
255impl<E: Entry> Iterator for IntoIter<E> {
256 type Item = (String, String);
257
258 fn next(&mut self) -> Option<Self::Item> {
259 self.0.next().map(|e| e.into())
260 }
261
262 fn size_hint(&self) -> (usize, Option<usize>) {
263 self.0.size_hint()
264 }
265}
266
267impl<E: Entry> ExactSizeIterator for IntoIter<E> {}
268
269impl<E: Entry> From<crate::v1dot0::Map> for Map<E> {
270 fn from(prev: crate::v1dot0::Map) -> Self {
271 prev.into_iter()
272 .map(|(key, value)| (key.into(), value))
273 .collect()
274 }
275}