From 0d9a3a60d67748fcd9eb8b484a161b169b721bcc Mon Sep 17 00:00:00 2001
From: Glyn Matthews <glyn.matthews@gmail.com>
Date: Sat, 8 May 2021 22:26:00 +0200
Subject: [PATCH 1/5] Added constexpr everywhere that there wasn't a compiler
 error

---
 include/skyr/v2/containers/static_vector.hpp     | 12 ++++++++++--
 include/skyr/v2/core/host.hpp                    | 14 +++++++-------
 include/skyr/v2/core/url_parser_context.hpp      | 12 ++++++------
 include/skyr/v2/core/url_record.hpp              |  6 +++---
 include/skyr/v2/domain/punycode.hpp              |  4 ++--
 include/skyr/v2/network/ipv4_address.hpp         |  2 +-
 .../v2/percent_encoding/percent_encoded_char.hpp | 16 ++++++++--------
 7 files changed, 37 insertions(+), 29 deletions(-)

diff --git a/include/skyr/v2/containers/static_vector.hpp b/include/skyr/v2/containers/static_vector.hpp
index 3be1359a..304cb256 100644
--- a/include/skyr/v2/containers/static_vector.hpp
+++ b/include/skyr/v2/containers/static_vector.hpp
@@ -10,6 +10,7 @@
 #include <array>
 #include <type_traits>
 #include <optional>
