web_url/parse/pre_path/
pre_path.rs1use crate::parse::pre_path::parse_scheme_len;
2use crate::parse::pre_path::{parse_host, parse_ip_and_validate_domain, parse_port};
3use crate::parse::Error;
4use address::IPAddress;
5
6#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
8pub struct PrePath {
9 pub scheme_len: usize,
10 pub host_len: usize,
11 pub ip: Option<IPAddress>,
12 pub port: Option<u16>,
13 pub port_len: usize,
14}
15
16impl PrePath {
17 pub fn len(&self) -> usize {
21 self.scheme_len + 3 + self.host_len + self.port_len
22 }
23
24 pub fn is_empty(&self) -> bool {
26 false
27 }
28}
29
30impl PrePath {
31 pub unsafe fn make_lowercase(&self, url: &mut str) {
39 url[..self.len()]
40 .as_bytes_mut()
41 .iter_mut()
42 .for_each(|c| *c = c.to_ascii_lowercase())
43 }
44}
45
46pub fn parse_pre_path(url: &str) -> Result<PrePath, Error> {
52 let (scheme_len, after_scheme) = parse_scheme_len(url)?;
53 let (host_str, after_host) = parse_host(after_scheme);
54 let ip: Option<IPAddress> = parse_ip_and_validate_domain(host_str)?;
55 let (port, after_port) = parse_port(after_host)?;
56 let port_len: usize = after_host.len() - after_port.len();
57 let pre_path: PrePath = PrePath {
58 scheme_len,
59 host_len: host_str.len(),
60 ip,
61 port,
62 port_len,
63 };
64 Ok(pre_path)
65}
66
67#[cfg(test)]
68mod tests {
69 use crate::parse::pre_path::{parse_pre_path, PrePath};
70 use crate::parse::Error;
71 use crate::parse::Error::{InvalidHost, InvalidScheme};
72 use address::{IPv4Address, IPv6Address};
73
74 #[test]
75 fn fn_parse_pre_path() {
76 let test_cases: &[(&str, Result<PrePath, Error>)] = &[
77 ("scheme:/", Err(InvalidScheme)),
78 ("!://", Err(InvalidScheme)),
79 ("scheme://", Err(InvalidHost)),
80 (
81 "scheme://host",
82 Ok(PrePath {
83 scheme_len: 6,
84 host_len: 4,
85 ip: None,
86 port: None,
87 port_len: 0,
88 }),
89 ),
90 (
91 "scheme://127.0.0.1",
92 Ok(PrePath {
93 scheme_len: 6,
94 host_len: 9,
95 ip: Some(IPv4Address::LOCALHOST.to_ip()),
96 port: None,
97 port_len: 0,
98 }),
99 ),
100 ("scheme://::1", Err(InvalidHost)),
101 (
102 "scheme://[::1]",
103 Ok(PrePath {
104 scheme_len: 6,
105 host_len: 5,
106 ip: Some(IPv6Address::LOCALHOST.to_ip()),
107 port: None,
108 port_len: 0,
109 }),
110 ),
111 (
112 "scheme://[::1]:80",
113 Ok(PrePath {
114 scheme_len: 6,
115 host_len: 5,
116 ip: Some(IPv6Address::LOCALHOST.to_ip()),
117 port: Some(80),
118 port_len: 3,
119 }),
120 ),
121 (
122 "scheme://[::1]:80/the/path",
123 Ok(PrePath {
124 scheme_len: 6,
125 host_len: 5,
126 ip: Some(IPv6Address::LOCALHOST.to_ip()),
127 port: Some(80),
128 port_len: 3,
129 }),
130 ),
131 ];
132 for (input, expected) in test_cases {
133 let result: Result<PrePath, Error> = parse_pre_path(input);
134 assert_eq!(result, *expected, "input={}", input);
135 }
136 }
137}