Skip to main content

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        let param: Param = param.into();
35        let end: usize = self.query_end as usize;
36
37        let c: char = if self.path_end == self.query_end {
38            '?'
39        } else {
40            '&'
41        };
42
43        let mut s = String::with_capacity(
44            1 + param.name().len() + param.value().map(|v| 1 + v.len()).unwrap_or(0),
45        );
46        s.push(c);
47        s.push_str(param.name());
48        if let Some(value) = param.value() {
49            s.push('=');
50            s.push_str(value);
51        }
52
53        self.url.insert_str(end, &s);
54        self.query_end = (end + s.len()) as u32;
55    }
56
57    /// Adds the query `param`.
58    pub fn with_param<'a, P>(mut self, param: P) -> Self
59    where
60        P: Into<Param<'a>>,
61    {
62        self.add_param(param);
63        self
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use crate::{Fragment, Param, WebUrl};
70    use std::error::Error;
71    use std::str::FromStr;
72
73    #[test]
74    fn query_accessor() -> Result<(), Box<dyn Error>> {
75        let url = WebUrl::from_str("https://example.com/path?key=value")?;
76        let query = url.query().unwrap();
77        assert_eq!(query.as_str(), "?key=value");
78
79        let url = WebUrl::from_str("https://example.com/path")?;
80        assert!(url.query().is_none());
81
82        Ok(())
83    }
84
85    #[test]
86    fn add_param() -> Result<(), Box<dyn Error>> {
87        let mut url: WebUrl = WebUrl::from_str("https://example.com")?;
88        url.set_fragment(Fragment::try_from("#fragment")?);
89
90        url.add_param(Param::try_from("one")?);
91        assert_eq!("https://example.com/?one#fragment", url.as_str());
92
93        url.add_param(Param::try_from("two=3")?);
94        assert_eq!("https://example.com/?one&two=3#fragment", url.as_str());
95
96        Ok(())
97    }
98
99    #[test]
100    fn with_param() -> Result<(), Box<dyn Error>> {
101        let url = WebUrl::from_str("https://example.com")?
102            .with_param(Param::try_from("a=1")?)
103            .with_param(Param::try_from("b=2")?);
104        assert_eq!(url.as_str(), "https://example.com/?a=1&b=2");
105
106        Ok(())
107    }
108}