diff --git a/ada_url/ada.cpp b/ada_url/ada.cpp index 72512a0..a3359af 100644 --- a/ada_url/ada.cpp +++ b/ada_url/ada.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2024-07-06 17:38:56 -0400. Do not edit! */ +/* auto-generated on 2024-08-24 20:20:43 -0400. Do not edit! */ /* begin file src/ada.cpp */ #include "ada.h" /* begin file src/checkers.cpp */ @@ -13830,7 +13830,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return "null"; } -[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_username"); if (has_non_empty_username()) { return helpers::substring(buffer, components.protocol_end + 2, @@ -13839,7 +13840,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return ""; } -[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_password"); if (has_non_empty_password()) { return helpers::substring(buffer, components.username_end + 1, @@ -13848,7 +13850,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return ""; } -[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_port"); if (components.port == url_components::omitted) { return ""; @@ -13857,7 +13860,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { components.pathname_start); } -[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_hash"); // If this's URL's fragment is either null or the empty string, then return // the empty string. Return U+0023 (#), followed by this's URL's fragment. @@ -13870,7 +13874,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, components.hash_start); } -[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_host"); // Technically, we should check if there is a hostname, but // the code below works even if there isn't. @@ -13888,7 +13893,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, start, components.pathname_start); } -[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_hostname"); // Technically, we should check if there is a hostname, but // the code below works even if there isn't. @@ -13902,7 +13908,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, start, components.host_end); } -[[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_pathname pathname_start = ", components.pathname_start, " buffer.size() = ", buffer.size(), " components.search_start = ", components.search_start, @@ -13916,7 +13923,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, components.pathname_start, ending_index); } -[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_search"); // If this's URL's query is either null or the empty string, then return the // empty string. Return U+003F (?), followed by this's URL's query. @@ -13933,7 +13941,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, components.search_start, ending_index); } -[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_protocol"); return helpers::substring(buffer, 0, components.protocol_end); } diff --git a/ada_url/ada.h b/ada_url/ada.h index 00ccd80..e1f6044 100644 --- a/ada_url/ada.h +++ b/ada_url/ada.h @@ -1,4 +1,4 @@ -/* auto-generated on 2024-07-06 17:38:56 -0400. Do not edit! */ +/* auto-generated on 2024-08-24 20:20:43 -0400. Do not edit! */ /* begin file include/ada.h */ /** * @file ada.h @@ -479,6 +479,18 @@ namespace ada { #define ADA_NEON 1 #endif +#ifndef __has_cpp_attribute +#define ada_lifetime_bound +#elif __has_cpp_attribute(msvc::lifetimebound) +#define ada_lifetime_bound [[msvc::lifetimebound]] +#elif __has_cpp_attribute(clang::lifetimebound) +#define ada_lifetime_bound [[clang::lifetimebound]] +#elif __has_cpp_attribute(lifetimebound) +#define ada_lifetime_bound [[lifetimebound]] +#else +#define ada_lifetime_bound +#endif + #endif // ADA_COMMON_DEFS_H /* end file include/ada/common_defs.h */ #include @@ -4845,35 +4857,38 @@ struct url_aggregator : url_base { * @see https://url.spec.whatwg.org/#dom-url-href * @see https://url.spec.whatwg.org/#concept-url-serializer */ - [[nodiscard]] inline std::string_view get_href() const noexcept; + [[nodiscard]] inline std::string_view get_href() const noexcept + ada_lifetime_bound; /** * The username getter steps are to return this's URL's username. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-username */ - [[nodiscard]] std::string_view get_username() const noexcept; + [[nodiscard]] std::string_view get_username() const noexcept + ada_lifetime_bound; /** * The password getter steps are to return this's URL's password. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-password */ - [[nodiscard]] std::string_view get_password() const noexcept; + [[nodiscard]] std::string_view get_password() const noexcept + ada_lifetime_bound; /** * Return this's URL's port, serialized. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-port */ - [[nodiscard]] std::string_view get_port() const noexcept; + [[nodiscard]] std::string_view get_port() const noexcept ada_lifetime_bound; /** * Return U+0023 (#), followed by this's URL's fragment. * This function does not allocate memory. * @return a lightweight std::string_view.. * @see https://url.spec.whatwg.org/#dom-url-hash */ - [[nodiscard]] std::string_view get_hash() const noexcept; + [[nodiscard]] std::string_view get_hash() const noexcept ada_lifetime_bound; /** * Return url's host, serialized, followed by U+003A (:) and url's port, * serialized. @@ -4882,7 +4897,7 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-host */ - [[nodiscard]] std::string_view get_host() const noexcept; + [[nodiscard]] std::string_view get_host() const noexcept ada_lifetime_bound; /** * Return this's URL's host, serialized. * This function does not allocate memory. @@ -4890,7 +4905,8 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-hostname */ - [[nodiscard]] std::string_view get_hostname() const noexcept; + [[nodiscard]] std::string_view get_hostname() const noexcept + ada_lifetime_bound; /** * The pathname getter steps are to return the result of URL path serializing * this's URL. @@ -4898,7 +4914,8 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-pathname */ - [[nodiscard]] std::string_view get_pathname() const noexcept; + [[nodiscard]] std::string_view get_pathname() const noexcept + ada_lifetime_bound; /** * Compute the pathname length in bytes without instantiating a view or a * string. @@ -4912,7 +4929,7 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-search */ - [[nodiscard]] std::string_view get_search() const noexcept; + [[nodiscard]] std::string_view get_search() const noexcept ada_lifetime_bound; /** * The protocol getter steps are to return this's URL's scheme, followed by * U+003A (:). @@ -4920,7 +4937,8 @@ struct url_aggregator : url_base { * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-protocol */ - [[nodiscard]] std::string_view get_protocol() const noexcept; + [[nodiscard]] std::string_view get_protocol() const noexcept + ada_lifetime_bound; /** * A URL includes credentials if its username or password is not the empty @@ -5828,7 +5846,7 @@ inline void url::set_scheme(std::string &&new_scheme) noexcept { type = ada::scheme::get_scheme_type(new_scheme); // We only move the 'scheme' if it is non-special. if (!is_special()) { - non_special_scheme = new_scheme; + non_special_scheme = std::move(new_scheme); } } @@ -5877,10 +5895,15 @@ inline void url::copy_scheme(const ada::url &u) { ada_really_inline size_t url::parse_port(std::string_view view, bool check_trailing_content) noexcept { ada_log("parse_port('", view, "') ", view.size()); + if (!view.empty() && view[0] == '-') { + ada_log("parse_port: view[0] == '0' && view.size() > 1"); + is_valid = false; + return 0; + } uint16_t parsed_port{}; auto r = std::from_chars(view.data(), view.data() + view.size(), parsed_port); if (r.ec == std::errc::result_out_of_range) { - ada_log("parse_port: std::errc::result_out_of_range"); + ada_log("parse_port: r.ec == std::errc::result_out_of_range"); is_valid = false; return 0; } @@ -6776,8 +6799,8 @@ inline bool url_aggregator::has_port() const noexcept { buffer[components.host_end + 1] == '.'; } -[[nodiscard]] inline std::string_view url_aggregator::get_href() - const noexcept { +[[nodiscard]] inline std::string_view url_aggregator::get_href() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_href"); return buffer; } @@ -6785,10 +6808,15 @@ inline bool url_aggregator::has_port() const noexcept { ada_really_inline size_t url_aggregator::parse_port( std::string_view view, bool check_trailing_content) noexcept { ada_log("url_aggregator::parse_port('", view, "') ", view.size()); + if (!view.empty() && view[0] == '-') { + ada_log("parse_port: view[0] == '0' && view.size() > 1"); + is_valid = false; + return 0; + } uint16_t parsed_port{}; auto r = std::from_chars(view.data(), view.data() + view.size(), parsed_port); if (r.ec == std::errc::result_out_of_range) { - ada_log("parse_port: std::errc::result_out_of_range"); + ada_log("parse_port: r.ec == std::errc::result_out_of_range"); is_valid = false; return 0; } @@ -7279,14 +7307,14 @@ url_search_params_entries_iter::next() { #ifndef ADA_ADA_VERSION_H #define ADA_ADA_VERSION_H -#define ADA_VERSION "2.9.0" +#define ADA_VERSION "2.9.1" namespace ada { enum { ADA_VERSION_MAJOR = 2, ADA_VERSION_MINOR = 9, - ADA_VERSION_REVISION = 0, + ADA_VERSION_REVISION = 1, }; } // namespace ada diff --git a/pyproject.toml b/pyproject.toml index 87cf638..1aa0771 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "ada-url" -version = "1.15.0" +version = "1.15.1" authors = [ {name = "Bo Bayles", email = "bo@bbayles.com"}, ] diff --git a/tests/files/urltestdata.json b/tests/files/urltestdata.json index 53f6d57..9dbe545 100644 --- a/tests/files/urltestdata.json +++ b/tests/files/urltestdata.json @@ -4849,21 +4849,6 @@ "search": "", "hash": "" }, - { - "input": "http://example.com/\uD800\uD801\uDFFE\uDFFF\uFDD0\uFDCF\uFDEF\uFDF0\uFFFE\uFFFF?\uD800\uD801\uDFFE\uDFFF\uFDD0\uFDCF\uFDEF\uFDF0\uFFFE\uFFFF", - "base": null, - "href": "http://example.com/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF", - "origin": "http://example.com", - "protocol": "http:", - "username": "", - "password": "", - "host": "example.com", - "hostname": "example.com", - "port": "", - "pathname": "/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF", - "search": "?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF", - "hash": "" - }, "Forbidden host code points", { "input": "sc://a\u0000b/", @@ -9658,6 +9643,201 @@ "search": "", "hash": "" }, + { + "input": "android://x:0/a", + "base": null, + "href": "android://x:0/a", + "origin": "null", + "protocol": "android:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "/a", + "search": "", + "hash": "" + }, + { + "input": "drivefs://x:0/a", + "base": null, + "href": "drivefs://x:0/a", + "origin": "null", + "protocol": "drivefs:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "/a", + "search": "", + "hash": "" + }, + { + "input": "chromeos-steam://x:0/a", + "base": null, + "href": "chromeos-steam://x:0/a", + "origin": "null", + "protocol": "chromeos-steam:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "/a", + "search": "", + "hash": "" + }, + { + "input": "steam://x:0/a", + "base": null, + "href": "steam://x:0/a", + "origin": "null", + "protocol": "steam:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "/a", + "search": "", + "hash": "" + }, + { + "input": "materialized-view://x:0/a", + "base": null, + "href": "materialized-view://x:0/a", + "origin": "null", + "protocol": "materialized-view:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "/a", + "search": "", + "hash": "" + }, + { + "input": "android-app://x:0", + "base": null, + "href": "android-app://x:0", + "origin": "null", + "protocol": "android-app:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, + { + "input": "chrome-distiller://x:0", + "base": null, + "href": "chrome-distiller://x:0", + "origin": "null", + "protocol": "chrome-distiller:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, + { + "input": "chrome-extension://x:0", + "base": null, + "href": "chrome-extension://x:0", + "origin": "null", + "protocol": "chrome-extension:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, + { + "input": "chrome-native://x:0", + "base": null, + "href": "chrome-native://x:0", + "origin": "null", + "protocol": "chrome-native:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, + { + "input": "chrome-resource://x:0", + "base": null, + "href": "chrome-resource://x:0", + "origin": "null", + "protocol": "chrome-resource:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, + { + "input": "chrome-search://x:0", + "base": null, + "href": "chrome-search://x:0", + "origin": "null", + "protocol": "chrome-search:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, + { + "input": "fuchsia-dir://x:0", + "base": null, + "href": "fuchsia-dir://x:0", + "origin": "null", + "protocol": "fuchsia-dir:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, + { + "input": "isolated-app://x:0", + "base": null, + "href": "isolated-app://x:0", + "origin": "null", + "protocol": "isolated-app:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, "Scheme relative path starting with multiple slashes", { "input": "///test",