diff --git a/Cargo.lock b/Cargo.lock index 684d946..0cafff4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "ada-url" -version = "1.0.1" +version = "1.0.2" dependencies = [ "cc", "criterion", diff --git a/Cargo.toml b/Cargo.toml index 1f78d1d..19df8c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ "LongYinan ", "Boshen " ] -version = "1.0.1" +version = "1.0.2" edition = "2021" description = "Fast WHATWG Compliant URL parser" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index a3435a2..06674ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,25 @@ +//! # Ada URL +//! +//! Ada is a fast and spec-compliant URL parser written in C++. +//! - It's widely tested by both Web Platform Tests and Google OSS Fuzzer. +//! - It is extremely fast. +//! - It's the default URL parser of Node.js since Node 18.16.0. +//! - It supports Unicode Technical Standard. +//! +//! The Ada library passes the full range of tests from the specification, across a wide range +//! of platforms (e.g., Windows, Linux, macOS). +//! +//! ## Performance +//! +//! Ada is extremely fast. +//! For more information read our [benchmark page](https://ada-url.com/docs/performance). +//! +//! ```text +//! ada ▏ 188 ns/URL ███▏ +//! servo url ▏ 664 ns/URL ███████████▎ +//! CURL ▏ 1471 ns/URL █████████████████████████ +//! ``` + use thiserror::Error; pub mod ffi { @@ -160,6 +182,8 @@ impl Url { /// Returns whether or not the URL can be parsed or not. /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-canparse) + /// /// ``` /// use ada_url::Url; /// assert!(Url::can_parse("https://ada-url.github.io/ada", None)); @@ -180,6 +204,16 @@ impl Url { } } + /// Return the origin of this URL + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-origin) + /// + /// ``` + /// use ada_url::Url; + /// + /// let mut url = Url::parse("blob:https://example.com/foo", None).expect("Invalid URL"); + /// assert_eq!(url.origin(), "https://example.com"); + /// ``` pub fn origin(&mut self) -> &str { unsafe { let out = ffi::ada_get_origin(self.url); @@ -188,6 +222,8 @@ impl Url { } } + /// Return the parsed version of the URL with all components. + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-href) pub fn href(&self) -> &str { unsafe { ffi::ada_get_href(self.url) }.as_str() } @@ -196,6 +232,16 @@ impl Url { unsafe { ffi::ada_set_href(self.url, input.as_ptr().cast(), input.len()) } } + /// Return the username for this URL as a percent-encoded ASCII string. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-username) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("ftp://rms:secret123@example.com", None).expect("Invalid URL"); + /// assert_eq!(url.username(), "rms"); + /// ``` pub fn username(&self) -> &str { unsafe { ffi::ada_get_username(self.url) }.as_str() } @@ -204,6 +250,16 @@ impl Url { unsafe { ffi::ada_set_username(self.url, input.as_ptr().cast(), input.len()) } } + /// Return the password for this URL, if any, as a percent-encoded ASCII string. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-password) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("ftp://rms:secret123@example.com", None).expect("Invalid URL"); + /// assert_eq!(url.password(), "secret123"); + /// ``` pub fn password(&self) -> &str { unsafe { ffi::ada_get_password(self.url) }.as_str() } @@ -212,6 +268,19 @@ impl Url { unsafe { ffi::ada_set_password(self.url, input.as_ptr().cast(), input.len()) } } + /// Return the port number for this URL, or an empty string. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-port) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("https://example.com", None).expect("Invalid URL"); + /// assert_eq!(url.port(), ""); + /// + /// let url = Url::parse("https://example.com:8080", None).expect("Invalid URL"); + /// assert_eq!(url.port(), "8080"); + /// ``` pub fn port(&self) -> &str { unsafe { ffi::ada_get_port(self.url) }.as_str() } @@ -220,6 +289,23 @@ impl Url { unsafe { ffi::ada_set_port(self.url, input.as_ptr().cast(), input.len()) } } + /// Return this URL’s fragment identifier, or an empty string. + /// A fragment is the part of the URL with the # symbol. + /// The fragment is optional and, if present, contains a fragment identifier that identifies + /// a secondary resource, such as a section heading of a document. + /// In HTML, the fragment identifier is usually the id attribute of a an element that is + /// scrolled to on load. Browsers typically will not send the fragment portion of a URL to the + /// server. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-hash) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("https://example.com/data.csv#row=4", None).expect("Invalid URL"); + /// assert_eq!(url.hash(), "#row=4"); + /// assert!(url.has_hash()); + /// ``` pub fn hash(&self) -> &str { unsafe { ffi::ada_get_hash(self.url) }.as_str() } @@ -228,6 +314,16 @@ impl Url { unsafe { ffi::ada_set_hash(self.url, input.as_ptr().cast(), input.len()) } } + /// Return the parsed representation of the host for this URL with an optional port number. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-host) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("https://127.0.0.1:8080/index.html", None).expect("Invalid URL"); + /// assert_eq!(url.host(), "127.0.0.1:8080"); + /// ``` pub fn host(&self) -> &str { unsafe { ffi::ada_get_host(self.url) }.as_str() } @@ -236,6 +332,20 @@ impl Url { unsafe { ffi::ada_set_host(self.url, input.as_ptr().cast(), input.len()) } } + /// Return the parsed representation of the host for this URL. Non-ASCII domain labels are + /// punycode-encoded per IDNA if this is the host of a special URL, or percent encoded for + /// non-special URLs. + /// + /// Hostname does not contain port number. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-hostname) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("https://127.0.0.1:8080/index.html", None).expect("Invalid URL"); + /// assert_eq!(url.hostname(), "127.0.0.1"); + /// ``` pub fn hostname(&self) -> &str { unsafe { ffi::ada_get_hostname(self.url) }.as_str() } @@ -244,6 +354,16 @@ impl Url { unsafe { ffi::ada_set_hostname(self.url, input.as_ptr().cast(), input.len()) } } + /// Return the path for this URL, as a percent-encoded ASCII string. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-pathname) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("https://example.com/api/versions?page=2", None).expect("Invalid URL"); + /// assert_eq!(url.pathname(), "/api/versions"); + /// ``` pub fn pathname(&self) -> &str { unsafe { ffi::ada_get_pathname(self.url) }.as_str() } @@ -252,6 +372,19 @@ impl Url { unsafe { ffi::ada_set_pathname(self.url, input.as_ptr().cast(), input.len()) } } + /// Return this URL’s query string, if any, as a percent-encoded ASCII string. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-search) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("https://example.com/products?page=2", None).expect("Invalid URL"); + /// assert_eq!(url.search(), "?page=2"); + /// + /// let url = Url::parse("https://example.com/products", None).expect("Invalid URL"); + /// assert_eq!(url.search(), ""); + /// ``` pub fn search(&self) -> &str { unsafe { ffi::ada_get_search(self.url) }.as_str() } @@ -260,6 +393,16 @@ impl Url { unsafe { ffi::ada_set_search(self.url, input.as_ptr().cast(), input.len()) } } + /// Return the scheme of this URL, lower-cased, as an ASCII string with the ‘:’ delimiter. + /// + /// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-protocol) + /// + /// ``` + /// use ada_url::Url; + /// + /// let url = Url::parse("file:///tmp/foo", None).expect("Invalid URL"); + /// assert_eq!(url.protocol(), "file:"); + /// ``` pub fn protocol(&self) -> &str { unsafe { ffi::ada_get_protocol(self.url) }.as_str() }