uri_parsing_rs/ast/
query.rs

1use std::collections::HashMap;
2use itertools::Itertools;
3use std::fmt::Formatter;
4use std::cmp::Ordering;
5
6#[derive(Debug, Clone, PartialEq, Hash)]
7pub struct Query {
8  params: Vec<(String, Option<String>)>,
9}
10
11impl Default for Query {
12  fn default() -> Self {
13    Query {
14      params: Vec::default(),
15    }
16  }
17}
18
19impl PartialOrd for Query {
20  fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
21    self.to_string().partial_cmp(&other.to_string())
22  }
23}
24
25impl std::fmt::Display for Query {
26  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
27    write!(f, "{}", self.as_string())
28  }
29}
30
31impl From<Vec<(String, Option<String>)>> for Query {
32  fn from(src: Vec<(String, Option<String>)>) -> Self {
33    let params = src.into_iter().collect_vec();
34    Self { params }
35  }
36}
37
38impl From<Vec<(&str, Option<&str>)>> for Query {
39  fn from(src: Vec<(&str, Option<&str>)>) -> Self {
40    let params = src
41      .into_iter()
42      .map(|(k, v)| (k.to_string(), v.map(|v| v.to_string())))
43      .collect_vec();
44    Self { params }
45  }
46}
47
48impl Query {
49  pub fn new(params: Vec<(String, Option<String>)>) -> Self {
50    Self { params }
51  }
52
53  pub fn params(&self) -> HashMap<&String, Vec<&String>> {
54    let mut result: HashMap<&String, Vec<&String>> = HashMap::new();
55    for (key, value) in self.params.iter() {
56      match (result.get_mut(&key), value) {
57        (None, None) => {
58          result.insert(key, Vec::new());
59        }
60        (None, Some(v)) => {
61          result.insert(key, vec![v]);
62        }
63        (Some(values), Some(v)) => {
64          values.push(v);
65        }
66        _ => (),
67      }
68    }
69    result
70  }
71
72  pub fn add(&mut self, key: String, value: String) {
73    self.params.push((key, Some(value)));
74  }
75
76  pub fn add_opt(&mut self, key: String, value: Option<String>) {
77    match value {
78      Some(v) => {
79        self.add(key, v);
80        ()
81      }
82      None => (),
83    }
84  }
85
86  pub fn get_param(&self, key: String) -> Option<Vec<&String>> {
87    self.params().get(&key).map(|v| v.clone())
88  }
89
90  pub fn as_string(&self) -> String {
91    self
92      .params
93      .iter()
94      .map(|(k, v)| {
95        if v.is_none() {
96          k.clone()
97        } else {
98          format!(
99            "{}{}",
100            k,
101            v.as_ref()
102              .map(|s| format!("={}", s))
103              .unwrap_or("".to_string())
104          )
105        }
106      })
107      .join("&")
108  }
109}