lastfm_client/
url_builder.rs

1use std::collections::HashMap;
2
3pub type QueryParams = HashMap<String, String>;
4
5#[derive(Debug, Clone)]
6pub struct Url {
7    base: String,
8    query_params: QueryParams,
9}
10
11impl Url {
12    #[must_use]
13    pub fn new(base: &str) -> Self {
14        Url {
15            base: base.to_string(),
16            query_params: HashMap::new(),
17        }
18    }
19
20    #[must_use]
21    pub fn add_args(mut self, args: QueryParams) -> Self {
22        self.query_params.extend(args);
23
24        self
25    }
26
27    #[must_use]
28    pub fn build(&self) -> String {
29        if self.query_params.is_empty() {
30            return self.base.clone();
31        }
32
33        let query_string: Vec<String> = self
34            .query_params
35            .iter()
36            .map(|(k, v)| format!("{k}={v}"))
37            .collect();
38
39        format!("{}?{}", self.base, query_string.join("&"))
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn test_basic_url() {
49        let url = Url::new("https://www.google.com");
50        assert_eq!(url.build(), "https://www.google.com");
51    }
52
53    #[test]
54    fn test_single_query_param() {
55        let mut params = HashMap::new();
56        params.insert("q".to_string(), "rust".to_string());
57
58        let url = Url::new("https://www.google.com").add_args(params);
59        assert_eq!(url.build(), "https://www.google.com?q=rust");
60    }
61
62    #[test]
63    fn test_multiple_query_params() {
64        let mut params = HashMap::new();
65        params.insert("q".to_string(), "rust".to_string());
66        params.insert("lang".to_string(), "en".to_string());
67
68        let url = Url::new("https://www.google.com").add_args(params);
69        let built_url = url.build();
70        assert!(
71            built_url == "https://www.google.com?q=rust&lang=en"
72                || built_url == "https://www.google.com?lang=en&q=rust"
73        );
74    }
75
76    #[test]
77    fn test_chained_param_addition() {
78        let url = Url::new("https://www.example.com")
79            .add_args(HashMap::from([("page".to_string(), "1".to_string())]))
80            .add_args(HashMap::from([("limit".to_string(), "10".to_string())]));
81
82        let built_url = url.build();
83        assert!(
84            built_url == "https://www.example.com?page=1&limit=10"
85                || built_url == "https://www.example.com?limit=10&page=1"
86        );
87    }
88
89    #[test]
90    fn test_param_overwrite() {
91        let mut params1 = HashMap::new();
92        params1.insert("key".to_string(), "value1".to_string());
93
94        let mut params2 = HashMap::new();
95        params2.insert("key".to_string(), "value2".to_string());
96
97        let url = Url::new("https://www.example.com")
98            .add_args(params1)
99            .add_args(params2);
100
101        assert_eq!(url.build(), "https://www.example.com?key=value2");
102    }
103}