web_url/url/
query.rs

1use crate::{Param, Query, WebUrl};
2
3impl WebUrl {
4    //! Query
5
6    /// Gets the optional query.
7    pub fn query(&self) -> Option<Query<'_>> {
8        let query: &str = self.query_str();
9        if query.is_empty() {
10            None
11        } else {
12            Some(unsafe { Query::new(query) })
13        }
14    }
15
16    /// Gets the query string.
17    ///
18    /// This will be a valid query string starting with a '?' or it will be empty.
19    fn query_str(&self) -> &str {
20        let start: usize = self.path_end as usize;
21        let end: usize = self.query_end as usize;
22        &self.url[start..end]
23    }
24}
25
26impl WebUrl {
27    //! Query Parameter Mutations
28
29    /// Adds the query `param`.
30    pub fn add_param<'a, P>(&mut self, param: P)
31    where
32        P: Into<Param<'a>>,
33    {
34        // todo -- this could be more efficient but probably doesn't matter
35
36        let param: Param = param.into();
37        let start: usize = self.path_end as usize;
38        let mut end: usize = self.query_end as usize;
39
40        let extra: usize = 1 + param.name().len() + param.value().map(|v| 1 + v.len()).unwrap_or(0);
41        self.url.reserve(extra);
42
43        let c: char = if start == end { '?' } else { '&' };
44        self.url.insert(end, c);
45        end += 1;
46
47        self.url.insert_str(end, param.name());
48        end += param.name().len();
49
50        if let Some(value) = param.value() {
51            self.url.insert(end, '=');
52            end += 1;
53
54            self.url.insert_str(end, value);
55            end += value.len();
56        }
57
58        self.query_end = end as u32;
59    }
60
61    /// Adds the query `param`.
62    pub fn with_param<'a, P>(mut self, param: P) -> Self
63    where
64        P: Into<Param<'a>>,
65    {
66        self.add_param(param);
67        self
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use crate::{Fragment, Param, WebUrl};
74    use std::error::Error;
75    use std::str::FromStr;
76
77    #[test]
78    fn add_param() -> Result<(), Box<dyn Error>> {
79        let mut url: WebUrl = WebUrl::from_str("https://example.com")?;
80        url.set_fragment(Fragment::try_from("#fragment")?);
81
82        url.add_param(Param::try_from("one")?);
83        assert_eq!("https://example.com/?one#fragment", url.as_str());
84
85        url.add_param(Param::try_from("two=3")?);
86        assert_eq!("https://example.com/?one&two=3#fragment", url.as_str());
87
88        Ok(())
89    }
90}