1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::collections::{hash_map::Keys, HashMap};
use std::fmt;
use std::sync::Arc;
use serde::{de::MapAccess, de::Visitor, Deserialize, Deserializer};
#[derive(Default, Debug, PartialEq)]
pub struct StrMap(pub(crate) Arc<HashMap<String, String>>);
impl StrMap {
pub fn get(&self, key: &str) -> Option<&str> {
self.0.get(key).map(|value| value.as_ref())
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter(&self) -> StrMapIter {
StrMapIter {
data: self,
keys: self.0.keys(),
}
}
}
impl Clone for StrMap {
fn clone(&self) -> Self {
StrMap(self.0.clone())
}
}
impl From<HashMap<String, String>> for StrMap {
fn from(inner: HashMap<String, String>) -> Self {
StrMap(Arc::new(inner))
}
}
pub struct StrMapIter<'a> {
data: &'a StrMap,
keys: Keys<'a, String, String>,
}
impl<'a> Iterator for StrMapIter<'a> {
type Item = (&'a str, &'a str);
#[inline]
fn next(&mut self) -> Option<(&'a str, &'a str)> {
self.keys
.next()
.and_then(|k| self.data.get(k).map(|v| (k.as_str(), v)))
}
}
impl<'de> Deserialize<'de> for StrMap {
fn deserialize<D>(deserializer: D) -> Result<StrMap, D::Error>
where
D: Deserializer<'de>,
{
struct StrMapVisitor;
impl<'de> Visitor<'de> for StrMapVisitor {
type Value = StrMap;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a StrMap")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut inner = HashMap::new();
while let Some((key, value)) = map.next_entry()? {
inner.insert(key, value);
}
Ok(StrMap(Arc::new(inner)))
}
}
deserializer.deserialize_map(StrMapVisitor)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[test]
fn str_map_default_is_empty() {
assert!(StrMap::default().is_empty())
}
#[test]
fn str_map_get() {
let mut data = HashMap::new();
data.insert("foo".into(), "bar".into());
let strmap = StrMap(data.into());
assert_eq!(strmap.get("foo"), Some("bar"));
assert_eq!(strmap.get("bar"), None);
}
#[test]
fn str_map_iter() {
let mut data = HashMap::new();
data.insert("foo".into(), "bar".into());
data.insert("baz".into(), "boom".into());
let strmap = StrMap(data.into());
let mut values = strmap.iter().map(|(_, v)| v).collect::<Vec<_>>();
values.sort();
assert_eq!(values, vec!["bar", "boom"]);
}
}