summaryrefslogtreecommitdiffstats
path: root/vendor/url/src/lib.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/url/src/lib.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/url/src/lib.rs')
-rw-r--r--vendor/url/src/lib.rs114
1 files changed, 108 insertions, 6 deletions
diff --git a/vendor/url/src/lib.rs b/vendor/url/src/lib.rs
index 6dc09d12f..ad3c89001 100644
--- a/vendor/url/src/lib.rs
+++ b/vendor/url/src/lib.rs
@@ -121,7 +121,7 @@ url = { version = "2", features = ["serde"] }
*/
-#![doc(html_root_url = "https://docs.rs/url/2.3.1")]
+#![doc(html_root_url = "https://docs.rs/url/2.4.0")]
#![cfg_attr(
feature = "debugger_visualizer",
feature(debugger_visualizer),
@@ -322,6 +322,32 @@ impl Url {
url
}
+ /// https://url.spec.whatwg.org/#potentially-strip-trailing-spaces-from-an-opaque-path
+ fn strip_trailing_spaces_from_opaque_path(&mut self) {
+ if !self.cannot_be_a_base() {
+ return;
+ }
+
+ if self.fragment_start.is_some() {
+ return;
+ }
+
+ if self.query_start.is_some() {
+ return;
+ }
+
+ let trailing_space_count = self
+ .serialization
+ .chars()
+ .rev()
+ .take_while(|c| *c == ' ')
+ .count();
+
+ let start = self.serialization.len() - trailing_space_count;
+
+ self.serialization.truncate(start);
+ }
+
/// Parse a string as an URL, with this URL as the base URL.
///
/// The inverse of this is [`make_relative`].
@@ -601,7 +627,7 @@ impl Url {
}
assert!(self.scheme_end >= 1);
- assert!(matches!(self.byte_at(0), b'a'..=b'z' | b'A'..=b'Z'));
+ assert!(self.byte_at(0).is_ascii_alphabetic());
assert!(self
.slice(1..self.scheme_end)
.chars()
@@ -657,7 +683,14 @@ impl Url {
assert_eq!(self.host_end, self.scheme_end + 1);
assert_eq!(self.host, HostInternal::None);
assert_eq!(self.port, None);
- assert_eq!(self.path_start, self.scheme_end + 1);
+ if self.path().starts_with("//") {
+ // special case when first path segment is empty
+ assert_eq!(self.byte_at(self.scheme_end + 1), b'/');
+ assert_eq!(self.byte_at(self.scheme_end + 2), b'.');
+ assert_eq!(self.path_start, self.scheme_end + 3);
+ } else {
+ assert_eq!(self.path_start, self.scheme_end + 1);
+ }
}
if let Some(start) = self.query_start {
assert!(start >= self.path_start);
@@ -786,12 +819,35 @@ impl Url {
self.slice(..self.scheme_end)
}
+ /// Return whether the URL is special (has a special scheme)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use url::Url;
+ /// # use url::ParseError;
+ ///
+ /// # fn run() -> Result<(), ParseError> {
+ /// assert!(Url::parse("http:///tmp/foo")?.is_special());
+ /// assert!(Url::parse("file:///tmp/foo")?.is_special());
+ /// assert!(!Url::parse("moz:///tmp/foo")?.is_special());
+ /// # Ok(())
+ /// # }
+ /// # run().unwrap();
+ /// ```
+ pub fn is_special(&self) -> bool {
+ let scheme_type = SchemeType::from(self.scheme());
+ scheme_type.is_special()
+ }
+
/// Return whether the URL has an 'authority',
/// which can contain a username, password, host, and port number.
///
/// URLs that do *not* are either path-only like `unix:/run/foo.socket`
/// or cannot-be-a-base like `data:text/plain,Stuff`.
///
+ /// See also the `authority` method.
+ ///
/// # Examples
///
/// ```
@@ -817,6 +873,47 @@ impl Url {
self.slice(self.scheme_end..).starts_with("://")
}
+ /// Return the authority of this URL as an ASCII string.
+ ///
+ /// Non-ASCII domains are punycode-encoded per IDNA if this is the host
+ /// of a special URL, or percent encoded for non-special URLs.
+ /// IPv6 addresses are given between `[` and `]` brackets.
+ /// Ports are omitted if they match the well known port of a special URL.
+ ///
+ /// Username and password are percent-encoded.
+ ///
+ /// See also the `has_authority` method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use url::Url;
+ /// # use url::ParseError;
+ ///
+ /// # fn run() -> Result<(), ParseError> {
+ /// let url = Url::parse("unix:/run/foo.socket")?;
+ /// assert_eq!(url.authority(), "");
+ /// let url = Url::parse("file:///tmp/foo")?;
+ /// assert_eq!(url.authority(), "");
+ /// let url = Url::parse("https://user:password@example.com/tmp/foo")?;
+ /// assert_eq!(url.authority(), "user:password@example.com");
+ /// let url = Url::parse("irc://àlex.рф.example.com:6667/foo")?;
+ /// assert_eq!(url.authority(), "%C3%A0lex.%D1%80%D1%84.example.com:6667");
+ /// let url = Url::parse("http://àlex.рф.example.com:80/foo")?;
+ /// assert_eq!(url.authority(), "xn--lex-8ka.xn--p1ai.example.com");
+ /// # Ok(())
+ /// # }
+ /// # run().unwrap();
+ /// ```
+ pub fn authority(&self) -> &str {
+ let scheme_separator_len = "://".len() as u32;
+ if self.has_authority() && self.path_start > self.scheme_end + scheme_separator_len {
+ self.slice(self.scheme_end + scheme_separator_len..self.path_start)
+ } else {
+ ""
+ }
+ }
+
/// 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.
///
@@ -1391,7 +1488,8 @@ impl Url {
self.serialization.push('#');
self.mutate(|parser| parser.parse_fragment(parser::Input::no_trim(input)))
} else {
- self.fragment_start = None
+ self.fragment_start = None;
+ self.strip_trailing_spaces_from_opaque_path();
}
}
@@ -1454,6 +1552,9 @@ impl Url {
parser::Input::trim_tab_and_newlines(input, vfn),
)
});
+ } else {
+ self.query_start = None;
+ self.strip_trailing_spaces_from_opaque_path();
}
self.restore_already_parsed_fragment(fragment);
@@ -1989,7 +2090,8 @@ impl Url {
if !self.has_host() || self.host() == Some(Host::Domain("")) || self.scheme() == "file" {
return Err(());
}
- if let Some(password) = password {
+ let password = password.unwrap_or_default();
+ if !password.is_empty() {
let host_and_after = self.slice(self.host_start..).to_owned();
self.serialization.truncate(self.username_end as usize);
self.serialization.push(':');
@@ -2805,7 +2907,7 @@ fn file_url_segments_to_pathbuf(
// A windows drive letter must end with a slash.
if bytes.len() > 2
- && matches!(bytes[bytes.len() - 2], b'a'..=b'z' | b'A'..=b'Z')
+ && bytes[bytes.len() - 2].is_ascii_alphabetic()
&& matches!(bytes[bytes.len() - 1], b':' | b'|')
{
bytes.push(b'/');