1pub mod rfc2396;
2pub mod uri;
3
4#[derive(Debug, Clone, Copy)]
6pub enum ParseRIError {
7 InvalidAuthority,
8 InvalidPathAbsolute,
9 InvalidSegment,
10 InvalidSegmentNzNc,
11 InvalidPChar,
12 InvalidScheme,
13 InvalidSchemeSeparator,
14 InvalidIPLiteral,
15 InvalidIPvFuture,
16 InvalidIPv6address,
17 InvalidH16,
18 InvalidLS32,
19 InvalidIPv4address,
20 InvalidDecOctet,
21 InvalidPctEncoded,
22 NotTermination,
23 Unsupported,
24 Unknown,
25}
26
27impl std::fmt::Display for ParseRIError {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 write!(f, "{self:?}")
30 }
31}
32
33impl std::error::Error for ParseRIError {}
34
35#[cfg(test)]
36mod tests {
37 use crate::uri::URIString;
38
39 #[test]
43 fn uri_parse_tests() {
44 let uri = URIString::parse(r#"ftp://ftp.is.co.za/rfc/rfc1808.txt"#).unwrap();
45 assert_eq!(uri.scheme().unwrap(), "ftp");
46 assert_eq!(uri.authority().unwrap(), "ftp.is.co.za");
47 assert!(uri.userinfo().is_none());
48 assert_eq!(uri.host().unwrap(), "ftp.is.co.za");
49 assert!(uri.port().is_none());
50 assert_eq!(uri.path(), "/rfc/rfc1808.txt");
51 assert!(uri.query().is_none());
52 assert!(uri.fragment().is_none());
53
54 let uri = URIString::parse(r#"http://www.ietf.org/rfc/rfc2396.txt"#).unwrap();
55 assert_eq!(uri.scheme().unwrap(), "http");
56 assert_eq!(uri.authority().unwrap(), "www.ietf.org");
57 assert!(uri.userinfo().is_none());
58 assert_eq!(uri.host().unwrap(), "www.ietf.org");
59 assert!(uri.port().is_none());
60 assert_eq!(uri.path(), "/rfc/rfc2396.txt");
61 assert!(uri.query().is_none());
62 assert!(uri.fragment().is_none());
63
64 let uri = URIString::parse(r#"ldap://[2001:db8::7]/c=GB?objectClass?one"#).unwrap();
65 assert_eq!(uri.scheme().unwrap(), "ldap");
66 assert_eq!(uri.authority().unwrap(), "[2001:db8::7]");
67 assert!(uri.userinfo().is_none());
68 assert_eq!(uri.host().unwrap(), "[2001:db8::7]");
69 assert!(uri.port().is_none());
70 assert_eq!(uri.path(), "/c=GB");
71 assert_eq!(uri.query().unwrap(), "objectClass?one");
72 assert!(uri.fragment().is_none());
73
74 let uri = URIString::parse(r#"mailto:John.Doe@example.com"#).unwrap();
75 assert_eq!(uri.scheme().unwrap(), "mailto");
76 assert!(uri.authority().is_none());
77 assert!(uri.userinfo().is_none());
78 assert!(uri.host().is_none());
79 assert!(uri.port().is_none());
80 assert_eq!(uri.path(), "John.Doe@example.com");
81 assert!(uri.query().is_none());
82 assert!(uri.fragment().is_none());
83
84 let uri = URIString::parse(r#"news:comp.infosystems.www.servers.unix"#).unwrap();
85 assert_eq!(uri.scheme().unwrap(), "news");
86 assert!(uri.authority().is_none());
87 assert!(uri.userinfo().is_none());
88 assert!(uri.host().is_none());
89 assert!(uri.port().is_none());
90 assert_eq!(uri.path(), "comp.infosystems.www.servers.unix");
91 assert!(uri.query().is_none());
92 assert!(uri.fragment().is_none());
93
94 let uri = URIString::parse(r#"tel:+1-816-555-1212"#).unwrap();
95 assert_eq!(uri.scheme().unwrap(), "tel");
96 assert!(uri.authority().is_none());
97 assert!(uri.userinfo().is_none());
98 assert!(uri.host().is_none());
99 assert!(uri.port().is_none());
100 assert_eq!(uri.path(), "+1-816-555-1212");
101 assert!(uri.query().is_none());
102 assert!(uri.fragment().is_none());
103
104 let uri = URIString::parse(r#"telnet://192.0.2.16:80/"#).unwrap();
105 assert_eq!(uri.scheme().unwrap(), "telnet");
106 assert_eq!(uri.authority().unwrap(), "192.0.2.16:80");
107 assert!(uri.userinfo().is_none());
108 assert_eq!(uri.host().unwrap(), "192.0.2.16");
109 assert_eq!(uri.port().unwrap(), "80");
110 assert_eq!(uri.path(), "/");
111 assert!(uri.query().is_none());
112 assert!(uri.fragment().is_none());
113
114 let uri =
115 URIString::parse(r#"urn:oasis:names:specification:docbook:dtd:xml:4.1.2"#).unwrap();
116 assert_eq!(uri.scheme().unwrap(), "urn");
117 assert!(uri.authority().is_none());
118 assert!(uri.userinfo().is_none());
119 assert!(uri.host().is_none());
120 assert!(uri.port().is_none());
121 assert_eq!(
122 uri.path(),
123 "oasis:names:specification:docbook:dtd:xml:4.1.2"
124 );
125 assert!(uri.query().is_none());
126 assert!(uri.fragment().is_none());
127
128 let uri =
129 URIString::parse(r#"foo://example.com:8042/over/there?name=ferret#nose"#).unwrap();
130 assert_eq!(uri.scheme().unwrap(), "foo");
131 assert_eq!(uri.authority().unwrap(), "example.com:8042");
132 assert!(uri.userinfo().is_none());
133 assert_eq!(uri.host().unwrap(), "example.com");
134 assert_eq!(uri.port().unwrap(), "8042");
135 assert_eq!(uri.path(), "/over/there");
136 assert_eq!(uri.query().unwrap(), "name=ferret");
137 assert_eq!(uri.fragment().unwrap(), "nose");
138
139 let uri = URIString::parse(r#"foo:"#).unwrap();
141 assert_eq!(uri.scheme().unwrap(), "foo");
142 assert!(uri.authority().is_none());
143 assert!(uri.userinfo().is_none());
144 assert!(uri.host().is_none());
145 assert!(uri.port().is_none());
146 assert_eq!(uri.path(), "");
147 assert!(uri.query().is_none());
148 assert!(uri.fragment().is_none());
149
150 let uri = URIString::parse(r#"foo:/"#).unwrap();
151 assert_eq!(uri.scheme().unwrap(), "foo");
152 assert!(uri.authority().is_none());
153 assert!(uri.userinfo().is_none());
154 assert!(uri.host().is_none());
155 assert!(uri.port().is_none());
156 assert_eq!(uri.path(), "/");
157 assert!(uri.query().is_none());
158 assert!(uri.fragment().is_none());
159
160 let uri = URIString::parse(r#"foo://"#).unwrap();
161 assert_eq!(uri.scheme().unwrap(), "foo");
162 assert_eq!(uri.authority().unwrap(), "");
163 assert!(uri.userinfo().is_none());
164 assert_eq!(uri.host().unwrap(), "");
165 assert!(uri.port().is_none());
166 assert_eq!(uri.path(), "");
167 assert!(uri.query().is_none());
168 assert!(uri.fragment().is_none());
169
170 let uri = URIString::parse(r#"foo:///"#).unwrap();
171 assert_eq!(uri.scheme().unwrap(), "foo");
172 assert_eq!(uri.authority().unwrap(), "");
173 assert!(uri.userinfo().is_none());
174 assert_eq!(uri.host().unwrap(), "");
175 assert!(uri.port().is_none());
176 assert_eq!(uri.path(), "/");
177 assert!(uri.query().is_none());
178 assert!(uri.fragment().is_none());
179
180 let uri = URIString::parse(r#"foo:////"#).unwrap();
181 assert_eq!(uri.scheme().unwrap(), "foo");
182 assert_eq!(uri.authority().unwrap(), "");
183 assert!(uri.userinfo().is_none());
184 assert_eq!(uri.host().unwrap(), "");
185 assert!(uri.port().is_none());
186 assert_eq!(uri.path(), "//");
187 assert!(uri.query().is_none());
188 assert!(uri.fragment().is_none());
189 }
190
191 #[test]
193 fn uri_resolve_tests() {
194 let base = URIString::parse(r#"http://a/b/c/d;p?q"#).unwrap();
195 assert!(base.is_absolute());
196
197 let rel = URIString::parse("g:h").unwrap();
199 assert_eq!(base.resolve(&rel).as_escaped_str(), "g:h");
200 let rel = URIString::parse("g").unwrap();
201 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g");
202 let rel = URIString::parse("./g").unwrap();
203 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g");
204 let rel = URIString::parse("g/").unwrap();
205 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g/");
206 let rel = URIString::parse("/g").unwrap();
207 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/g");
208 let rel = URIString::parse("//g").unwrap();
209 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://g");
210 let rel = URIString::parse("?y").unwrap();
211 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/d;p?y");
212 let rel = URIString::parse("g?y").unwrap();
213 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g?y");
214 let rel = URIString::parse("#s").unwrap();
215 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/d;p?q#s");
216 let rel = URIString::parse("g#s").unwrap();
217 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g#s");
218 let rel = URIString::parse("g?y#s").unwrap();
219 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g?y#s");
220 let rel = URIString::parse(";x").unwrap();
221 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/;x");
222 let rel = URIString::parse("g;x").unwrap();
223 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g;x");
224 let rel = URIString::parse("g;x?y#s").unwrap();
225 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g;x?y#s");
226 let rel = URIString::parse("").unwrap();
227 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/d;p?q");
228 let rel = URIString::parse(".").unwrap();
229 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/");
230 let rel = URIString::parse("./").unwrap();
231 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/");
232 let rel = URIString::parse("..").unwrap();
233 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/");
234 let rel = URIString::parse("../").unwrap();
235 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/");
236 let rel = URIString::parse("../g").unwrap();
237 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/g");
238 let rel = URIString::parse("../..").unwrap();
239 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/");
240 let rel = URIString::parse("../../").unwrap();
241 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/");
242 let rel = URIString::parse("../../g").unwrap();
243 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/g");
244
245 let rel = URIString::parse("../../../g").unwrap();
247 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/g");
248 let rel = URIString::parse("../../../../g").unwrap();
249 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/g");
250 let rel = URIString::parse("/./g").unwrap();
251 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/g");
252 let rel = URIString::parse("/../g").unwrap();
253 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/g");
254 let rel = URIString::parse("g.").unwrap();
255 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g.");
256 let rel = URIString::parse(".g").unwrap();
257 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/.g");
258 let rel = URIString::parse("g..").unwrap();
259 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g..");
260 let rel = URIString::parse("..g").unwrap();
261 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/..g");
262 let rel = URIString::parse("./../g").unwrap();
263 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/g");
264 let rel = URIString::parse("./g/.").unwrap();
265 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g/");
266 let rel = URIString::parse("g/./h").unwrap();
267 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g/h");
268 let rel = URIString::parse("g/../h").unwrap();
269 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/h");
270 let rel = URIString::parse("g;x=1/./y").unwrap();
271 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g;x=1/y");
272 let rel = URIString::parse("g;x=1/../y").unwrap();
273 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/y");
274 let rel = URIString::parse("g?y/./x").unwrap();
275 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g?y/./x");
276 let rel = URIString::parse("g?y/../x").unwrap();
277 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g?y/../x");
278 let rel = URIString::parse("g#s/./x").unwrap();
279 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g#s/./x");
280 let rel = URIString::parse("g#s/../x").unwrap();
281 assert_eq!(base.resolve(&rel).as_escaped_str(), "http://a/b/c/g#s/../x");
282
283 assert_eq!(
285 URIString::parse("http://www.example.org/one/two")
286 .unwrap()
287 .resolve(&URIString::parse("").unwrap())
288 .as_escaped_str(),
289 "http://www.example.org/one/two"
290 );
291 assert_eq!(
292 URIString::parse("http://www.example.org/one/two#frag")
293 .unwrap()
294 .resolve(&URIString::parse("").unwrap())
295 .as_escaped_str(),
296 "http://www.example.org/one/two"
297 );
298 }
299
300 #[cfg(target_family = "windows")]
301 #[test]
302 fn windows_path_test() {
303 assert_eq!(
304 URIString::parse_file_path("C:\\Windows\\System32\\")
305 .unwrap()
306 .as_escaped_str(),
307 "file:C:/Windows/System32/"
308 );
309 assert_eq!(
310 URIString::parse_file_path("\\\\localhost\\share\\")
311 .unwrap()
312 .as_escaped_str(),
313 "file://localhost/share/"
314 );
315
316 let test = URIString::parse_file_path("resources\\test.xml").unwrap();
317 assert_eq!(test.as_unescaped_str().unwrap(), "resources/test.xml");
318
319 let base = URIString::parse_file_path("C:\\Users\\someuser\\Document\\").unwrap();
320 assert_eq!(
321 base.as_unescaped_str().unwrap(),
322 "file:C:/Users/someuser/Document/"
323 );
324
325 let resolved = base.resolve(&test);
326 assert_eq!(
327 resolved.as_unescaped_str().unwrap(),
328 "file:C:/Users/someuser/Document/resources/test.xml"
329 );
330 }
331}