|
|
@@ -6,10 +6,64 @@
|
|
|
|
|
|
#include <fmt/format.h>
|
|
|
|
|
|
+#include "common/assert.h"
|
|
|
#include "common/uuid.h"
|
|
|
|
|
|
namespace Common {
|
|
|
|
|
|
+namespace {
|
|
|
+
|
|
|
+bool IsHexDigit(char c) {
|
|
|
+ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
|
|
+}
|
|
|
+
|
|
|
+u8 HexCharToByte(char c) {
|
|
|
+ if (c >= '0' && c <= '9') {
|
|
|
+ return static_cast<u8>(c - '0');
|
|
|
+ }
|
|
|
+ if (c >= 'a' && c <= 'f') {
|
|
|
+ return static_cast<u8>(c - 'a' + 10);
|
|
|
+ }
|
|
|
+ if (c >= 'A' && c <= 'F') {
|
|
|
+ return static_cast<u8>(c - 'A' + 10);
|
|
|
+ }
|
|
|
+ ASSERT_MSG(false, "{} is not a hexadecimal digit!", c);
|
|
|
+ return u8{0};
|
|
|
+}
|
|
|
+
|
|
|
+} // Anonymous namespace
|
|
|
+
|
|
|
+u128 HexStringToU128(std::string_view hex_string) {
|
|
|
+ const size_t length = hex_string.length();
|
|
|
+
|
|
|
+ // Detect "0x" prefix.
|
|
|
+ const bool has_0x_prefix = length > 2 && hex_string[0] == '0' && hex_string[1] == 'x';
|
|
|
+ const size_t offset = has_0x_prefix ? 2 : 0;
|
|
|
+
|
|
|
+ // Check length.
|
|
|
+ if (length > 32 + offset) {
|
|
|
+ ASSERT_MSG(false, "hex_string has more than 32 hexadecimal characters!");
|
|
|
+ return INVALID_UUID;
|
|
|
+ }
|
|
|
+
|
|
|
+ u64 lo = 0;
|
|
|
+ u64 hi = 0;
|
|
|
+ for (size_t i = 0; i < length - offset; ++i) {
|
|
|
+ const char c = hex_string[length - 1 - i];
|
|
|
+ if (!IsHexDigit(c)) {
|
|
|
+ ASSERT_MSG(false, "{} is not a hexadecimal digit!", c);
|
|
|
+ return INVALID_UUID;
|
|
|
+ }
|
|
|
+ if (i < 16) {
|
|
|
+ lo |= u64{HexCharToByte(c)} << (i * 4);
|
|
|
+ }
|
|
|
+ if (i >= 16) {
|
|
|
+ hi |= u64{HexCharToByte(c)} << ((i - 16) * 4);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return u128{lo, hi};
|
|
|
+}
|
|
|
+
|
|
|
UUID UUID::Generate() {
|
|
|
std::random_device device;
|
|
|
std::mt19937 gen(device());
|