keyring_core/
attributes.rs1use std::collections::HashMap;
7
8use crate::{Error::Invalid, Result};
9
10pub fn parse_attributes(
21 keys: &[&str],
22 attrs: Option<&HashMap<&str, &str>>,
23) -> Result<HashMap<String, String>> {
24 let mut result: HashMap<String, String> = HashMap::new();
25 if attrs.is_none() {
26 return Ok(result);
27 }
28 let key_map: HashMap<String, char> = keys
29 .iter()
30 .map(|k| {
31 if k.starts_with("*") {
32 (k.split_at(1).1.to_string(), '*')
33 } else if k.starts_with("+") {
34 (k.split_at(1).1.to_string(), '+')
35 } else {
36 (k.to_string(), ' ')
37 }
38 })
39 .collect();
40 for (key, value) in attrs.unwrap() {
41 if let Some(prefix) = key_map.get(*key) {
42 match *prefix {
43 '*' if *value != "true" && *value != "false" => {
44 let msg = "must be 'true' or 'false'";
45 return Err(Invalid(key.to_string(), msg.to_string()));
46 }
47 '+' if value.is_empty() => {
48 let msg = "must not be empty";
49 return Err(Invalid(key.to_string(), msg.to_string()));
50 }
51 _ => {}
52 }
53 result.insert(key.to_string(), value.to_string());
54 } else {
55 return Err(Invalid(key.to_string(), "unknown key".to_string()));
56 }
57 }
58 Ok(result)
59}
60
61pub fn externalize_attributes(attrs: &HashMap<&str, &str>) -> HashMap<String, String> {
63 attrs
64 .iter()
65 .map(|(k, v)| (k.to_string(), v.to_string()))
66 .collect()
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_parse_attributes() {
75 let attrs = HashMap::from([("key1", "value1"), ("key2", "true"), ("key3", "false")]);
76 assert_eq!(parse_attributes(&["key1"], None).unwrap().len(), 0);
77 assert_eq!(
78 parse_attributes(&["key1", "key2", "key3"], Some(&attrs))
79 .unwrap()
80 .len(),
81 3
82 );
83 let parsed = parse_attributes(&["+key1", "*key2", "*key3"], Some(&attrs)).unwrap();
84 assert_eq!(parsed.len(), 3);
85 assert_eq!(parsed.get("key1"), Some(&"value1".to_string()));
86 assert_eq!(parsed.get("key2"), Some(&"true".to_string()));
87 assert_eq!(parsed.get("key3"), Some(&"false".to_string()));
88 let bad_attrs = HashMap::from([("key1", "t")]);
89 match parse_attributes(&["*key1"], Some(&bad_attrs)) {
90 Err(Invalid(key, msg)) => {
91 assert_eq!(key, "key1");
92 assert_eq!(msg, "must be 'true' or 'false'");
93 }
94 _ => panic!("Incorrect error for invalid boolean attribute"),
95 }
96 let bad_attrs = HashMap::from([("key1", "")]);
97 match parse_attributes(&["+key1"], Some(&bad_attrs)) {
98 Err(Invalid(key, msg)) => {
99 assert_eq!(key, "key1");
100 assert_eq!(msg, "must not be empty");
101 }
102 _ => panic!("Incorrect error for empty string attribute"),
103 }
104 match parse_attributes(&["other_key"], Some(&bad_attrs)) {
105 Err(Invalid(key, msg)) => {
106 assert_eq!(key, "key1");
107 assert_eq!(msg, "unknown key");
108 }
109 _ => panic!("Incorrect error for unknown attribute"),
110 }
111 }
112
113 #[test]
114 fn test_externalize_attributes() {
115 let attrs = HashMap::from([("key1", "value1"), ("key2", "true"), ("key3", "false")]);
116 let externalized = externalize_attributes(&attrs);
117 assert_eq!(externalized.len(), 3);
118 assert_eq!(externalized.get("key1"), Some(&"value1".to_string()));
119 assert_eq!(externalized.get("key2"), Some(&"true".to_string()));
120 assert_eq!(externalized.get("key3"), Some(&"false".to_string()));
121 }
122}