aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.uuid
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-07-02 03:28:45 +0100
committerLexi Winter <lexi@le-fay.org>2025-07-02 03:28:45 +0100
commit712edacbc75e6dc98c11b3c5f6c52f823c747e2f (patch)
tree1cd3710635e0ec27d12845d21ef774102d13b938 /nihil.uuid
parenta4607e29540a9352c35afff17193ceeab137cc9d (diff)
downloadnihil-712edacbc75e6dc98c11b3c5f6c52f823c747e2f.tar.gz
nihil-712edacbc75e6dc98c11b3c5f6c52f823c747e2f.tar.bz2
move uuid to util
Diffstat (limited to 'nihil.uuid')
-rw-r--r--nihil.uuid/CMakeLists.txt22
-rw-r--r--nihil.uuid/test.cc923
-rw-r--r--nihil.uuid/uuid.ccm768
3 files changed, 0 insertions, 1713 deletions
diff --git a/nihil.uuid/CMakeLists.txt b/nihil.uuid/CMakeLists.txt
deleted file mode 100644
index a210322..0000000
--- a/nihil.uuid/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-# This source code is released into the public domain.
-
-add_library(nihil.uuid STATIC)
-target_link_libraries(nihil.uuid PRIVATE nihil.std)
-target_sources(nihil.uuid
- PUBLIC FILE_SET modules TYPE CXX_MODULES FILES
- uuid.ccm
-)
-
-if(NIHIL_TESTS)
- enable_testing()
-
- add_executable(nihil.uuid.test test.cc)
- target_link_libraries(nihil.uuid.test PRIVATE
- nihil.uuid
- Catch2::Catch2WithMain
- )
-
- include(CTest)
- include(Catch)
- catch_discover_tests(nihil.uuid.test)
-endif()
diff --git a/nihil.uuid/test.cc b/nihil.uuid/test.cc
deleted file mode 100644
index 551c491..0000000
--- a/nihil.uuid/test.cc
+++ /dev/null
@@ -1,923 +0,0 @@
-/*
- * From https://github.com/mariusbancila/stduuid
- *
- * Copyright (c) 2017
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <catch2/catch_test_macros.hpp>
-
-import nihil.std;
-import nihil.uuid;
-
-// NOLINTBEGIN(bugprone-unchecked-optional-access)
-
-namespace {
-// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0205r0.html
-template <typename EngineT, std::size_t StateSize = EngineT::state_size>
-void seed_rng(EngineT &engine)
-{
- using engine_type = typename EngineT::result_type;
- using device_type = std::random_device::result_type;
- using seedseq_type = std::seed_seq::result_type;
-
- constexpr auto bytes_needed = StateSize * sizeof(engine_type);
- constexpr auto numbers_needed = (sizeof(device_type) < sizeof(seedseq_type))
- ? (bytes_needed / sizeof(device_type))
- : (bytes_needed / sizeof(seedseq_type));
-
- auto numbers = std::array<device_type, numbers_needed>{};
- auto rnddev = std::random_device{};
- std::ranges::generate(numbers, std::ref(rnddev));
-
- auto seedseq = std::seed_seq(std::cbegin(numbers), std::cend(numbers));
- engine.seed(seedseq);
-}
-
-using namespace nihil;
-
-TEST_CASE("uuid: Test multiple default generators", "[uuid]")
-{
- uuid id1;
- uuid id2;
-
- {
- std::random_device rd;
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- id1 = uuid_random_generator{generator}();
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::random_number_based);
- REQUIRE(id1.variant() == uuid_variant::rfc);
- }
-
- {
- std::random_device rd;
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- id2 = uuid_random_generator{generator}();
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::random_number_based);
- REQUIRE(id2.variant() == uuid_variant::rfc);
- }
-
- REQUIRE(id1 != id2);
-}
-
-TEST_CASE("uuid: Test default generator", "[uuid]")
-{
- std::random_device rd;
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- uuid const guid = uuid_random_generator{generator}();
- REQUIRE(!guid.is_nil());
- REQUIRE(guid.version() == uuid_version::random_number_based);
- REQUIRE(guid.variant() == uuid_variant::rfc);
-}
-
-TEST_CASE("uuid: Test random generator (conversion ctor w/ smart ptr)", "[uuid]")
-{
- std::random_device rd;
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- uuid_random_generator dgen(&generator);
- auto id1 = dgen();
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::random_number_based);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen();
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::random_number_based);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
-}
-
-TEST_CASE("uuid: Test random generator (conversion ctor w/ ptr)", "[uuid]")
-{
- std::random_device rd;
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- auto generator = std::make_unique<std::mt19937>(seq);
-
- uuid_random_generator dgen(generator.get());
- auto id1 = dgen();
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::random_number_based);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen();
- REQUIRE(!id1.is_nil());
- REQUIRE(id2.version() == uuid_version::random_number_based);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
-}
-
-TEST_CASE("uuid: Test random generator (conversion ctor w/ ref)", "[uuid]")
-{
- std::random_device rd;
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- uuid_random_generator dgen(generator);
- auto id1 = dgen();
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::random_number_based);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen();
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::random_number_based);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
-}
-
-TEST_CASE("uuid: Test basic random generator (conversion ctor w/ ptr) "
- "w/ ranlux48_base",
- "[uuid]")
-{
- std::random_device rd;
- auto seed_data = std::array<int, 6>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::ranlux48_base generator(seq);
-
- basic_uuid_random_generator<std::ranlux48_base> dgen(&generator);
- auto id1 = dgen();
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::random_number_based);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen();
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::random_number_based);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
-}
-
-TEST_CASE("uuid: Test basic random generator (conversion ctor w/ smart ptr) "
- "w/ ranlux48_base",
- "[uuid]")
-{
- std::random_device rd;
- auto seed_data = std::array<int, 6>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- auto generator = std::make_unique<std::ranlux48_base>(seq);
-
- basic_uuid_random_generator<std::ranlux48_base> dgen(generator.get());
- auto id1 = dgen();
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::random_number_based);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen();
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::random_number_based);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
-}
-
-TEST_CASE("uuid: Test basic random generator (conversion ctor w/ ref) "
- "w/ ranlux48_base",
- "[uuid]")
-{
- std::random_device rd;
- auto seed_data = std::array<int, 6>{};
- std::ranges::generate(seed_data, std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::ranlux48_base generator(seq);
-
- basic_uuid_random_generator<std::ranlux48_base> dgen(generator);
- auto id1 = dgen();
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::random_number_based);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen();
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::random_number_based);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
-}
-
-TEST_CASE("uuid: Test namespaces", "[uuid]")
-{
- REQUIRE(uuid_namespace_dns == uuid::from_string("6ba7b810-9dad-11d1-80b4-00c04fd430c8"));
- REQUIRE(uuid_namespace_url == uuid::from_string("6ba7b811-9dad-11d1-80b4-00c04fd430c8"));
- REQUIRE(uuid_namespace_oid == uuid::from_string("6ba7b812-9dad-11d1-80b4-00c04fd430c8"));
- REQUIRE(uuid_namespace_x500 == uuid::from_string("6ba7b814-9dad-11d1-80b4-00c04fd430c8"));
-}
-
-TEST_CASE("uuid: Test name generator (char*)", "[uuid]")
-{
- uuid_name_generator dgen(uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43").value());
-
- auto id1 = dgen("john");
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::name_based_sha1);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen("jane");
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::name_based_sha1);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- auto id3 = dgen("jane");
- REQUIRE(!id3.is_nil());
- REQUIRE(id3.version() == uuid_version::name_based_sha1);
- REQUIRE(id3.variant() == uuid_variant::rfc);
-
- auto id4 = dgen(L"jane");
- REQUIRE(!id4.is_nil());
- REQUIRE(id4.version() == uuid_version::name_based_sha1);
- REQUIRE(id4.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
- REQUIRE(id2 == id3);
- REQUIRE(id3 != id4);
-}
-
-TEST_CASE("uuid: Test name generator (std::string)", "[uuid]")
-{
- using namespace std::string_literals;
-
- uuid_name_generator dgen(uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43").value());
- auto id1 = dgen("john"s);
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::name_based_sha1);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen("jane"s);
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::name_based_sha1);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- auto id3 = dgen("jane"s);
- REQUIRE(!id3.is_nil());
- REQUIRE(id3.version() == uuid_version::name_based_sha1);
- REQUIRE(id3.variant() == uuid_variant::rfc);
-
- auto id4 = dgen(L"jane"s);
- REQUIRE(!id4.is_nil());
- REQUIRE(id4.version() == uuid_version::name_based_sha1);
- REQUIRE(id4.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
- REQUIRE(id2 == id3);
- REQUIRE(id3 != id4);
-}
-
-TEST_CASE("uuid: Test name generator (std::string_view)", "[uuid]")
-{
- using namespace std::string_view_literals;
-
- uuid_name_generator dgen(uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43").value());
- auto id1 = dgen("john"sv);
- REQUIRE(!id1.is_nil());
- REQUIRE(id1.version() == uuid_version::name_based_sha1);
- REQUIRE(id1.variant() == uuid_variant::rfc);
-
- auto id2 = dgen("jane"sv);
- REQUIRE(!id2.is_nil());
- REQUIRE(id2.version() == uuid_version::name_based_sha1);
- REQUIRE(id2.variant() == uuid_variant::rfc);
-
- auto id3 = dgen("jane"sv);
- REQUIRE(!id3.is_nil());
- REQUIRE(id3.version() == uuid_version::name_based_sha1);
- REQUIRE(id3.variant() == uuid_variant::rfc);
-
- auto id4 = dgen(L"jane"sv);
- REQUIRE(!id4.is_nil());
- REQUIRE(id4.version() == uuid_version::name_based_sha1);
- REQUIRE(id4.variant() == uuid_variant::rfc);
-
- REQUIRE(id1 != id2);
- REQUIRE(id2 == id3);
- REQUIRE(id3 != id4);
-}
-
-TEST_CASE("uuid: Test name generator equality (char const*, std::string, "
- "std::string_view)",
- "[uuid]")
-{
- using namespace std::literals;
-
- auto dgen = uuid_name_generator(
- uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43").value());
- auto id1 = dgen("john");
- auto id2 = dgen("john"s);
- auto id3 = dgen("john"sv);
-
- REQUIRE(id1 == id2);
- REQUIRE(id2 == id3);
-}
-
-TEST_CASE("uuid: Test default constructor", "[uuid]")
-{
- auto empty = uuid();
- REQUIRE(empty.is_nil());
-}
-
-TEST_CASE("uuid: Test string conversion", "[uuid]")
-{
- auto empty = uuid();
- REQUIRE(to_string(empty) == "00000000-0000-0000-0000-000000000000");
- REQUIRE(to_string<wchar_t>(empty) == L"00000000-0000-0000-0000-000000000000");
-}
-
-TEST_CASE("uuid: Test is_valid_uuid(char*)", "[uuid]")
-{
- REQUIRE(uuid::is_valid_uuid("47183823-2574-4bfd-b411-99ed177d3e43"));
- REQUIRE(uuid::is_valid_uuid("{47183823-2574-4bfd-b411-99ed177d3e43}"));
- REQUIRE(uuid::is_valid_uuid(L"47183823-2574-4bfd-b411-99ed177d3e43"));
- REQUIRE(uuid::is_valid_uuid(L"{47183823-2574-4bfd-b411-99ed177d3e43}"));
- REQUIRE(uuid::is_valid_uuid("00000000-0000-0000-0000-000000000000"));
- REQUIRE(uuid::is_valid_uuid("{00000000-0000-0000-0000-000000000000}"));
- REQUIRE(uuid::is_valid_uuid(L"00000000-0000-0000-0000-000000000000"));
- REQUIRE(uuid::is_valid_uuid(L"{00000000-0000-0000-0000-000000000000}"));
-}
-
-TEST_CASE("uuid: Test is_valid_uuid(basic_string)", "[uuid]")
-{
- using namespace std::string_literals;
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e43"s;
- REQUIRE(uuid::is_valid_uuid(str));
- }
-
- {
- auto str = "{47183823-2574-4bfd-b411-99ed177d3e43}"s;
- REQUIRE(uuid::is_valid_uuid(str));
- }
-
- {
- auto str = L"47183823-2574-4bfd-b411-99ed177d3e43"s;
- REQUIRE(uuid::is_valid_uuid(str));
- }
-
- {
- auto str = L"{47183823-2574-4bfd-b411-99ed177d3e43}"s;
- REQUIRE(uuid::is_valid_uuid(str));
- }
-
- {
- auto str = "00000000-0000-0000-0000-000000000000"s;
- REQUIRE(uuid::is_valid_uuid(str));
- }
-
- {
- auto str = "{00000000-0000-0000-0000-000000000000}"s;
- REQUIRE(uuid::is_valid_uuid(str));
- }
-
- {
- auto str = L"00000000-0000-0000-0000-000000000000"s;
- REQUIRE(uuid::is_valid_uuid(str));
- }
-
- {
- auto str = L"{00000000-0000-0000-0000-000000000000}"s;
- REQUIRE(uuid::is_valid_uuid(str));
- }
-}
-
-TEST_CASE("uuid: Test is_valid_uuid(basic_string_view)", "[uuid]")
-{
- using namespace std::string_view_literals;
-
- REQUIRE(uuid::is_valid_uuid("47183823-2574-4bfd-b411-99ed177d3e43"sv));
- REQUIRE(uuid::is_valid_uuid("{47183823-2574-4bfd-b411-99ed177d3e43}"sv));
- REQUIRE(uuid::is_valid_uuid(L"47183823-2574-4bfd-b411-99ed177d3e43"sv));
- REQUIRE(uuid::is_valid_uuid(L"{47183823-2574-4bfd-b411-99ed177d3e43}"sv));
- REQUIRE(uuid::is_valid_uuid("00000000-0000-0000-0000-000000000000"sv));
- REQUIRE(uuid::is_valid_uuid("{00000000-0000-0000-0000-000000000000}"sv));
- REQUIRE(uuid::is_valid_uuid(L"00000000-0000-0000-0000-000000000000"sv));
- REQUIRE(uuid::is_valid_uuid(L"{00000000-0000-0000-0000-000000000000}"sv));
-}
-
-TEST_CASE("uuid: Test is_valid_uuid(char*) invalid format", "[uuid]")
-{
- REQUIRE(!uuid::is_valid_uuid(""));
- REQUIRE(!uuid::is_valid_uuid("{}"));
- REQUIRE(!uuid::is_valid_uuid("47183823-2574-4bfd-b411-99ed177d3e4"));
- REQUIRE(!uuid::is_valid_uuid("47183823-2574-4bfd-b411-99ed177d3e430"));
- REQUIRE(!uuid::is_valid_uuid("{47183823-2574-4bfd-b411-99ed177d3e43"));
- REQUIRE(!uuid::is_valid_uuid("47183823-2574-4bfd-b411-99ed177d3e43}"));
-}
-
-TEST_CASE("uuid: Test is_valid_uuid(basic_string) invalid format", "[uuid]")
-{
- using namespace std::string_literals;
-
- {
- auto str = ""s;
- REQUIRE(!uuid::is_valid_uuid(str));
- }
-
- {
- auto str = "{}"s;
- REQUIRE(!uuid::is_valid_uuid(str));
- }
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e4"s;
- REQUIRE(!uuid::is_valid_uuid(str));
- }
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e430"s;
- REQUIRE(!uuid::is_valid_uuid(str));
- }
-
- {
- auto str = "{47183823-2574-4bfd-b411-99ed177d3e43"s;
- REQUIRE(!uuid::is_valid_uuid(str));
- }
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e43}"s;
- REQUIRE(!uuid::is_valid_uuid(str));
- }
-}
-
-TEST_CASE("uuid: Test is_valid_uuid(basic_string_view) invalid format", "[uuid]")
-{
- using namespace std::string_view_literals;
-
- REQUIRE(!uuid::is_valid_uuid(""sv));
- REQUIRE(!uuid::is_valid_uuid("{}"sv));
- REQUIRE(!uuid::is_valid_uuid("47183823-2574-4bfd-b411-99ed177d3e4"sv));
- REQUIRE(!uuid::is_valid_uuid("47183823-2574-4bfd-b411-99ed177d3e430"sv));
- REQUIRE(!uuid::is_valid_uuid("{47183823-2574-4bfd-b411-99ed177d3e43"sv));
- REQUIRE(!uuid::is_valid_uuid("47183823-2574-4bfd-b411-99ed177d3e43}"sv));
-}
-
-TEST_CASE("uuid: Test from_string(char*)", "[uuid]")
-{
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e43";
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string(guid) == str);
- }
-
- {
- auto str = "{47183823-2574-4bfd-b411-99ed177d3e43}";
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43");
- }
-
- {
- auto guid = uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43").value();
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43");
- REQUIRE(to_string<wchar_t>(guid) == L"47183823-2574-4bfd-b411-99ed177d3e43");
- }
-
- {
- auto str = L"47183823-2574-4bfd-b411-99ed177d3e43";
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string<wchar_t>(guid) == str);
- }
-
- {
- auto str = "4718382325744bfdb41199ed177d3e43";
- REQUIRE_NOTHROW(uuid::from_string(str));
- REQUIRE(uuid::from_string(str).has_value());
- }
-
- {
- auto str = "00000000-0000-0000-0000-000000000000";
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = "{00000000-0000-0000-0000-000000000000}";
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = L"00000000-0000-0000-0000-000000000000";
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = L"{00000000-0000-0000-0000-000000000000}";
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-}
-
-TEST_CASE("uuid: Test from_string(basic_string)", "[uuid]")
-{
- using namespace std::string_literals;
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e43"s;
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string(guid) == str);
- }
-
- {
- auto str = "{47183823-2574-4bfd-b411-99ed177d3e43}"s;
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43");
- }
-
- {
- auto guid = uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43"s).value();
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43");
- REQUIRE(to_string<wchar_t>(guid) == L"47183823-2574-4bfd-b411-99ed177d3e43");
- }
-
- {
- auto str = L"47183823-2574-4bfd-b411-99ed177d3e43"s;
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string<wchar_t>(guid) == str);
- }
-
- {
- auto str = "4718382325744bfdb41199ed177d3e43"s;
- REQUIRE_NOTHROW(uuid::from_string(str));
- REQUIRE(uuid::from_string(str).has_value());
- }
-
- {
- auto str = "00000000-0000-0000-0000-000000000000"s;
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = "{00000000-0000-0000-0000-000000000000}"s;
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = L"00000000-0000-0000-0000-000000000000"s;
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = L"{00000000-0000-0000-0000-000000000000}"s;
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-}
-
-TEST_CASE("uuid: Test from_string(basic_string_view)", "[uuid]")
-{
- using namespace std::string_view_literals;
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e43"sv;
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string(guid) == str);
- }
-
- {
- auto str = "{47183823-2574-4bfd-b411-99ed177d3e43}"sv;
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43");
- }
-
- {
- auto guid = uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43"sv).value();
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43");
- REQUIRE(to_string<wchar_t>(guid) == L"47183823-2574-4bfd-b411-99ed177d3e43");
- }
-
- {
- auto str = L"47183823-2574-4bfd-b411-99ed177d3e43"sv;
- auto guid = uuid::from_string(str).value();
- REQUIRE(to_string<wchar_t>(guid) == str);
- }
-
- {
- auto str = "4718382325744bfdb41199ed177d3e43"sv;
- REQUIRE_NOTHROW(uuid::from_string(str));
- REQUIRE(uuid::from_string(str).has_value());
- }
-
- {
- auto str = "00000000-0000-0000-0000-000000000000"sv;
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = "{00000000-0000-0000-0000-000000000000}"sv;
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = L"00000000-0000-0000-0000-000000000000"sv;
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-
- {
- auto str = L"{00000000-0000-0000-0000-000000000000}"sv;
- auto guid = uuid::from_string(str).value();
- REQUIRE(guid.is_nil());
- }
-}
-
-TEST_CASE("uuid: Test constexpr from_string", "[uuid]")
-{
- constexpr uuid value = uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43").value();
- static_assert(!value.is_nil());
- static_assert(value.variant() == uuid_variant::rfc);
- static_assert(value.version() != uuid_version::none);
-}
-
-TEST_CASE("uuid: Test from_string(char*) invalid format", "[uuid]")
-{
- REQUIRE(!uuid::from_string("").has_value());
- REQUIRE(!uuid::from_string("{}").has_value());
- REQUIRE(!uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e4").has_value());
- REQUIRE(!uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e430").has_value());
- REQUIRE(!uuid::from_string("{47183823-2574-4bfd-b411-99ed177d3e43").has_value());
- REQUIRE(!uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43}").has_value());
-}
-
-TEST_CASE("uuid: Test from_string(basic_string) invalid format", "[uuid]")
-{
- using namespace std::string_literals;
-
- {
- auto str = ""s;
- REQUIRE(!uuid::from_string(str).has_value());
- }
-
- {
- auto str = "{}"s;
- REQUIRE(!uuid::from_string(str).has_value());
- }
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e4"s;
- REQUIRE(!uuid::from_string(str).has_value());
- }
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e430"s;
- REQUIRE(!uuid::from_string(str).has_value());
- }
-
- {
- auto str = "{47183823-2574-4bfd-b411-99ed177d3e43"s;
- REQUIRE(!uuid::from_string(str).has_value());
- }
-
- {
- auto str = "47183823-2574-4bfd-b411-99ed177d3e43}"s;
- REQUIRE(!uuid::from_string(str).has_value());
- }
-}
-
-TEST_CASE("uuid: Test from_string(basic_string_view) invalid format", "[uuid]")
-{
- using namespace std::string_view_literals;
-
- REQUIRE(!uuid::from_string(""sv).has_value());
- REQUIRE(!uuid::from_string("{}"sv).has_value());
- REQUIRE(!uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e4"sv).has_value());
- REQUIRE(!uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e430"sv).has_value());
- REQUIRE(!uuid::from_string("{47183823-2574-4bfd-b411-99ed177d3e43"sv).has_value());
- REQUIRE(!uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43}"sv).has_value());
-}
-
-TEST_CASE("uuid: Test iterators constructor", "[uuid]")
-{
- using namespace std::string_literals;
-
- {
- std::array<uuid::value_type, 16> arr{
- {0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd, 0xb4, 0x11, 0x99, 0xed,
- 0x17, 0x7d, 0x3e, 0x43}
- };
-
- auto const guid = uuid(std::begin(arr), std::end(arr));
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43"s);
- }
-
- {
- uuid::value_type arr[16] = {// NOLINT
- 0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd,
- 0xb4, 0x11, 0x99, 0xed, 0x17, 0x7d, 0x3e, 0x43};
-
- auto const guid = uuid(std::begin(arr), std::end(arr));
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43"s);
- }
-}
-
-TEST_CASE("uuid: Test array constructors", "[uuid]")
-{
- using namespace std::string_literals;
-
- {
- auto const guid = uuid {
- {0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd, 0xb4, 0x11, 0x99, 0xed,
- 0x17, 0x7d, 0x3e, 0x43}
- };
-
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43"s);
- }
-
- {
- auto arr = std::array<uuid::value_type, 16>{
- {0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd, 0xb4, 0x11, 0x99, 0xed,
- 0x17, 0x7d, 0x3e, 0x43}
- };
-
- auto const guid = uuid(arr);
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43"s);
- }
-
- {
- uuid::value_type arr[16]{// NOLINT
- 0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd,
- 0xb4, 0x11, 0x99, 0xed, 0x17, 0x7d, 0x3e, 0x43};
-
- auto const guid = uuid(arr);
- REQUIRE(to_string(guid) == "47183823-2574-4bfd-b411-99ed177d3e43"s);
- }
-}
-
-TEST_CASE("uuid: Test equality", "[uuid]")
-{
- uuid empty;
-
- auto engine = uuid_random_generator::engine_type{};
- seed_rng(engine);
- uuid guid = uuid_random_generator{engine}();
-
- REQUIRE(empty == empty);
- REQUIRE(guid == guid);
- REQUIRE(empty != guid);
-}
-
-TEST_CASE("Test comparison", "[uuid]")
-{
- auto empty = uuid{};
-
- auto engine = uuid_random_generator::engine_type{};
- seed_rng(engine);
-
- auto gen = uuid_random_generator{engine};
- auto id = gen();
-
- REQUIRE(empty < id);
-
- auto ids = std::set{uuid{}, gen(), gen(), gen(), gen()};
-
- REQUIRE(ids.size() == 5);
- REQUIRE(ids.contains(uuid{}) == true);
-}
-
-TEST_CASE("uuid: Test hashing", "[uuid]")
-{
- using namespace std::string_literals;
-
- auto str = "47183823-2574-4bfd-b411-99ed177d3e43"s;
- auto guid = uuid::from_string(str).value();
-
- auto h1 = std::hash<std::string>{};
- auto h2 = std::hash<uuid>{};
- REQUIRE(h1(str) != h2(guid));
-
- auto engine = uuid_random_generator::engine_type{};
- seed_rng(engine);
- uuid_random_generator gen{engine};
-
- std::unordered_set<uuid> ids{uuid{}, gen(), gen(), gen(), gen()};
-
- REQUIRE(ids.size() == 5);
- REQUIRE(ids.find(uuid{}) != ids.end());
-}
-
-TEST_CASE("uuid: Test swap", "[uuid]")
-{
- uuid empty;
-
- auto engine = uuid_random_generator::engine_type{};
- seed_rng(engine);
- uuid guid = uuid_random_generator{engine}();
-
- REQUIRE(empty.is_nil());
- REQUIRE(!guid.is_nil());
-
- std::swap(empty, guid);
-
- REQUIRE(!empty.is_nil());
- REQUIRE(guid.is_nil());
-
- empty.swap(guid);
-
- REQUIRE(empty.is_nil());
- REQUIRE(!guid.is_nil());
-}
-
-TEST_CASE("uuid: Test constexpr", "[uuid]")
-{
- constexpr uuid empty;
- static_assert(empty.is_nil());
- static_assert(empty.variant() == uuid_variant::ncs);
- static_assert(empty.version() == uuid_version::none);
-}
-
-TEST_CASE("uuid: Test size", "[uuid]")
-{
- REQUIRE(sizeof(uuid) == 16);
-}
-
-TEST_CASE("uuid: Test assignment", "[uuid]")
-{
- auto id1 = uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43").value();
- auto id2 = id1;
- REQUIRE(id1 == id2);
-
- id1 = uuid::from_string("{fea43102-064f-4444-adc2-02cec42623f8}").value();
- REQUIRE(id1 != id2);
-
- auto id3 = std::move(id2);
- REQUIRE(to_string(id3) == "47183823-2574-4bfd-b411-99ed177d3e43");
-}
-
-TEST_CASE("uuid: Test trivial", "[uuid]")
-{
- REQUIRE(std::is_trivially_copyable_v<uuid>);
-}
-
-TEST_CASE("uuid: Test as_bytes", "[uuid]")
-{
- std::array<uuid::value_type, 16> arr{
- {0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd, 0xb4, 0x11, 0x99, 0xed, 0x17, 0x7d,
- 0x3e, 0x43}
- };
-
- {
- uuid id{arr};
- REQUIRE(!id.is_nil());
-
- auto view = id.as_bytes();
- REQUIRE(memcmp(view.data(), arr.data(), arr.size()) == 0);
- }
-
- {
- const uuid id{arr};
- REQUIRE(!id.is_nil());
-
- auto view = id.as_bytes();
- REQUIRE(memcmp(view.data(), arr.data(), arr.size()) == 0);
- }
-}
-} // anonymous namespace
-
-// NOLINTEND(bugprone-unchecked-optional-access)
diff --git a/nihil.uuid/uuid.ccm b/nihil.uuid/uuid.ccm
deleted file mode 100644
index a7a4770..0000000
--- a/nihil.uuid/uuid.ccm
+++ /dev/null
@@ -1,768 +0,0 @@
-// From https://github.com/mariusbancila/stduuid
-//
-// Copyright (c) 2017
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-
-export module nihil.uuid;
-
-import nihil.std;
-
-namespace nihil {
-
-template <typename TChar>
-[[nodiscard]] constexpr auto hex2char(TChar const ch) noexcept -> unsigned char
-{
- if (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9'))
- return static_cast<unsigned char>(ch - static_cast<TChar>('0'));
-
- if (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f'))
- return static_cast<unsigned char>(10 + ch - static_cast<TChar>('a'));
-
- if (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'))
- return static_cast<unsigned char>(10 + ch - static_cast<TChar>('A'));
-
- return 0;
-}
-
-template <typename TChar>
-[[nodiscard]] constexpr auto is_hex(TChar const ch) noexcept -> bool
-{
- return (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) ||
- (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) ||
- (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'));
-}
-
-template <typename TChar>
-[[nodiscard]] constexpr auto
-to_string_view(TChar const *str) noexcept -> std::basic_string_view<TChar>
-{
- if (str)
- return str;
- return {};
-}
-
-template <typename StringType>
-[[nodiscard]] constexpr auto to_string_view(StringType const &str) noexcept
- -> std::basic_string_view<typename StringType::value_type, typename StringType::traits_type>
-{
- return str;
-}
-
-struct sha1
-{
- using digest32_t = std::array<std::uint32_t, 5>;
- using digest8_t = std::array<std::uint8_t, 20>;
-
- static constexpr unsigned int block_bytes = 64;
-
- sha1()
- {
- reset();
- }
-
- [[nodiscard]] static auto
- left_rotate(std::uint32_t value, std::size_t const count) noexcept -> std::uint32_t
- {
- return (value << count) ^ (value >> (32 - count));
- }
-
- auto reset(this sha1 &self) noexcept -> void
- {
- self.m_digest[0] = 0x67452301;
- self.m_digest[1] = 0xEFCDAB89;
- self.m_digest[2] = 0x98BADCFE;
- self.m_digest[3] = 0x10325476;
- self.m_digest[4] = 0xC3D2E1F0;
- self.m_blockByteIndex = 0;
- self.m_byteCount = 0;
- }
-
- auto process_byte(this sha1 &self, std::uint8_t octet) -> void
- {
- self.m_block.at(self.m_blockByteIndex++) = octet;
- ++self.m_byteCount;
-
- if (self.m_blockByteIndex == block_bytes) {
- self.m_blockByteIndex = 0;
- self.process_block();
- }
- }
-
- auto process_block(this sha1 &self, void const *const start, void const *const end) -> void
- {
- auto const *first = static_cast<std::uint8_t const *>(start);
- auto const *last = static_cast<std::uint8_t const *>(end);
-
- while (first != last) {
- self.process_byte(*first);
- first++;
- }
- }
-
- auto process_bytes(this sha1 &self, void const *const data, std::size_t const len) -> void
- {
- auto *block = static_cast<std::uint8_t const *>(data);
- self.process_block(block, block + len);
- }
-
- auto get_digest(this sha1 &self) -> digest32_t
- {
- auto const bit_count = self.m_byteCount * 8;
-
- self.process_byte(0x80);
- if (self.m_blockByteIndex > 56) {
- while (self.m_blockByteIndex != 0)
- self.process_byte(0);
-
- while (self.m_blockByteIndex < 56)
- self.process_byte(0);
- } else {
- while (self.m_blockByteIndex < 56)
- self.process_byte(0);
- }
-
- self.process_byte(0);
- self.process_byte(0);
- self.process_byte(0);
- self.process_byte(0);
- self.process_byte(static_cast<unsigned char>((bit_count >> 24U) & 0xFFU));
- self.process_byte(static_cast<unsigned char>((bit_count >> 16U) & 0xFFU));
- self.process_byte(static_cast<unsigned char>((bit_count >> 8U) & 0xFFU));
- self.process_byte(static_cast<unsigned char>((bit_count) & 0xFFU));
-
- return self.m_digest;
- }
-
- auto get_digest_bytes(this sha1 &self) -> digest8_t
- {
- auto d32 = self.get_digest();
-
- return {
- static_cast<std::uint8_t>(d32[0] >> 24U),
- static_cast<std::uint8_t>(d32[0] >> 16U),
- static_cast<std::uint8_t>(d32[0] >> 8U),
- static_cast<std::uint8_t>(d32[0] >> 0U),
-
- static_cast<std::uint8_t>(d32[1] >> 24U),
- static_cast<std::uint8_t>(d32[1] >> 16U),
- static_cast<std::uint8_t>(d32[1] >> 8U),
- static_cast<std::uint8_t>(d32[1] >> 0U),
-
- static_cast<std::uint8_t>(d32[2] >> 24U),
- static_cast<std::uint8_t>(d32[2] >> 16U),
- static_cast<std::uint8_t>(d32[2] >> 8U),
- static_cast<std::uint8_t>(d32[2] >> 0U),
-
- static_cast<std::uint8_t>(d32[3] >> 24U),
- static_cast<std::uint8_t>(d32[3] >> 16U),
- static_cast<std::uint8_t>(d32[3] >> 8U),
- static_cast<std::uint8_t>(d32[3] >> 0U),
-
- static_cast<std::uint8_t>(d32[4] >> 24U),
- static_cast<std::uint8_t>(d32[4] >> 16U),
- static_cast<std::uint8_t>(d32[4] >> 8U),
- static_cast<std::uint8_t>(d32[4] >> 0U),
- };
- }
-
-private:
- auto process_block(this sha1 &self) -> void
- {
- auto w = std::array<std::uint32_t, 80>{};
-
- for (std::size_t i = 0; i < 16; i++) {
- w.at(i) = static_cast<std::uint32_t>(self.m_block.at((i * 4) + 0)) << 24U;
- w.at(i) |= static_cast<std::uint32_t>(self.m_block.at((i * 4) + 1)) << 16U;
- w.at(i) |= static_cast<std::uint32_t>(self.m_block.at((i * 4) + 2)) << 8U;
- w.at(i) |= static_cast<std::uint32_t>(self.m_block.at((i * 4) + 3));
- }
-
- for (std::size_t i = 16; i < 80; i++) {
- w.at(i) = left_rotate(
- (w.at(i - 3) ^ w.at(i - 8) ^ w.at(i - 14) ^ w.at(i - 16)), 1);
- }
-
- auto a = self.m_digest[0];
- auto b = self.m_digest[1];
- auto c = self.m_digest[2];
- auto d = self.m_digest[3];
- auto e = self.m_digest[4];
-
- for (std::size_t i = 0; i < 80; ++i) {
- auto f = std::uint32_t{0};
- auto k = std::uint32_t{0};
-
- if (i < 20) {
- f = (b & c) | (~b & d);
- k = 0x5A827999;
- } else if (i < 40) {
- f = b ^ c ^ d;
- k = 0x6ED9EBA1;
- } else if (i < 60) {
- f = (b & c) | (b & d) | (c & d);
- k = 0x8F1BBCDC;
- } else {
- f = b ^ c ^ d;
- k = 0xCA62C1D6;
- }
-
- auto temp = std::uint32_t{left_rotate(a, 5) + f + e + k + w.at(i)};
- e = d;
- d = c;
- c = left_rotate(b, 30);
- b = a;
- a = temp;
- }
-
- self.m_digest[0] += a;
- self.m_digest[1] += b;
- self.m_digest[2] += c;
- self.m_digest[3] += d;
- self.m_digest[4] += e;
- }
-
- digest32_t m_digest{};
- std::array<std::uint8_t, 64> m_block{};
- std::size_t m_blockByteIndex{};
- std::size_t m_byteCount{};
-};
-
-template <typename CharT>
-inline constexpr std::string_view empty_guid = "00000000-0000-0000-0000-000000000000";
-
-template <>
-inline constexpr std::wstring_view empty_guid<wchar_t> = L"00000000-0000-0000-0000-000000000000";
-
-template <typename CharT>
-inline constexpr std::string_view guid_encoder = "0123456789abcdef";
-
-template <>
-inline constexpr std::wstring_view guid_encoder<wchar_t> = L"0123456789abcdef";
-
-// ---------------------------------------------------------------------
-// UUID format https://tools.ietf.org/html/rfc4122
-// ---------------------------------------------------------------------
-
-// ---------------------------------------------------------------------
-// Field NDR Data Type Octet # Note
-// Note
-// ---------------------------------------------------------------------
-// time_low unsigned long 0 - 3
-// The low field of the timestamp.
-// time_mid unsigned short 4 - 5
-// The middle field of the timestamp.
-// time_hi_and_version unsigned short 6 - 7
-// The high field of the timestamp multiplexed with the version number.
-// clock_seq_hi_and_reserved unsigned small 8
-// The high field of the clock sequence multiplexed with the variant.
-// clock_seq_low unsigned small 9
-// The low field of the clock sequence.
-// node character 10 - 15
-// The spatially unique node identifier.
-// ---------------------------------------------------------------------
-// 0 1 2 3
-// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | time_low |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | time_mid | time_hi_and_version |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |clk_seq_hi_res | clk_seq_low | node (0-1) |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | node (2-5) |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-// ---------------------------------------------------------------------
-// enumerations
-// ---------------------------------------------------------------------
-
-// indicated by a bit pattern in octet 8, marked with N in
-// xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx
-export enum struct uuid_variant : std::uint8_t {
- // NCS backward compatibility (with the obsolete Apollo Network
- // Computing System 1.5 UUID format).
- // N bit pattern: 0xxx
- // > the first 6 octets of the UUID are a 48-bit timestamp (the number
- // of 4 microsecond units of time since 1 Jan 1980 UTC);
- // > the next 2 octets are reserved;
- // > the next octet is the "address family";
- // > the final 7 octets are a 56-bit host ID in the form specified by
- // the address family
- ncs,
-
- // RFC 4122/DCE 1.1
- // N bit pattern: 10xx
- // > big-endian byte order
- rfc,
-
- // Microsoft Corporation backward compatibility
- // N bit pattern: 110x
- // > little endian byte order
- // > formely used in the Component Object Model (COM) library
- microsoft,
-
- // reserved for possible future definition
- // N bit pattern: 111x
- reserved
-};
-
-// indicated by a bit pattern in octet 6, marked with M in
-// xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx
-export enum struct uuid_version : std::uint8_t {
- // only possible for nil or invalid uuids
- none = 0,
- // The time-based version specified in RFC 4122
- time_based = 1,
- // DCE Security version, with embedded POSIX UIDs.
- dce_security = 2,
- // The name-based version specified in RFS 4122 with MD5 hashing
- name_based_md5 = 3,
- // The randomly or pseudo-randomly generated version specified in RFS 4122
- random_number_based = 4,
- // The name-based version specified in RFS 4122 with SHA1 hashing
- name_based_sha1 = 5
-};
-
-// Forward declare uuid and to_string so that we can declare to_string as a
-// friend later.
-export struct uuid;
-export template <typename CharT = char, typename Traits = std::char_traits<CharT>,
- typename Allocator = std::allocator<CharT>>
-auto to_string(uuid const &id) -> std::basic_string<CharT, Traits, Allocator>;
-
-// --------------------------------------------------------------------------------------------------------------------------
-// uuid class
-// --------------------------------------------------------------------------------------------------------------------------
-export struct uuid
-{
- using value_type = std::uint8_t;
-
- constexpr uuid() noexcept = default;
-
- uuid(value_type (&arr)[16]) noexcept // NOLINT
- {
- std::ranges::copy(arr, std::ranges::begin(data));
- }
-
- explicit constexpr uuid(std::array<value_type, 16> const &arr) noexcept
- : data{arr}
- {
- }
-
- explicit uuid(std::span<value_type, 16> bytes)
- {
- std::ranges::copy(bytes, std::ranges::begin(data));
- }
-
- explicit uuid(std::span<value_type> bytes)
- {
- if (bytes.size() != 16)
- throw std::logic_error("wrong size for uuid");
- std::ranges::copy(bytes, std::ranges::begin(data));
- }
-
- template <typename ForwardIterator>
- explicit uuid(ForwardIterator first, ForwardIterator last)
- {
- if (std::distance(first, last) != 16)
- throw std::logic_error("wrong size for uuid");
-
- std::copy(first, last, std::begin(data));
- }
-
- [[nodiscard]] constexpr auto variant() const noexcept -> uuid_variant
- {
- if ((data[8] & 0x80U) == 0x00U)
- return uuid_variant::ncs;
- else if ((data[8] & 0xC0U) == 0x80U)
- return uuid_variant::rfc;
- else if ((data[8] & 0xE0U) == 0xC0U)
- return uuid_variant::microsoft;
- else
- return uuid_variant::reserved;
- }
-
- [[nodiscard]] constexpr auto version() const noexcept -> uuid_version
- {
- if ((data[6] & 0xF0U) == 0x10U)
- return uuid_version::time_based;
- else if ((data[6] & 0xF0U) == 0x20U)
- return uuid_version::dce_security;
- else if ((data[6] & 0xF0U) == 0x30U)
- return uuid_version::name_based_md5;
- else if ((data[6] & 0xF0U) == 0x40U)
- return uuid_version::random_number_based;
- else if ((data[6] & 0xF0U) == 0x50U)
- return uuid_version::name_based_sha1;
- else
- return uuid_version::none;
- }
-
- [[nodiscard]] constexpr auto is_nil() const noexcept -> bool
- {
- return std::ranges::all_of(data, [](auto i) { return i == 0; });
- }
-
- auto swap(uuid &other) noexcept -> void
- {
- data.swap(other.data);
- }
-
- [[nodiscard]] auto as_bytes() const -> std::span<std::byte const, 16>
- {
- return std::span<std::byte const, 16>(
- reinterpret_cast<std::byte const *>(data.data()), 16);
- }
-
- template <typename StringType>
- [[nodiscard]] constexpr static auto is_valid_uuid(StringType const &in_str) noexcept -> bool
- {
- auto str = to_string_view(in_str);
- auto firstDigit = true;
- auto hasBraces = std::size_t{0};
- auto index = std::size_t{0};
-
- if (str.empty())
- return false;
-
- if (str.front() == '{')
- hasBraces = 1;
-
- if (hasBraces && str.back() != '}')
- return false;
-
- for (std::size_t i = hasBraces; i < str.size() - hasBraces; ++i) {
- if (str[i] == '-')
- continue;
-
- if (index >= 16 || !is_hex(str[i]))
- return false;
-
- if (firstDigit) {
- firstDigit = false;
- } else {
- index++;
- firstDigit = true;
- }
- }
-
- if (index < 16)
- return false;
-
- return true;
- }
-
- template <typename StringType>
- [[nodiscard]] constexpr static auto
- from_string(StringType const &in_str) -> std::optional<uuid>
- {
- auto str = to_string_view(in_str);
- bool firstDigit = true;
- auto hasBraces = std::size_t{0};
- auto index = std::size_t{0};
-
- auto data = std::array<std::uint8_t, 16>{};
-
- if (str.empty())
- return {};
-
- if (str.front() == '{')
- hasBraces = 1;
- if (hasBraces && str.back() != '}')
- return {};
-
- for (std::size_t i = hasBraces; i < str.size() - hasBraces; ++i) {
- if (str[i] == '-')
- continue;
-
- if (index >= 16 || !is_hex(str[i])) {
- return {};
- }
-
- if (firstDigit) {
- data.at(index) = static_cast<std::uint8_t>(hex2char(str[i]) << 4);
- firstDigit = false;
- } else {
- data.at(index) =
- static_cast<std::uint8_t>(data.at(index) | hex2char(str[i]));
- index++;
- firstDigit = true;
- }
- }
-
- if (index < 16) {
- return {};
- }
-
- return uuid{data};
- }
-
-private:
- std::array<value_type, 16> data{{0}};
-
- friend auto operator==(uuid const &, uuid const &) noexcept -> bool;
- friend auto operator<(uuid const &, uuid const &) noexcept -> bool;
-
- template <class Elem, class Traits>
- friend auto operator<<(std::basic_ostream<Elem, Traits> &s, uuid const &id)
- -> std::basic_ostream<Elem, Traits> &;
-
- template <class CharT, class Traits, class Allocator>
- friend auto to_string(uuid const &id) -> std::basic_string<CharT, Traits, Allocator>;
-
- friend std::hash<uuid>;
-};
-
-// --------------------------------------------------------------------------------------------------------------------------
-// operators and non-member functions
-// --------------------------------------------------------------------------------------------------------------------------
-
-export [[nodiscard]]
-auto operator==(uuid const &lhs, uuid const &rhs) noexcept -> bool
-{
- return lhs.data == rhs.data;
-}
-
-export [[nodiscard]]
-auto operator!=(uuid const &lhs, uuid const &rhs) noexcept -> bool
-{
- return !(lhs == rhs);
-}
-
-export [[nodiscard]]
-auto operator<(uuid const &lhs, uuid const &rhs) noexcept -> bool
-{
- return lhs.data < rhs.data;
-}
-
-export template <typename CharT, typename Traits, typename Allocator>
-[[nodiscard]] auto to_string(uuid const &id) -> std::basic_string<CharT, Traits, Allocator>
-{
- auto uustr =
- std::basic_string<CharT, Traits, Allocator>(std::from_range, empty_guid<CharT>);
-
- for (std::size_t i = 0, index = 0; i < 36; ++i) {
- if (i == 8 || i == 13 || i == 18 || i == 23)
- continue;
-
- uustr[i] = guid_encoder<CharT>[id.data.at(index) >> 4U & 0x0FU];
- uustr[++i] = guid_encoder<CharT>[id.data.at(index) & 0x0FU];
- index++;
- }
-
- return uustr;
-}
-
-export template <class Elem, class Traits>
-auto operator<<(std::basic_ostream<Elem, Traits> &s, uuid const &id)
- -> std::basic_ostream<Elem, Traits> &
-{
- return s << to_string(id);
-}
-
-export auto swap(uuid &lhs, uuid &rhs) noexcept -> void
-{
- lhs.swap(rhs);
-}
-
-/***********************************************************************
- * namespace IDs that could be used for generating name-based uuids
- */
-
-// Name string is a fully-qualified domain name
-export uuid uuid_namespace_dns{
- {0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
- 0xc8}
-};
-
-// Name string is a URL
-export uuid uuid_namespace_url{
- {0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
- 0xc8}
-};
-
-// Name string is an ISO OID (See https://oidref.com/,
-// https://en.wikipedia.org/wiki/Object_identifier)
-export uuid uuid_namespace_oid{
- {0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
- 0xc8}
-};
-
-// Name string is an X.500 DN, in DER or a text output format (See
-// https://en.wikipedia.org/wiki/X.500,
-// https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One)
-export uuid uuid_namespace_x500{
- {0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
- 0xc8}
-};
-
-/***********************************************************************
- * uuid generators
- */
-
-export template <typename UniformRandomNumberGenerator>
-struct basic_uuid_random_generator
-{
- using engine_type = UniformRandomNumberGenerator;
-
- explicit basic_uuid_random_generator(engine_type &gen)
- : generator(&gen, [](auto) {})
- {
- }
-
- explicit basic_uuid_random_generator(engine_type *gen)
- : generator(gen, [](auto) {})
- {
- }
-
- [[nodiscard]] auto operator()() -> uuid
- {
- auto bytes = std::array<std::uint8_t, 16>{};
- std::ranges::generate(bytes, [&] { return distribution(*generator); });
-
- // variant must be 10xxxxxx
- bytes[8] &= 0xBFU;
- bytes[8] |= 0x80U;
-
- // version must be 0100xxxx
- bytes[6] &= 0x4FU;
- bytes[6] |= 0x40U;
-
- return uuid{std::begin(bytes), std::end(bytes)};
- }
-
-private:
- std::uniform_int_distribution<std::uint32_t> distribution;
- std::shared_ptr<UniformRandomNumberGenerator> generator;
-};
-
-export using uuid_random_generator = basic_uuid_random_generator<std::mt19937>;
-
-export struct uuid_name_generator
-{
- explicit uuid_name_generator(uuid const &namespace_uuid) noexcept
- : nsuuid(namespace_uuid)
- {
- }
-
- template <typename StringType>
- [[nodiscard]] auto operator()(StringType const &name) -> uuid
- {
- reset();
- process_characters(to_string_view(name));
- return make_uuid();
- }
-
-private:
- auto reset() -> void
- {
- hasher.reset();
-
- auto nsbytes = nsuuid.as_bytes();
-
- auto bytes = std::array<std::byte, 16>();
- std::ranges::copy(nsbytes, std::ranges::begin(bytes));
-
- hasher.process_bytes(bytes.data(), bytes.size());
- }
-
- template <typename CharT, typename Traits>
- auto process_characters(std::basic_string_view<CharT, Traits> const str) -> void
- {
- for (std::uint32_t c : str) {
- hasher.process_byte(static_cast<std::uint8_t>(c & 0xFFU));
- if constexpr (!std::is_same_v<CharT, char>) {
- hasher.process_byte(static_cast<std::uint8_t>((c >> 8U) & 0xFFU));
- hasher.process_byte(static_cast<std::uint8_t>((c >> 16U) & 0xFFU));
- hasher.process_byte(static_cast<std::uint8_t>((c >> 24U) & 0xFFU));
- }
- }
- }
-
- [[nodiscard]] auto make_uuid() -> uuid
- {
- auto digest = hasher.get_digest_bytes();
-
- // variant must be 0b10xxxxxx
- digest[8] &= 0xBFU;
- digest[8] |= 0x80U;
-
- // version must be 0b0101xxxx
- digest[6] &= 0x5FU;
- digest[6] |= 0x50U;
-
- return uuid(std::span(digest).subspan(0, 16));
- }
-
- uuid nsuuid;
- sha1 hasher;
-};
-
-/*
- * Create a random UUID.
- */
-export auto random_uuid() -> uuid
-{
- auto rd = std::random_device();
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::ranges::generate(seed_data, std::ref(rd));
-
- auto seq = std::seed_seq(std::ranges::begin(seed_data), std::ranges::end(seed_data));
- auto generator = std::mt19937(seq);
- auto gen = uuid_random_generator{generator};
-
- return gen();
-}
-
-} // namespace nihil
-
-namespace std {
-
-export template <>
-struct hash<nihil::uuid>
-{
- using argument_type = nihil::uuid;
- using result_type = std::size_t;
-
- [[nodiscard]] auto operator()(argument_type const &uuid) const noexcept -> result_type
- {
- auto const l = static_cast<uint64_t>(uuid.data[0]) << 56U |
- static_cast<uint64_t>(uuid.data[1]) << 48U |
- static_cast<uint64_t>(uuid.data[2]) << 40U |
- static_cast<uint64_t>(uuid.data[3]) << 32U |
- static_cast<uint64_t>(uuid.data[4]) << 24U |
- static_cast<uint64_t>(uuid.data[5]) << 16U |
- static_cast<uint64_t>(uuid.data[6]) << 8U |
- static_cast<uint64_t>(uuid.data[7]);
-
- auto const h = static_cast<uint64_t>(uuid.data[8]) << 56U |
- static_cast<uint64_t>(uuid.data[9]) << 48U |
- static_cast<uint64_t>(uuid.data[10]) << 40U |
- static_cast<uint64_t>(uuid.data[11]) << 32U |
- static_cast<uint64_t>(uuid.data[12]) << 24U |
- static_cast<uint64_t>(uuid.data[13]) << 16U |
- static_cast<uint64_t>(uuid.data[14]) << 8U |
- static_cast<uint64_t>(uuid.data[15]);
-
- return std::hash<std::uint64_t>{}(l ^ h);
- }
-};
-
-} // namespace std