+#include <cassert>
 
 namespace skyr::inline v2 {
 ///
@@ -51,14 +52,15 @@ class static_vector {
   constexpr auto operator=(const static_vector &) -> static_vector & = default;
   constexpr auto operator=(static_vector &&) noexcept -> static_vector & = default;
 
-  ~static_vector() {
+  constexpr ~static_vector() {
     clear();
   }
 
   /// Gets the first const element in the vector
   /// \return a const T &
-  /// \pre `size() > 0`
+  /// \pre `size_ > 0`
   constexpr auto front() const noexcept -> const_reference {
+    assert(size() > 0);
     return impl_[0];
   }
 
@@ -66,6 +68,7 @@ class static_vector {
   /// \return a T &
   /// \pre `size() > 0`
   constexpr auto front() noexcept -> reference {
+    assert(size_ > 0);
     return impl_[0];
   }
 
@@ -73,6 +76,7 @@ class static_vector {
   /// \return
   /// \pre `size() > 0`
   constexpr auto back() const noexcept -> const_reference {
+    assert(size_ > 0);
     return impl_[size_ - 1];
   }
 
@@ -80,6 +84,7 @@ class static_vector {
   /// \return
   /// \pre `size() > 0`
   constexpr auto back() noexcept -> reference {
+    assert(size_ > 0);
     return impl_[size_ - 1];
   }
 
@@ -89,6 +94,7 @@ class static_vector {
   /// \pre `size() < capacity()`
   /// \post `size() > 0 && size() <= capacity()`
   constexpr auto push_back(const_reference value) noexcept -> reference {
+    assert(size_ < Capacity);
     impl_[size_++] = value;
     return impl_[size_ - 1];
   }
@@ -101,6 +107,7 @@ class static_vector {
   /// \post `size() > 0 && size() <= capacity()`
   template <class... Args>
   constexpr auto emplace_back(Args &&... args) noexcept(std::is_trivially_move_assignable_v<T>) -> reference {
+    assert(size_ < Capacity);
     impl_[size_++] = value_type{std::forward<Args>(args)...};
     return back();
   }
@@ -108,6 +115,7 @@ class static_vector {
   ///
   /// \pre `size() > 0`
   constexpr void pop_back() noexcept {
+    assert(size_ > 0);
     back().~value_type();
     --size_;
   }
diff --git a/include/skyr/v2/core/host.hpp b/include/skyr/v2/core/host.hpp
index 272828a4..671c37dc 100644
--- a/include/skyr/v2/core/host.hpp
+++ b/include/skyr/v2/core/host.hpp
@@ -86,7 +86,7 @@ class host {
 
   ///
   /// \return \c true if the host is a domain, \c false otherwise
-  [[nodiscard]] auto is_domain_name() const noexcept {
+  [[nodiscard]] constexpr auto is_domain_name() const noexcept {
     return std::holds_alternative<skyr::v2::domain_name>(host_);
   }
 
@@ -98,31 +98,31 @@ class host {
 
   ///
   /// \return \c true if the host is an IPv4 address, \c false otherwise
-  [[nodiscard]] auto is_ipv4_address() const noexcept {
+  [[nodiscard]] constexpr auto is_ipv4_address() const noexcept {
     return std::holds_alternative<skyr::v2::ipv4_address>(host_);
   }
 
   ///
   /// \return
-  [[nodiscard]] auto to_ipv4_address() const noexcept {
+  [[nodiscard]] constexpr auto to_ipv4_address() const noexcept {
     return is_ipv4_address() ? std::make_optional(std::get<skyr::v2::ipv4_address>(host_)) : std::nullopt;
   }
 
   ///
   /// \return \c true if the host is an IPv6 address, \c false otherwise
-  [[nodiscard]] auto is_ipv6_address() const noexcept {
+  [[nodiscard]] constexpr auto is_ipv6_address() const noexcept {
     return std::holds_alternative<skyr::v2::ipv6_address>(host_);
   }
 
   ///
   /// \return
-  [[nodiscard]] auto to_ipv6_address() const noexcept {
+  [[nodiscard]] constexpr auto to_ipv6_address() const noexcept {
     return is_ipv6_address() ? std::make_optional(std::get<skyr::v2::ipv6_address>(host_)) : std::nullopt;
   }
 
   ///
   /// \return \c true if the host is an opaque host, \c false otherwise
-  [[nodiscard]] auto is_opaque_host() const noexcept {
+  [[nodiscard]] constexpr auto is_opaque_host() const noexcept {
     return std::holds_alternative<skyr::v2::opaque_host>(host_);
   }
 
@@ -134,7 +134,7 @@ class host {
 
   ///
   /// \return
-  [[nodiscard]] auto is_empty() const noexcept {
+  [[nodiscard]] constexpr auto is_empty() const noexcept {
     return std::holds_alternative<empty_host>(host_);
   }
 
diff --git a/include/skyr/v2/core/url_parser_context.hpp b/include/skyr/v2/core/url_parser_context.hpp
index 0a93eea6..e2c6e8ef 100644
--- a/include/skyr/v2/core/url_parser_context.hpp
+++ b/include/skyr/v2/core/url_parser_context.hpp
@@ -27,12 +27,12 @@ using namespace std::string_literals;
 using namespace std::string_view_literals;
 
 namespace details {
-inline auto contains(std::string_view view, char element) noexcept {
+constexpr inline auto contains(std::string_view view, char element) noexcept {
   auto first = std::cbegin(view), last = std::cend(view);
   return last != std::find(first, last, element);
 }
 
-inline auto port_number(std::string_view port) noexcept -> tl::expected<std::uint16_t, url_parse_errc> {
+constexpr inline auto port_number(std::string_view port) noexcept -> tl::expected<std::uint16_t, url_parse_errc> {
   if (port.empty()) {
     return tl::make_unexpected(url_parse_errc::invalid_port);
   }
@@ -55,7 +55,7 @@ inline auto is_url_code_point(char byte) noexcept {
   return std::isalnum(byte, std::locale::classic()) || contains("!$&'()*+,-./:;=?@_~"sv, byte);
 }
 
-inline auto is_windows_drive_letter(std::string_view segment) noexcept {
+constexpr inline auto is_windows_drive_letter(std::string_view segment) noexcept {
   if (segment.size() < 2) {
     return false;
   }
@@ -73,17 +73,17 @@ inline auto is_windows_drive_letter(std::string_view segment) noexcept {
   return result;
 }
 
-inline auto is_single_dot_path_segment(std::string_view segment) noexcept {
+constexpr inline auto is_single_dot_path_segment(std::string_view segment) noexcept {
   return (segment == ".") || (segment == "%2e") || (segment == "%2E");
 }
 
-inline auto is_double_dot_path_segment(std::string_view segment) noexcept {
+constexpr inline auto is_double_dot_path_segment(std::string_view segment) noexcept {
   return (segment == "..") || (segment == "%2e.") || (segment == ".%2e") || (segment == "%2e%2e") ||
          (segment == "%2E.") || (segment == ".%2E") || (segment == "%2E%2E") || (segment == "%2E%2e") ||
          (segment == "%2e%2E");
 }
 
-inline void shorten_path(std::string_view scheme, std::vector<std::string> &path) {
+constexpr inline void shorten_path(std::string_view scheme, std::vector<std::string> &path) {
   if (!path.empty() && !((scheme == "file"sv) && (path.size() == 1) && is_windows_drive_letter(path.front()))) {
     path.pop_back();
   }
diff --git a/include/skyr/v2/core/url_record.hpp b/include/skyr/v2/core/url_record.hpp
index afebe96b..e14d19b5 100644
--- a/include/skyr/v2/core/url_record.hpp
+++ b/include/skyr/v2/core/url_record.hpp
@@ -50,21 +50,21 @@ class url_record {
   /// Tests if the URL is a special scheme
   /// \returns `true` if the URL scheme is a special scheme, `false`
   ///          otherwise
-  [[nodiscard]] auto is_special() const noexcept -> bool {
+  [[nodiscard]] constexpr auto is_special() const noexcept -> bool {
     return skyr::is_special(scheme);
   }
 
   /// Tests if the URL includes credentials
   /// \returns `true` if the URL username or password is not an
   ///          empty string, `false` otherwise
-  [[nodiscard]] auto includes_credentials() const noexcept -> bool {
+  [[nodiscard]] constexpr auto includes_credentials() const noexcept -> bool {
     return !username.empty() || !password.empty();
   }
 
   /// Tests if the URL cannot have a username, password or port
   /// \returns `true` if the URL cannot have a username, password
   ///          or port
-  [[nodiscard]] auto cannot_have_a_username_password_or_port() const noexcept -> bool {
+  [[nodiscard]] constexpr auto cannot_have_a_username_password_or_port() const noexcept -> bool {
     return (!host || host.value().is_empty()) || cannot_be_a_base_url || (scheme == "file");
   }
 
diff --git a/include/skyr/v2/domain/punycode.hpp b/include/skyr/v2/domain/punycode.hpp
index ea5d0799..f48edcf9 100644
--- a/include/skyr/v2/domain/punycode.hpp
+++ b/include/skyr/v2/domain/punycode.hpp
@@ -50,7 +50,7 @@ constexpr inline auto adapt(uint32_t delta, uint32_t numpoints, bool firsttime)
 /// \param input A UTF-32 encoded domain
 /// \param output An ascii string on output
 /// \returns `void` or an error
-inline auto punycode_encode(std::u32string_view input, std::string *output) -> tl::expected<void, domain_errc> {
+constexpr inline auto punycode_encode(std::u32string_view input, std::string *output) -> tl::expected<void, domain_errc> {
   using namespace punycode::constants;
 
   constexpr auto is_ascii_value = [] (auto c) { return c < 0x80; };
@@ -138,7 +138,7 @@ inline auto punycode_encode(std::u32string_view input, std::string *output) -> t
 /// \param input An ASCII encoded domain to be decoded
 /// \returns The decoded UTF-8 domain, or an error
 template <class StringView>
-inline auto punycode_decode(StringView input, std::u32string *output) -> tl::expected<void, domain_errc> {
+constexpr inline auto punycode_decode(StringView input, std::u32string *output) -> tl::expected<void, domain_errc> {
   using namespace punycode::constants;
 
   // decode_digit(cp) returns the numeric value of a basic code
diff --git a/include/skyr/v2/network/ipv4_address.hpp b/include/skyr/v2/network/ipv4_address.hpp
index 36e309f9..efdd5301 100644
--- a/include/skyr/v2/network/ipv4_address.hpp
+++ b/include/skyr/v2/network/ipv4_address.hpp
@@ -108,7 +108,7 @@ constexpr inline auto parse_ipv4_number(std::string_view input, bool *validation
 /// Parses an IPv4 address
 /// \param input An input string
 /// \returns An `ipv4_address` object or an error
-inline auto parse_ipv4_address(std::string_view input, bool *validation_error)
+constexpr inline auto parse_ipv4_address(std::string_view input, bool *validation_error)
     -> tl::expected<ipv4_address, ipv4_address_errc> {
   using namespace std::string_view_literals;
 
diff --git a/include/skyr/v2/percent_encoding/percent_encoded_char.hpp b/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
index ce119387..bb16afcf 100644
--- a/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
+++ b/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
@@ -172,49 +172,49 @@ struct percent_encoded_char {
 
   ///
   /// \return
-  [[nodiscard]] auto cbegin() const noexcept {
+  [[nodiscard]] constexpr auto cbegin() const noexcept {
     return impl_.cbegin();
   }
 
   ///
   /// \return
-  [[nodiscard]] auto cend() const noexcept {
+  [[nodiscard]] constexpr auto cend() const noexcept {
     return impl_.cend();
   }
 
   ///
   /// \return
-  [[nodiscard]] auto begin() const noexcept {
+  [[nodiscard]] constexpr auto begin() const noexcept {
     return cbegin();
   }
 
   ///
   /// \return
-  [[nodiscard]] auto end() const noexcept {
+  [[nodiscard]] constexpr auto end() const noexcept {
     return cend();
   }
 
   ///
   /// \return
-  [[nodiscard]] auto size() const noexcept {
+  [[nodiscard]] constexpr auto size() const noexcept {
     return impl_.size();
   }
 
   ///
   /// \return
-  [[nodiscard]] auto is_encoded() const noexcept {
+  [[nodiscard]] constexpr auto is_encoded() const noexcept {
     return impl_.size() == 3;
   }
 
   ///
   /// \return
-  [[nodiscard]] auto to_string() const & -> std::string {
+  [[nodiscard]] constexpr auto to_string() const & -> const std::string & {
     return impl_;
   }
 
   ///
   /// \return
-  [[nodiscard]] auto to_string() && noexcept -> std::string && {
+  [[nodiscard]] constexpr auto to_string() && noexcept -> std::string && {
     return std::move(impl_);
   }
 

From d23aedf164e14ff09179a65f87ef0d8d21775c29 Mon Sep 17 00:00:00 2001
From: Glyn Matthews <glyn.matthews@gmail.com>
Date: Sat, 8 May 2021 22:54:46 +0200
Subject: [PATCH 2/5] Removed some constexpr where there are CI failures

---
 include/skyr/v2/domain/punycode.hpp                       | 2 +-
 include/skyr/v2/percent_encoding/percent_encoded_char.hpp | 8 ++++----
 src/v1/url/url.cpp                                        | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/skyr/v2/domain/punycode.hpp b/include/skyr/v2/domain/punycode.hpp
index f48edcf9..640ddd34 100644
--- a/include/skyr/v2/domain/punycode.hpp
+++ b/include/skyr/v2/domain/punycode.hpp
@@ -50,7 +50,7 @@ constexpr inline auto adapt(uint32_t delta, uint32_t numpoints, bool firsttime)
 /// \param input A UTF-32 encoded domain
 /// \param output An ascii string on output
 /// \returns `void` or an error
-constexpr inline auto punycode_encode(std::u32string_view input, std::string *output) -> tl::expected<void, domain_errc> {
+inline auto punycode_encode(std::u32string_view input, std::string *output) -> tl::expected<void, domain_errc> {
   using namespace punycode::constants;
 
   constexpr auto is_ascii_value = [] (auto c) { return c < 0x80; };
diff --git a/include/skyr/v2/percent_encoding/percent_encoded_char.hpp b/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
index bb16afcf..c37110f8 100644
--- a/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
+++ b/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
@@ -172,25 +172,25 @@ struct percent_encoded_char {
 
   ///
   /// \return
-  [[nodiscard]] constexpr auto cbegin() const noexcept {
+  [[nodiscard]] auto cbegin() const noexcept {
     return impl_.cbegin();
   }
 
   ///
   /// \return
-  [[nodiscard]] constexpr auto cend() const noexcept {
+  [[nodiscard]] auto cend() const noexcept {
     return impl_.cend();
   }
 
   ///
   /// \return
-  [[nodiscard]] constexpr auto begin() const noexcept {
+  [[nodiscard]] auto begin() const noexcept {
     return cbegin();
   }
 
   ///
   /// \return
-  [[nodiscard]] constexpr auto end() const noexcept {
+  [[nodiscard]] auto end() const noexcept {
     return cend();
   }
 
diff --git a/src/v1/url/url.cpp b/src/v1/url/url.cpp
index b820de1c..4052d1a7 100644
--- a/src/v1/url/url.cpp
+++ b/src/v1/url/url.cpp
@@ -17,7 +17,7 @@ void url::initialize(string_view input, const url_record *base) {
 
   bool validation_error = false;
   details::parse(input, &validation_error, base)
-      .and_then([=](auto &&url) -> result_type {
+      .and_then([this](auto &&url) -> result_type {
         update_record(std::forward<url_record>(url));
         return {};
       })

From b3d61dde3085c6f53eb41e66af7148fbd2cab6cd Mon Sep 17 00:00:00 2001
From: Glyn Matthews <glyn.matthews@gmail.com>
Date: Sat, 8 May 2021 23:49:54 +0200
Subject: [PATCH 3/5] Removed some constexpr where there are CI failures

---
 include/skyr/v2/core/url_parser_context.hpp               | 2 +-
 include/skyr/v2/core/url_record.hpp                       | 2 +-
 include/skyr/v2/percent_encoding/percent_encoded_char.hpp | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/skyr/v2/core/url_parser_context.hpp b/include/skyr/v2/core/url_parser_context.hpp
index e2c6e8ef..a4864826 100644
--- a/include/skyr/v2/core/url_parser_context.hpp
+++ b/include/skyr/v2/core/url_parser_context.hpp
@@ -83,7 +83,7 @@ constexpr inline auto is_double_dot_path_segment(std::string_view segment) noexc
          (segment == "%2e%2E");
 }
 
-constexpr inline void shorten_path(std::string_view scheme, std::vector<std::string> &path) {
+inline void shorten_path(std::string_view scheme, std::vector<std::string> &path) {
   if (!path.empty() && !((scheme == "file"sv) && (path.size() == 1) && is_windows_drive_letter(path.front()))) {
     path.pop_back();
   }
diff --git a/include/skyr/v2/core/url_record.hpp b/include/skyr/v2/core/url_record.hpp
index e14d19b5..d197a609 100644
--- a/include/skyr/v2/core/url_record.hpp
+++ b/include/skyr/v2/core/url_record.hpp
@@ -57,7 +57,7 @@ class url_record {
   /// Tests if the URL includes credentials
   /// \returns `true` if the URL username or password is not an
   ///          empty string, `false` otherwise
-  [[nodiscard]] constexpr auto includes_credentials() const noexcept -> bool {
+  [[nodiscard]] auto includes_credentials() const noexcept -> bool {
     return !username.empty() || !password.empty();
   }
 
diff --git a/include/skyr/v2/percent_encoding/percent_encoded_char.hpp b/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
index c37110f8..1101f1d2 100644
--- a/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
+++ b/include/skyr/v2/percent_encoding/percent_encoded_char.hpp
@@ -196,13 +196,13 @@ struct percent_encoded_char {
 
   ///
   /// \return
-  [[nodiscard]] constexpr auto size() const noexcept {
+  [[nodiscard]] auto size() const noexcept {
     return impl_.size();
   }
 
   ///
   /// \return
-  [[nodiscard]] constexpr auto is_encoded() const noexcept {
+  [[nodiscard]] auto is_encoded() const noexcept {
     return impl_.size() == 3;
   }
 

From e26a2e658f177977eea3ddf1b0e36a3f8fc29dd7 Mon Sep 17 00:00:00 2001
From: Glyn Matthews <glyn.matthews@gmail.com>
Date: Sun, 9 May 2021 00:06:32 +0200
Subject: [PATCH 4/5] Removed some constexpr where there are CI failures

---
 include/skyr/v2/core/url_parser_context.hpp | 4 ++--
 include/skyr/v2/core/url_record.hpp         | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/skyr/v2/core/url_parser_context.hpp b/include/skyr/v2/core/url_parser_context.hpp
index a4864826..b30275e5 100644
--- a/include/skyr/v2/core/url_parser_context.hpp
+++ b/include/skyr/v2/core/url_parser_context.hpp
@@ -32,13 +32,13 @@ constexpr inline auto contains(std::string_view view, char element) noexcept {
   return last != std::find(first, last, element);
 }
 
-constexpr inline auto port_number(std::string_view port) noexcept -> tl::expected<std::uint16_t, url_parse_errc> {
+inline auto port_number(std::string_view port) noexcept -> tl::expected<std::uint16_t, url_parse_errc> {
   if (port.empty()) {
     return tl::make_unexpected(url_parse_errc::invalid_port);
   }
 
   const char *port_first = port.data();
-  char *port_last = nullptr;
+  char *port_last = nullptr; // NOLINT
   auto port_value = std::strtoul(port_first, &port_last, 10);
 
   if (port_first == port_last) {
diff --git a/include/skyr/v2/core/url_record.hpp b/include/skyr/v2/core/url_record.hpp
index d197a609..afebe96b 100644
--- a/include/skyr/v2/core/url_record.hpp
+++ b/include/skyr/v2/core/url_record.hpp
@@ -50,7 +50,7 @@ class url_record {
   /// Tests if the URL is a special scheme
   /// \returns `true` if the URL scheme is a special scheme, `false`
   ///          otherwise
-  [[nodiscard]] constexpr auto is_special() const noexcept -> bool {
+  [[nodiscard]] auto is_special() const noexcept -> bool {
     return skyr::is_special(scheme);
   }
 
@@ -64,7 +64,7 @@ class url_record {
   /// Tests if the URL cannot have a username, password or port
   /// \returns `true` if the URL cannot have a username, password
   ///          or port
-  [[nodiscard]] constexpr auto cannot_have_a_username_password_or_port() const noexcept -> bool {
+  [[nodiscard]] auto cannot_have_a_username_password_or_port() const noexcept -> bool {
     return (!host || host.value().is_empty()) || cannot_be_a_base_url || (scheme == "file");
   }
 

From 29a72695ac0752212291bd7da36ee7cc1d298067 Mon Sep 17 00:00:00 2001
From: Glyn Matthews <glyn.matthews@gmail.com>
Date: Sun, 9 May 2021 00:31:04 +0200
Subject: [PATCH 5/5] Removed some constexpr where there are CI failures

---
 .github/workflows/skyr-url-ci.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.github/workflows/skyr-url-ci.yml b/.github/workflows/skyr-url-ci.yml
index a5cd7813..1d5f22a1 100644
--- a/.github/workflows/skyr-url-ci.yml
+++ b/.github/workflows/skyr-url-ci.yml
@@ -476,8 +476,6 @@ jobs:
           set(BUILD_V2 OFF)
           if ("${{ matrix.config.name }}" STREQUAL "Windows MSVC 2019 Debug (C++20)" OR
               "${{ matrix.config.name }}" STREQUAL "Windows MSVC 2019 Release (C++20)" OR
-              "${{ matrix.config.name }}" STREQUAL "Linux GCC 10 Debug (C++20)" OR
-              "${{ matrix.config.name }}" STREQUAL "Linux GCC 10 Release (C++20)" OR
               "${{ matrix.config.name }}" STREQUAL "Linux GCC 11 Debug (C++20)" OR
               "${{ matrix.config.name }}" STREQUAL "Linux GCC 11 Release (C++20)" OR
               "${{ matrix.config.name }}" STREQUAL "Linux Clang 11 Debug (C++20)" OR
