Skip to content

Commit

Permalink
Rename non-relative to cannot-be-a-base, per upcoming spec change.
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonSapin committed Mar 25, 2016
1 parent 5e0ffed commit 47af82d
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 37 deletions.
54 changes: 29 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ assert!(issue_list_url.path_segments().map(|c| c.collect::<Vec<_>>()) ==
Some(vec!["rust-lang", "rust", "issues"]));
assert!(issue_list_url.query() == Some("labels=E-easy&state=open"));
assert!(issue_list_url.fragment() == None);
assert!(!issue_list_url.non_relative());
assert!(!issue_list_url.cannot_be_a_base());
```
Some URLs are said to be "non-relative":
Some URLs are said to be *cannot-be-a-base*:
they don’t have a username, password, host, or port,
and their "path" is an arbitrary string rather than slash-separated segments:
Expand All @@ -80,7 +80,7 @@ use url::Url;
let data_url = Url::parse("data:text/plain,Hello?World#").unwrap();
assert!(data_url.non_relative());
assert!(data_url.cannot_be_a_base());
assert!(data_url.scheme() == "data");
assert!(data_url.path() == "text/plain,Hello");
assert!(data_url.path_segments().is_none());
Expand Down Expand Up @@ -250,9 +250,13 @@ impl Url {
self.slice(self.scheme_end + 1 ..).starts_with("//")
}

/// Return whether this URL is non-relative (typical of e.g. `data:` and `mailto:` URLs.)
/// Return whether this URL is a cannot-be-a-base URL,
/// meaning that parsing a relative URL string with this URL as the base will return an error.
///
/// This is the case if the scheme and `:` delimiter are not followed by a `/` slash,
/// as is typically the case of `data:` and `mailto:` URLs.
#[inline]
pub fn non_relative(&self) -> bool {
pub fn cannot_be_a_base(&self) -> bool {
self.byte_at(self.path_start) != b'/'
}

Expand Down Expand Up @@ -285,7 +289,7 @@ impl Url {
/// Non-ASCII domains are punycode-encoded per IDNA.
/// IPv6 addresses are given between `[` and `]` brackets.
///
/// Non-relative URLs (typical of `data:` and `mailto:`) and some `file:` URLs
/// Cannot-be-a-base URLs (typical of `data:` and `mailto:`) and some `file:` URLs
/// don’t have a host.
///
/// See also the `host` method.
Expand All @@ -300,7 +304,7 @@ impl Url {
/// Return the parsed representation of the host for this URL.
/// Non-ASCII domain labels are punycode-encoded per IDNA.
///
/// Non-relative URLs (typical of `data:` and `mailto:`) and some `file:` URLs
/// Cannot-be-a-base URLs (typical of `data:` and `mailto:`) and some `file:` URLs
/// don’t have a host.
///
/// See also the `host_str` method.
Expand Down Expand Up @@ -384,7 +388,7 @@ impl Url {
/// Return the path for this URL, as a percent-encoded ASCII string.
/// For relative URLs, this starts with a '/' slash
/// and continues with slash-separated path segments.
/// For non-relative URLs, this is an arbitrary string that doesn’t start with '/'.
/// For cannot-be-a-base URLs, this is an arbitrary string that doesn’t start with '/'.
pub fn path(&self) -> &str {
match (self.query_start, self.fragment_start) {
(None, None) => self.slice(self.path_start..),
Expand All @@ -398,7 +402,7 @@ impl Url {
/// If this URL is relative, return an iterator of '/' slash-separated path segments,
/// each as a percent-encoded ASCII string.
///
/// Return `None` for non-relative URLs, or an iterator of at least one string.
/// Return `None` for cannot-be-a-base URLs, or an iterator of at least one string.
pub fn path_segments(&self) -> Option<str::Split<char>> {
let path = self.path();
if path.starts_with('/') {
Expand Down Expand Up @@ -492,16 +496,16 @@ impl Url {
(Some(i), _) | (None, Some(i)) => (i, self.slice(i..).to_owned()),
(None, None) => (to_u32(self.serialization.len()).unwrap(), String::new())
};
let non_relative = self.non_relative();
let cannot_be_a_base = self.cannot_be_a_base();
let scheme_type = SchemeType::from(self.scheme());
self.serialization.truncate(self.path_start as usize);
self.mutate(|parser| {
if non_relative {
if cannot_be_a_base {
if path.starts_with('/') {
parser.serialization.push_str("%2F");
parser.parse_non_relative_path(&path[1..]);
parser.parse_cannot_be_a_base_path(&path[1..]);
} else {
parser.parse_non_relative_path(path);
parser.parse_cannot_be_a_base_path(path);
}
} else {
let mut has_host = true; // FIXME
Expand All @@ -520,9 +524,9 @@ impl Url {

/// Remove the last segment of this URL’s path.
///
/// If this URL is non-relative, do nothing and return `Err`.
/// If this URL is cannot-be-a-base, do nothing and return `Err`.
pub fn pop_path_segment(&mut self) -> Result<(), ()> {
if self.non_relative() {
if self.cannot_be_a_base() {
return Err(())
}
let last_slash;
Expand All @@ -548,9 +552,9 @@ impl Url {

/// Add a segment at the end of this URL’s path.
///
/// If this URL is non-relative, do nothing and return `Err`.
/// If this URL is cannot-be-a-base, do nothing and return `Err`.
pub fn push_path_segment(&mut self, segment: &str) -> Result<(), ()> {
if self.non_relative() {
if self.cannot_be_a_base() {
return Err(())
}
let after_path = match (self.query_start, self.fragment_start) {
Expand Down Expand Up @@ -578,7 +582,7 @@ impl Url {

/// Change this URL’s port number.
///
/// If this URL is non-relative, does not have a host, or has the `file` scheme;
/// If this URL is cannot-be-a-base, does not have a host, or has the `file` scheme;
/// do nothing and return `Err`.
pub fn set_port(&mut self, mut port: Option<u16>) -> Result<(), ()> {
if !self.has_host() || self.scheme() == "file" {
Expand Down Expand Up @@ -625,13 +629,13 @@ impl Url {

/// Change this URL’s host.
///
/// If this URL is non-relative or there is an error parsing the given `host`,
/// If this URL is cannot-be-a-base or there is an error parsing the given `host`,
/// do nothing and return `Err`.
///
/// Removing the host (calling this with `None`)
/// will also remove any username, password, and port number.
pub fn set_host(&mut self, host: Option<&str>) -> Result<(), ()> {
if self.non_relative() {
if self.cannot_be_a_base() {
return Err(())
}

Expand Down Expand Up @@ -695,11 +699,11 @@ impl Url {

/// Change this URL’s host to the given IP address.
///
/// If this URL is non-relative, do nothing and return `Err`.
/// If this URL is cannot-be-a-base, do nothing and return `Err`.
///
/// Compared to `Url::set_host`, this skips the host parser.
pub fn set_ip_host(&mut self, address: IpAddr) -> Result<(), ()> {
if self.non_relative() {
if self.cannot_be_a_base() {
return Err(())
}

Expand All @@ -713,7 +717,7 @@ impl Url {

/// Change this URL’s password.
///
/// If this URL is non-relative or does not have a host, do nothing and return `Err`.
/// If this URL is cannot-be-a-base or does not have a host, do nothing and return `Err`.
pub fn set_password(&mut self, password: Option<&str>) -> Result<(), ()> {
if !self.has_host() {
return Err(())
Expand Down Expand Up @@ -763,7 +767,7 @@ impl Url {

/// Change this URL’s username.
///
/// If this URL is non-relative or does not have a host, do nothing and return `Err`.
/// If this URL is cannot-be-a-base or does not have a host, do nothing and return `Err`.
pub fn set_username(&mut self, username: &str) -> Result<(), ()> {
if !self.has_host() {
return Err(())
Expand Down Expand Up @@ -801,7 +805,7 @@ impl Url {
///
/// Do nothing and return `Err` if:
/// * The new scheme is not in `[a-zA-Z][a-zA-Z0-9+.-]+`
/// * This URL is non-relative and the new scheme is one of
/// * This URL is cannot-be-a-base and the new scheme is one of
/// `http`, `https`, `ws`, `wss`, `ftp`, or `gopher`
pub fn set_scheme(&mut self, scheme: &str) -> Result<(), ()> {
self.set_scheme_internal(scheme, false)
Expand Down
14 changes: 7 additions & 7 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ simple_enum_error! {
InvalidIpv6Address => "invalid IPv6 address",
InvalidDomainCharacter => "invalid domain character",
RelativeUrlWithoutBase => "relative URL without a base",
RelativeUrlWithNonRelativeBase => "relative URL with a non-relative base",
RelativeUrlWithCannotBeABaseBase => "relative URL with a cannot-be-a-base base",
Overflow => "URLs more than 4 GB are not supported",
}

Expand Down Expand Up @@ -150,8 +150,8 @@ impl<'a> Parser<'a> {
if let Some(base_url) = self.base_url {
if input.starts_with("#") {
self.fragment_only(base_url, input)
} else if base_url.non_relative() {
Err(ParseError::RelativeUrlWithNonRelativeBase)
} else if base_url.cannot_be_a_base() {
Err(ParseError::RelativeUrlWithCannotBeABaseBase)
} else {
let scheme_type = SchemeType::from(base_url.scheme());
if scheme_type.is_file() {
Expand Down Expand Up @@ -210,8 +210,8 @@ impl<'a> Parser<'a> {
if let Some(base_url) = self.base_url {
if slashes_count < 2 &&
base_url.scheme() == &self.serialization[..scheme_end as usize] {
// Non-relative URLs only happen with "not special" schemes.
debug_assert!(!base_url.non_relative());
// "Cannot-be-a-base" URLs only happen with "not special" schemes.
debug_assert!(!base_url.cannot_be_a_base());
self.serialization.clear();
return self.parse_relative(input, scheme_type, base_url)
}
Expand Down Expand Up @@ -243,7 +243,7 @@ impl<'a> Parser<'a> {
self.serialization.push('/');
self.parse_path(scheme_type, &mut false, path_start, &input[1..])
} else {
self.parse_non_relative_path(input)
self.parse_cannot_be_a_base_path(input)
};
self.with_query_and_fragment(scheme_end, username_end, host_start,
host_end, host, port, path_start, remaining)
Expand Down Expand Up @@ -854,7 +854,7 @@ impl<'a> Parser<'a> {

}

pub fn parse_non_relative_path<'i>(&mut self, input: &'i str) -> &'i str {
pub fn parse_cannot_be_a_base_path<'i>(&mut self, input: &'i str) -> &'i str {
for (i, c, next_i) in input.char_ranges() {
match c {
'?' | '#' if self.context == Context::UrlParser => return &input[i..],
Expand Down
2 changes: 1 addition & 1 deletion src/percent_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ macro_rules! define_encode_set {
}
}

/// This encode set is used for fragment identifier and non-relative scheme data.
/// This encode set is used for the path of cannot-be-a-base URLs.
#[derive(Copy, Clone)]
#[allow(non_camel_case_types)]
pub struct SIMPLE_ENCODE_SET;
Expand Down
8 changes: 4 additions & 4 deletions src/webidl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl WebIdl {

/// Setter for https://url.spec.whatwg.org/#dom-url-host
pub fn set_host(url: &mut Url, new_host: &str) {
if url.non_relative() {
if url.cannot_be_a_base() {
return
}
let host;
Expand Down Expand Up @@ -123,7 +123,7 @@ impl WebIdl {

/// Setter for https://url.spec.whatwg.org/#dom-url-hostname
pub fn set_hostname(url: &mut Url, new_hostname: &str) {
if url.non_relative() {
if url.cannot_be_a_base() {
return
}
let result = Parser::parse_host(new_hostname, SchemeType::from(url.scheme()), |_| ());
Expand All @@ -147,7 +147,7 @@ impl WebIdl {
pub fn set_port(url: &mut Url, new_port: &str) {
let result;
{
// has_host implies !non_relative
// has_host implies !cannot_be_a_base
let scheme = url.scheme();
if !url.has_host() || scheme == "file" {
return
Expand All @@ -167,7 +167,7 @@ impl WebIdl {

/// Setter for https://url.spec.whatwg.org/#dom-url-pathname
pub fn set_pathname(url: &mut Url, new_pathname: &str) {
if !url.non_relative() {
if !url.cannot_be_a_base() {
url.set_path(new_pathname)
}
}
Expand Down

0 comments on commit 47af82d

Please sign in to comment.