From 973aec43ea54bbf95b64fbcb636403401d1ca60e Mon Sep 17 00:00:00 2001 From: Rutger Broekhoff Date: Fri, 28 Aug 2026 18:03:05 +0200 Subject: Import from e4b104792206ee7ea64bf39c6b7d2c0c230f9d14 --- server/src/trace.cppm | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 server/src/trace.cppm (limited to 'server/src/trace.cppm') diff --git a/server/src/trace.cppm b/server/src/trace.cppm new file mode 100644 index 0000000..00ecd05 --- /dev/null +++ b/server/src/trace.cppm @@ -0,0 +1,79 @@ +module; + +// Might as well since we're using OpenSSL +#include +#include + +export module routemon:trace; + +import std; +import :util; + +namespace routemon::trace { + + class uuid7 { + std::uint64_t high_ = 0; + std::uint64_t low_ = 0; + + public: + uuid7() { + namespace chrono = std::chrono; + auto const unix_time_ms_signed = static_cast(chrono::duration_cast(chrono::system_clock::now().time_since_epoch()).count()); + if (unix_time_ms_signed < 0) + throw std::runtime_error{"system time before UNIX epoch"}; + auto const unix_time_ms = static_cast(unix_time_ms_signed); + if (std::countl_zero(unix_time_ms) < 16) + throw std::runtime_error{"system time too great"}; + + auto rand = std::array{}; + int s = RAND_bytes(rand.data(), static_cast(rand.size())); + if (s != 1) { + unsigned long e = ERR_get_error(); + throw std::runtime_error{std::format("failed to generate UUID(v7): {} ({}, code {})", ERR_reason_error_string(e), ERR_lib_error_string(e), e)}; + } + + auto version = std::uint64_t{0b0111}; + auto variant = std::uint64_t{0b10}; + + high_ |= unix_time_ms << 16; + high_ |= version << 12; + high_ |= std::uint64_t{rand[0]} << 4; + high_ |= std::uint64_t{rand[1]}; + low_ |= variant << 62; + low_ |= std::uint64_t{rand[2]} << 54; + low_ |= std::uint64_t{rand[3]} << 48; + low_ |= std::uint64_t{rand[4]} << 40; + low_ |= std::uint64_t{rand[5]} << 32; + low_ |= std::uint64_t{rand[6]} << 24; + low_ |= std::uint64_t{rand[7]} << 16; + low_ |= std::uint64_t{rand[8]} << 8; + low_ |= std::uint64_t{rand[9]}; + } + + auto format(std::array& target) -> void { + auto high_high = (high_ & 0xffff'ffff'0000'0000) >> 32; + auto high_low_high = (high_ & 0x0000'0000'ffff'0000) >> 16; + auto low_low_high = (high_ & 0x0000'0000'0000'ffff) >> 0; + auto high_low = (low_ & 0xffff'0000'0000'0000) >> 48; + auto low_low = (low_ & 0x0000'ffff'ffff'ffff) >> 0; + + std::format_to(target.begin(), "{:0>8x}-{:0>4x}-{:0>4x}-{:0>4x}-{:0>12x}", + high_high, high_low_high, low_low_high, high_low, low_low); + target.back() = '\0'; + } + }; + + export class id { + std::array chars_; + + public: + id() { + uuid7{}.format(chars_); + } + + auto as_string() const -> util::zstring_view { + return util::zstring_view{chars_.data(), chars_.size() - 1}; + } + }; + +} // namespace routemon::trace -- cgit v1.3