summaryrefslogtreecommitdiffstats
path: root/server/src/trace.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/trace.cpp')
-rw-r--r--server/src/trace.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/server/src/trace.cpp b/server/src/trace.cpp
new file mode 100644
index 0000000..e7c00d0
--- /dev/null
+++ b/server/src/trace.cpp
@@ -0,0 +1,75 @@
1module;
2
3// Might as well since we're using OpenSSL
4#include <openssl/err.h>
5#include <openssl/rand.h>
6
7module routemon:trace$impl;
8
9import :trace;
10
11namespace routemon::trace {
12
13uuid7::uuid7()
14{
15 namespace chrono = std::chrono;
16 auto const unix_time_ms_signed = static_cast<std::int64_t>(
17 chrono::duration_cast<chrono::milliseconds>(
18 chrono::system_clock::now().time_since_epoch())
19 .count());
20 if (unix_time_ms_signed < 0)
21 throw std::runtime_error{"system time before UNIX epoch"};
22 auto const unix_time_ms = static_cast<std::uint64_t>(unix_time_ms_signed);
23 if (std::countl_zero(unix_time_ms) < 16)
24 throw std::runtime_error{"system time too great"};
25
26 auto rand = std::array<unsigned char, 10>{};
27 int s = RAND_bytes(rand.data(), static_cast<int>(rand.size()));
28 if (s != 1)
29 {
30 unsigned long e = ERR_get_error();
31 throw std::runtime_error{std::format(
32 "failed to generate UUID(v7): {} ({}, code {})",
33 ERR_reason_error_string(e), ERR_lib_error_string(e), e)};
34 }
35
36 auto version = std::uint64_t{0b0111};
37 auto variant = std::uint64_t{0b10};
38
39 hi_ |= unix_time_ms << 16;
40 hi_ |= version << 12;
41 hi_ |= std::uint64_t{rand[0]} << 4;
42 hi_ |= std::uint64_t{rand[1]};
43 lo_ |= variant << 62;
44 lo_ |= std::uint64_t{rand[2]} << 54;
45 lo_ |= std::uint64_t{rand[3]} << 48;
46 lo_ |= std::uint64_t{rand[4]} << 40;
47 lo_ |= std::uint64_t{rand[5]} << 32;
48 lo_ |= std::uint64_t{rand[6]} << 24;
49 lo_ |= std::uint64_t{rand[7]} << 16;
50 lo_ |= std::uint64_t{rand[8]} << 8;
51 lo_ |= std::uint64_t{rand[9]};
52}
53
54auto uuid7::format(std::array<char, 37>& target) -> void
55{
56 auto p____hi_hi = (hi_ & 0xffff'ffff'0000'0000) >> 32;
57 auto p_hi_lo_hi = (hi_ & 0x0000'0000'ffff'0000) >> 16;
58 auto p_lo_lo_hi = (hi_ & 0x0000'0000'0000'ffff) >> 0;
59 auto p____hi_lo = (lo_ & 0xffff'0000'0000'0000) >> 48;
60 auto p____lo_lo = (lo_ & 0x0000'ffff'ffff'ffff) >> 0;
61
62 std::format_to(
63 target.begin(), "{:0>8x}-{:0>4x}-{:0>4x}-{:0>4x}-{:0>12x}", p____hi_hi,
64 p_hi_lo_hi, p_lo_lo_hi, p____hi_lo, p____lo_lo);
65 target.back() = '\0';
66}
67
68id::id() { uuid7{}.format(chars_); }
69
70auto id::as_string() const -> util::zstring_view
71{
72 return util::zstring_view{chars_.data(), chars_.size() - 1};
73}
74
75} // namespace routemon::trace