sandbox
Loading...
Searching...
No Matches
uuid.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_MATH_UUID_HPP_
3#define LIBSBX_MATH_UUID_HPP_
4
5#if defined(SBX_MATH_UUID_USE_V4)
6
7#include <cinttypes>
8#include <exception>
9#include <charconv>
10
11#include <fmt/format.h>
12
13#include <range/v3/all.hpp>
14
16
17#include <libsbx/math/random.hpp>
18
19namespace sbx::math {
20
21struct invalid_uuid_exception : std::runtime_error {
22
23 invalid_uuid_exception(std::string_view uuid)
24 : std::runtime_error{fmt::format("String '{}' is not a valid uuid", uuid)} { }
25
26}; // struct invalid_uuid_exception
27
28class uuid {
29
30 friend struct fmt::formatter<sbx::math::uuid>;
31 friend struct std::hash<sbx::math::uuid>;
32
33 struct null_uui_tag { };
34
35public:
36
37 // static const uuid null;
38
39 using value_type = std::uint64_t;
40
41 uuid()
42 : _value{random::next<value_type>()} {
43 // Taken from https://www.cryptosys.net/pki/uuid-rfc4122.html
44
45 // // 1. Generate 16 random bytes (=128 bits)
46 // for (auto& byte : _bytes) {
47 // byte = random::next<std::uint8_t>();
48 // }
49
50 // 2. Adjust certain bits according to RFC 4122 section 4.4 as follows:
51 // (a) set the four most significant bits of the 7th byte to 0100'B, so the high nibble is "4"
52 // (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"
53 // _bytes[6] = 0x40 | (_bytes[6] & 0xf);
54 // _bytes[8] = 0x80 | (_bytes[8] & 0x3f);
55 }
56
57 // uuid(std::string_view string) {
58 // if (string.size() != 36u) {
59 // throw invalid_uuid_exception{string};
60 // }
61
62 // for (auto i = 0u, offset = 0u; i < _bytes.size(); ++i) {
63
64 // if (i == 4u || i == 6u || i == 8u || i == 10u) {
65 // ++offset;
66 // }
67
68 // auto substr = string.substr(i * 2u + offset, 2u);
69 // const auto [itr, error] = std::from_chars(substr.data(), substr.data() + 2u, _bytes[i], 16);
70
71 // if (error == std::errc::invalid_argument || error == std::errc::result_out_of_range) {
72 // throw invalid_uuid_exception{string};
73 // }
74 // }
75
76 // }
77
78 ~uuid() = default;
79
80 static auto null() -> uuid {
81 return uuid{null_uui_tag{}};
82 }
83
84 auto operator==(const uuid& other) const noexcept -> bool {
85 return _value == other._value;
86 }
87
88 // operator std::string() const {
89 // return fmt::format(
90 // "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
91 // _bytes[0], _bytes[1], _bytes[2], _bytes[3], _bytes[4], _bytes[5], _bytes[6], _bytes[7],
92 // _bytes[8], _bytes[9], _bytes[10], _bytes[11], _bytes[12], _bytes[13], _bytes[14], _bytes[15]
93 // );
94 // }
95
96 operator value_type() const {
97 return _value;
98 }
99
100private:
101
102 uuid(null_uui_tag)
103 : _value{0} { }
104
105 // std::array<std::uint8_t, 16u> _bytes;
106 value_type _value;
107
108}; // class uuid
109
110} // namespace sbx::math
111
112template<>
113struct fmt::formatter<sbx::math::uuid> {
114
115 template<typename ParseContext>
116 constexpr auto parse(ParseContext& context) -> decltype(context.begin()) {
117 return context.begin();
118 }
119
120 template<typename FormatContext>
121 auto format(const sbx::math::uuid& uuid, FormatContext& context) -> decltype(context.out()) {
122 return fmt::format_to(context.out(), "{}", static_cast<sbx::math::uuid::value_type>(uuid));
123 }
124}; // struct fmt::formatter<sbx::math::uuid>
125
126// template<>
127// struct YAML::convert<sbx::math::uuid> {
128
129// static auto encode(const sbx::math::uuid& rhs) -> YAML::Node {
130// return Node{std::string{rhs}};
131// }
132
133// static auto decode(const YAML::Node& node, sbx::math::uuid& rhs) -> bool {
134// rhs = sbx::math::uuid{node.as<std::string>()};
135
136// return true;
137// }
138
139// }; // struct YAML::convert<sbx::math::uuid>
140
141template<>
142struct std::hash<sbx::math::uuid> {
143 auto operator()(const sbx::math::uuid& uuid) const noexcept -> std::size_t {
144 return static_cast<sbx::math::uuid::value_type>(uuid);
145 }
146}; // struct std::hash<sbx::math::uuid>
147
148#else // SBX_MATH_UUID_USE_V4
149
150#include <cinttypes>
151#include <concepts>
152
153#include <fmt/format.h>
154
155#include <libsbx/math/random.hpp>
156
157namespace sbx::math {
158
159template<std::unsigned_integral Type>
161
162public:
163
164 using value_type = Type;
165
166 basic_uuid()
167 : _value{random::next<value_type>()} { }
168
169 static constexpr auto null() -> basic_uuid {
170 return basic_uuid{0u};
171 }
172
173 static constexpr auto from_value(const value_type value) -> basic_uuid {
174 return basic_uuid{value};
175 }
176
177 static constexpr auto create() -> basic_uuid {
178 return basic_uuid{random::next<value_type>()};
179 }
180
181 constexpr auto operator==(const basic_uuid& other) const noexcept -> bool {
182 return _value == other._value;
183 }
184
185 constexpr auto operator<(const basic_uuid& other) const noexcept -> bool {
186 return _value < other._value;
187 }
188
189 constexpr auto value() const noexcept -> value_type {
190 return _value;
191 }
192
193private:
194
195 basic_uuid(const value_type value)
196 : _value{value} { }
197
198 value_type _value;
199
200}; // class uuid
201
203
204} // namespace sbx::math
205
206template<std::unsigned_integral Type>
207struct fmt::formatter<sbx::math::basic_uuid<Type>> {
208
209 template<typename ParseContext>
210 constexpr auto parse(ParseContext& context) -> decltype(context.begin()) {
211 return context.begin();
212 }
213
214 template<typename FormatContext>
215 auto format(const sbx::math::basic_uuid<Type>& uuid, FormatContext& context) const -> decltype(context.out()) {
216 static constexpr auto width = sizeof(Type) * 2;
217
218 return fmt::format_to(context.out(), "{:0{}x}", uuid.value(), width);
219 }
220}; // struct fmt::formatter<sbx::math::uuid>
221
222
223template<std::unsigned_integral Type>
224struct std::hash<sbx::math::basic_uuid<Type>> {
225 auto operator()(const sbx::math::basic_uuid<Type>& uuid) const noexcept -> std::size_t {
226 return uuid.value();
227 }
228}; // struct std::hash<sbx::math::uuid>
229
230#endif // SBX_MATH_UUID_USE_V4
231
232#endif // LIBSBX_MATH_UUID_HPP_
233
Definition: uuid.hpp:160