Skip to content

Commit bdde710

Browse files
committed
Path and file parsing.
1 parent 95e0891 commit bdde710

File tree

6 files changed

+300
-63
lines changed

6 files changed

+300
-63
lines changed

src/host.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ pub(crate) enum HostInternal {
2424
Ipv6(Ipv6Addr),
2525
}
2626

27-
impl<S> From<Host<S>> for HostInternal {
27+
impl<S> From<Host<S>> for HostInternal
28+
where
29+
S: ToString,
30+
{
2831
fn from(host: Host<S>) -> HostInternal {
2932
match host {
33+
Host::Domain(ref s) if s.to_string().is_empty() => HostInternal::None,
3034
Host::Domain(_) => HostInternal::Domain,
3135
Host::Ipv4(address) => HostInternal::Ipv4(address),
3236
Host::Ipv6(address) => HostInternal::Ipv6(address),

src/lib.rs

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -456,13 +456,15 @@ impl Url {
456456

457457
if self.slice(self.scheme_end + 1..).starts_with("//") {
458458
// URL with authority
459-
match self.byte_at(self.username_end) {
460-
b':' => {
461-
assert!(self.host_start >= self.username_end + 2);
462-
assert_eq!(self.byte_at(self.host_start - 1), b'@');
459+
if self.username_end != self.serialization.len() as u32 {
460+
match self.byte_at(self.username_end) {
461+
b':' => {
462+
assert!(self.host_start >= self.username_end + 2);
463+
assert_eq!(self.byte_at(self.host_start - 1), b'@');
464+
}
465+
b'@' => assert!(self.host_start == self.username_end + 1),
466+
_ => assert_eq!(self.username_end, self.scheme_end + 3),
463467
}
464-
b'@' => assert!(self.host_start == self.username_end + 1),
465-
_ => assert_eq!(self.username_end, self.scheme_end + 3),
466468
}
467469
assert!(self.host_start >= self.username_end);
468470
assert!(self.host_end >= self.host_start);
@@ -490,7 +492,10 @@ impl Url {
490492
Some(port_str.parse::<u16>().expect("Couldn't parse port?"))
491493
);
492494
}
493-
assert_eq!(self.byte_at(self.path_start), b'/');
495+
assert!(
496+
self.path_start as usize == self.serialization.len()
497+
|| matches!(self.byte_at(self.path_start), b'/' | b'#' | b'?')
498+
);
494499
} else {
495500
// Anarchist URL (no authority)
496501
assert_eq!(self.username_end, self.scheme_end + 1);
@@ -501,11 +506,11 @@ impl Url {
501506
assert_eq!(self.path_start, self.scheme_end + 1);
502507
}
503508
if let Some(start) = self.query_start {
504-
assert!(start > self.path_start);
509+
assert!(start >= self.path_start);
505510
assert_eq!(self.byte_at(start), b'?');
506511
}
507512
if let Some(start) = self.fragment_start {
508-
assert!(start > self.path_start);
513+
assert!(start >= self.path_start);
509514
assert_eq!(self.byte_at(start), b'#');
510515
}
511516
if let (Some(query_start), Some(fragment_start)) = (self.query_start, self.fragment_start) {
@@ -745,7 +750,10 @@ impl Url {
745750
pub fn password(&self) -> Option<&str> {
746751
// This ':' is not the one marking a port number since a host can not be empty.
747752
// (Except for file: URLs, which do not have port numbers.)
748-
if self.has_authority() && self.byte_at(self.username_end) == b':' {
753+
if self.has_authority()
754+
&& self.username_end != self.serialization.len() as u32
755+
&& self.byte_at(self.username_end) == b':'
756+
{
749757
debug_assert!(self.byte_at(self.host_start - 1) == b'@');
750758
Some(self.slice(self.username_end + 1..self.host_start - 1))
751759
} else {
@@ -1226,7 +1234,7 @@ impl Url {
12261234
if let Some(input) = fragment {
12271235
self.fragment_start = Some(to_u32(self.serialization.len()).unwrap());
12281236
self.serialization.push('#');
1229-
self.mutate(|parser| parser.parse_fragment(parser::Input::new(input)))
1237+
self.mutate(|parser| parser.parse_fragment(parser::Input::no_trim(input)))
12301238
} else {
12311239
self.fragment_start = None
12321240
}
@@ -1284,7 +1292,12 @@ impl Url {
12841292
let scheme_type = SchemeType::from(self.scheme());
12851293
let scheme_end = self.scheme_end;
12861294
self.mutate(|parser| {
1287-
parser.parse_query(scheme_type, scheme_end, parser::Input::new(input))
1295+
let vfn = parser.violation_fn;
1296+
parser.parse_query(
1297+
scheme_type,
1298+
scheme_end,
1299+
parser::Input::trim_tab_and_newlines(input, vfn),
1300+
)
12881301
});
12891302
}
12901303

@@ -1390,8 +1403,12 @@ impl Url {
13901403
}
13911404
parser.parse_cannot_be_a_base_path(parser::Input::new(path));
13921405
} else {
1406+
let path_start = parser.serialization.len();
13931407
let mut has_host = true; // FIXME
13941408
parser.parse_path_start(scheme_type, &mut has_host, parser::Input::new(path));
1409+
if scheme_type.is_file() {
1410+
parser::trim_path(&mut parser.serialization, path_start);
1411+
}
13951412
}
13961413
});
13971414
self.restore_after_path(old_after_path_pos, &after_path);

0 commit comments

Comments
 (0)