Skip to content

Commit d932f28

Browse files
motiz88meta-codesync[bot]
authored andcommitted
Add generateRandomUuidString C++ helper (#54089)
Summary: Pull Request resolved: #54089 Changelog: [Internal] Adds a minimal standards-compliant UUID v4 generator to `react/utils` for use elsewhere in React Native. We don't need UUID parsing, support for UUID versions other than 4, a UUID value type, or extremely high performance - which makes inlining this simple, portable implementation directly in our codebase acceptable. Reviewed By: robhogan Differential Revision: D84149720 fbshipit-source-id: 399d88f4adaff3be4fef5dd1abab3c8552ca1a75
1 parent 9afd6bb commit d932f28

3 files changed

Lines changed: 117 additions & 0 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include "Uuid.h"
9+
10+
#include <array>
11+
#include <iomanip>
12+
#include <random>
13+
#include <sstream>
14+
15+
namespace {
16+
17+
std::mt19937& getThreadLocalEngine() {
18+
static thread_local std::random_device device;
19+
static thread_local std::mt19937 engine(device());
20+
return engine;
21+
}
22+
23+
uint64_t randomUInt64(uint64_t max = std::numeric_limits<uint64_t>::max()) {
24+
std::uniform_int_distribution<uint64_t> distribution(0, max);
25+
return distribution(getThreadLocalEngine());
26+
}
27+
28+
} // namespace
29+
30+
namespace facebook::react {
31+
32+
std::string generateRandomUuidString() {
33+
static constexpr uint8_t kUuidLength = 16;
34+
// see: https://tools.ietf.org/html/rfc4122#section-4.1.2 for reference
35+
static constexpr uint8_t kTimeLowSegBufEnd = sizeof(uint32_t);
36+
static constexpr uint8_t kTimeMidSegBufEnd =
37+
kTimeLowSegBufEnd + sizeof(uint16_t);
38+
static constexpr uint8_t kTimeHiAndVersionSegBufEnd =
39+
kTimeMidSegBufEnd + sizeof(uint16_t);
40+
static constexpr uint8_t kClockHiLoSegBufEnd =
41+
kTimeHiAndVersionSegBufEnd + sizeof(uint16_t);
42+
static constexpr uint8_t kNodeSegHiBufEnd =
43+
kClockHiLoSegBufEnd + sizeof(uint16_t);
44+
45+
std::array<uint8_t, kUuidLength> uuidBytes;
46+
47+
*(uint64_t*)uuidBytes.data() = randomUInt64();
48+
*(uint64_t*)(uuidBytes.data() + sizeof(uint64_t)) = randomUInt64();
49+
50+
// Conforming to RFC 4122: https://www.cryptosys.net/pki/uuid-rfc4122.html
51+
uuidBytes[7] &= 0x0f;
52+
uuidBytes[7] |= 0x40;
53+
uuidBytes[9] &= 0x3f;
54+
uuidBytes[9] |= 0x80;
55+
56+
std::stringstream ss;
57+
58+
ss << std::setfill('0') << std::setw(8) << std::right << std::hex
59+
<< *(uint32_t*)uuidBytes.data() << "-" << std::setw(4)
60+
<< *(uint16_t*)(uuidBytes.data() + kTimeLowSegBufEnd) << "-"
61+
<< *(uint16_t*)(uuidBytes.data() + kTimeMidSegBufEnd) << "-"
62+
<< *(uint16_t*)(uuidBytes.data() + kTimeHiAndVersionSegBufEnd) << "-"
63+
<< std::setw(8) << *(uint32_t*)(uuidBytes.data() + kNodeSegHiBufEnd)
64+
<< std::setw(4) << *(uint16_t*)(uuidBytes.data() + kClockHiLoSegBufEnd);
65+
66+
return ss.str();
67+
}
68+
69+
} // namespace facebook::react
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <string>
11+
12+
namespace facebook::react {
13+
14+
/**
15+
* Generates a random UUID version 4 string in the format
16+
* xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (lowercase).
17+
*/
18+
std::string generateRandomUuidString();
19+
20+
} // namespace facebook::react
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <react/utils/Uuid.h>
9+
10+
#include <gmock/gmock.h>
11+
#include <gtest/gtest.h>
12+
13+
using namespace ::testing;
14+
15+
namespace facebook::react {
16+
17+
TEST(UuidTest, TestGenerateRandomUuidString) {
18+
static constexpr auto kUuidV4Regex =
19+
"[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}";
20+
21+
std::string uuid1 = generateRandomUuidString();
22+
std::string uuid2 = generateRandomUuidString();
23+
EXPECT_THAT(uuid1, MatchesRegex(kUuidV4Regex));
24+
EXPECT_THAT(uuid2, MatchesRegex(kUuidV4Regex));
25+
EXPECT_NE(uuid1, uuid2);
26+
}
27+
28+
} // namespace facebook::react

0 commit comments

Comments
 (0)