1use std::collections::HashMap;
2
3pub const QUERY_START_WITH: &str = "?";
18pub const QUERY_SEP: &str = "&";
19pub const QUERY_VALUE_SEP: &str = "=";
20
21#[derive(Default, Debug)]
22pub struct QueryData(HashMap<String, String>);
23
24impl QueryData {
25 pub fn get(&self, key: &str) -> Option<&String> {
26 self.0.get(key)
27 }
28 pub fn set(&mut self, key: &str, value: &str) {
29 self.0.insert(key.to_string(), value.to_string());
30 }
31 pub fn len(&self) -> usize {
32 self.0.len()
33 }
34}
35
36impl From<&str> for QueryData {
37 fn from(value: &str) -> Self {
38 value.split(QUERY_SEP).filter(|item| !item.is_empty()).fold(
39 QueryData::default(),
40 |mut query_data, item| {
41 let (key, value) = item.split_once(QUERY_VALUE_SEP).unwrap_or((&item, &""));
42
43 query_data.set(key, value);
44
45 query_data
46 },
47 )
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn test_from_query_data() {
57 let query_one = QueryData::from("type=admin");
58
59 assert!(query_one
60 .get("type")
61 .and_then(|i| Some(i == "admin"))
62 .is_some());
63
64 let query_two = QueryData::from("a=1&b=2");
65
66 assert!(query_two.get("a").and_then(|i| Some(i == "1")).is_some());
67 assert!(query_two.get("b").and_then(|i| Some(i == "2")).is_some());
68
69 let query_three = QueryData::from("a&b&c=3");
70
71 assert!(query_three.get("a").and_then(|i| Some(i == "")).is_some());
72 assert!(query_three.get("b").and_then(|i| Some(i == "")).is_some());
73 assert!(query_three.get("b").and_then(|i| Some(i == "2")).is_some());
74 }
75}