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