1use crate::{Param, Query, WebUrl};
2
3impl WebUrl {
4 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 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 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 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}