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();
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 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}