module; // Might as well since we're using OpenSSL #include #include module routemon:trace$impl; import :trace; namespace routemon::trace { class psrng { mutable std::default_random_engine e_ = {}; mutable std::uniform_int_distribution distr_ = {}; mutable std::mutex mut_ = {}; public: auto next() const -> std::uint64_t { auto lock = std::lock_guard{mut_}; return distr_(e_); } static auto instance() -> psrng const& { static auto const inst = psrng{}; return inst; } }; uuid7::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 const& rng = psrng::instance(); auto const rand1 = rng.next(); auto const rand2 = rng.next(); auto version = std::uint64_t{0b0111}; auto variant = std::uint64_t{0b10}; hi_ = unix_time_ms << 16; hi_ |= version << 12; hi_ |= rand1 & 0x0000'0000'0000'0fff; lo_ = variant << 62; lo_ |= rand2 >> 2; } auto uuid7::format(std::span target) -> void { auto hexnibs = [](std::uint64_t v, std::span s) -> void { for (auto i = 0uz; i < n; i++) { static char const hextab[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', }; s[i] = hextab[(v >> 4 * (n - 1 - i)) & 0xf]; } }; auto p____hi_hi = (hi_ & 0xffff'ffff'0000'0000) >> 32; auto p_hi_lo_hi = (hi_ & 0x0000'0000'ffff'0000) >> 16; auto p_lo_lo_hi = (hi_ & 0x0000'0000'0000'ffff) >> 0; auto p____hi_lo = (lo_ & 0xffff'0000'0000'0000) >> 48; auto p____lo_lo = (lo_ & 0x0000'ffff'ffff'ffff) >> 0; hexnibs(p____hi_hi, target.subspan<0, 8>()); target[8] = '-'; hexnibs(p_hi_lo_hi, target.subspan<9, 4>()); target[13] = '-'; hexnibs(p_lo_lo_hi, target.subspan<14, 4>()); target[18] = '-'; hexnibs(p____hi_lo, target.subspan<19, 4>()); target[23] = '-'; hexnibs(p____lo_lo, target.subspan<24, 12>()); target[36] = '\0'; } id::id() { uuid7{}.format(chars_); } auto id::as_string() const -> util::zstring_view { return util::zstring_view{chars_.data(), chars_.size() - 1}; } } // namespace routemon::trace