rocketmq_common/common/attribute/
attribute_parser.rs1use std::collections::HashMap;
18use std::string::ToString;
19
20const ATTR_ARRAY_SEPARATOR_COMMA: &str = ",";
21const ATTR_KEY_VALUE_EQUAL_SIGN: &str = "=";
22const ATTR_ADD_PLUS_SIGN: &str = "+";
23const ATTR_DELETE_MINUS_SIGN: &str = "-";
24
25#[derive(Debug)]
26pub struct AttributeParser;
27
28impl AttributeParser {
29 pub fn parse_to_map(attributes_modification: &str) -> Result<HashMap<String, String>, String> {
30 if attributes_modification.is_empty() {
31 return Ok(HashMap::new());
32 }
33
34 let mut attributes = HashMap::new();
35 let kvs: Vec<&str> = attributes_modification
36 .split(ATTR_ARRAY_SEPARATOR_COMMA)
37 .collect();
38 for kv in kvs {
39 let mut key = String::new();
40 let mut value = String::new();
41 if kv.contains(ATTR_KEY_VALUE_EQUAL_SIGN) {
42 let splits: Vec<&str> = kv.split(ATTR_KEY_VALUE_EQUAL_SIGN).collect();
43 key.push_str(splits[0]);
44 value.push_str(splits[1]);
45 if !key.contains(ATTR_ADD_PLUS_SIGN) {
46 return Err(format!("add/alter attribute format is wrong: {key}"));
47 }
48 } else {
49 key.push_str(kv);
50 if !key.contains(ATTR_DELETE_MINUS_SIGN) {
51 return Err(format!("delete attribute format is wrong: {key}",));
52 }
53 }
54 if attributes.insert(key.clone(), value).is_some() {
55 return Err(format!("key duplication: {key}",));
56 }
57 }
58 Ok(attributes)
59 }
60
61 pub fn parse_to_string(attributes: &HashMap<String, String>) -> String {
62 if attributes.is_empty() {
63 return String::new();
64 }
65
66 let mut kvs: Vec<String> = Vec::new();
67 for (key, value) in attributes {
68 if value.is_empty() {
69 kvs.push(key.clone());
70 } else {
71 kvs.push(format!("{key}{ATTR_KEY_VALUE_EQUAL_SIGN}{value}"));
72 }
73 }
74 kvs.join(ATTR_ARRAY_SEPARATOR_COMMA)
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_parse_to_map_empty_string() {
84 let result = AttributeParser::parse_to_map("");
85 assert_eq!(result.unwrap(), HashMap::new());
86 }
87
88 #[test]
89 fn test_parse_to_map_valid_attributes() {
90 let input = "+key1=value1,+key2=value2,-key3";
91 let mut expected = HashMap::new();
92 expected.insert("+key1".to_string(), "value1".to_string());
93 expected.insert("+key2".to_string(), "value2".to_string());
94 expected.insert("-key3".to_string(), "".to_string());
95
96 let result = AttributeParser::parse_to_map(input);
97 assert_eq!(result.unwrap(), expected);
98 }
99
100 #[test]
101 fn test_parse_to_map_add_attribute_format_error() {
102 let input = "key1=value1,+key2=value2";
103 let result = AttributeParser::parse_to_map(input);
104 assert_eq!(
105 result.unwrap_err(),
106 "add/alter attribute format is wrong: key1".to_string()
107 );
108 }
109
110 #[test]
111 fn test_parse_to_map_delete_attribute_format_error() {
112 let input = "+key1=value1,key2";
113 let result = AttributeParser::parse_to_map(input);
114 assert_eq!(
115 result.unwrap_err(),
116 "delete attribute format is wrong: key2".to_string()
117 );
118 }
119
120 #[test]
121 fn test_parse_to_map_key_duplication_error() {
122 let input = "+key1=value1,+key1=value2";
123 let result = AttributeParser::parse_to_map(input);
124 assert_eq!(result.unwrap_err(), "key duplication: +key1".to_string());
125 }
126
127 #[test]
128 fn test_parse_to_string_empty_map() {
129 let attributes = HashMap::new();
130 let result = AttributeParser::parse_to_string(&attributes);
131 assert_eq!(result, "");
132 }
133
134 }