sandbox
Loading...
Searching...
No Matches
uuid.hpp
1#ifndef LIBSBX_MATH_UUID_HPP_
2#define LIBSBX_MATH_UUID_HPP_
3
4#include <cinttypes>
5
6#include <fmt/format.h>
7
8#include <range/v3/all.hpp>
9
11
12#include <libsbx/math/random.hpp>
13
14namespace sbx::math {
15
16class uuid {
17
18 friend struct fmt::formatter<sbx::math::uuid>;
19 friend struct std::hash<sbx::math::uuid>;
20
21public:
22
23 static const uuid null;
24
25 uuid() {
26 // Taken from https://www.cryptosys.net/pki/uuid-rfc4122.html
27
28 // 1. Generate 16 random bytes (=128 bits)
29 for (auto& byte : _bytes) {
30 byte = random::next<std::uint8_t>();
31 }
32
33 // 2. Adjust certain bits according to RFC 4122 section 4.4 as follows:
34 // (a) set the four most significant bits of the 7th byte to 0100'B, so the high nibble is "4"
35 // (b) set the two most significant bits of the 9th byte to 10'B, so the high nibble will be one of "8", "9", "A" or "B"
36 _bytes[6] = 0x40 | (_bytes[6] & 0xf);
37 _bytes[8] = 0x80 | (_bytes[8] & 0x3f);
38 }
39
40 ~uuid() = default;
41
42 auto operator==(const uuid& other) const noexcept -> bool {
43 return std::ranges::equal(_bytes, other._bytes);
44 }
45
46private:
47
48 uuid(std::array<std::uint8_t, 16u>&& bytes)
49 : _bytes{std::move(bytes)} { }
50
51 std::array<std::uint8_t, 16u> _bytes;
52
53}; // class uuid
54
55} // namespace sbx::math
56
57template<>
58struct fmt::formatter<sbx::math::uuid> {
59
60 template<typename ParseContext>
61 constexpr auto parse(ParseContext& context) -> decltype(context.begin()) {
62 return context.begin();
63 }
64
65 template<typename FormatContext>
66 auto format(const sbx::math::uuid& uuid, FormatContext& context) -> decltype(context.out()) {
67 for (const auto [i, byte] : ranges::views::enumerate(uuid._bytes)) {
68 fmt::format_to(context.out(), "{:02x}", byte);
69
70 if (i == 3 || i == 5 || i == 7 || i == 9) {
71 fmt::format_to(context.out(), "-");
72 }
73 }
74
75 return context.out();
76 }
77}; // struct fmt::formatter<sbx::math::uuid>
78
79template<>
80struct std::hash<sbx::math::uuid> {
81 auto operator()(const sbx::math::uuid& uuid) const noexcept -> std::size_t {
82 auto seed = std::size_t{0};
83
84 for (const auto& byte : uuid._bytes) {
85 sbx::utility::hash_combine(seed, byte);
86 }
87
88 return seed;
89 }
90}; // struct std::hash<sbx::math::uuid>
91
92#endif // LIBSBX_MATH_UUID_HPP_
93
Definition: uuid.hpp:16