C/C++ API Reference
Loading...
Searching...
No Matches
uuid.h
1// Copyright 2025 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#pragma once
16
17#include <array>
18#include <cstddef>
19#include <cstdint>
20#include <string_view>
21
22#include "pw_assert/assert.h"
23#include "pw_bytes/span.h"
25#include "pw_result/result.h"
26#include "pw_status/status.h"
27#include "pw_string/hex.h"
28#include "pw_string/string.h"
29
31namespace pw::uuid {
32
34
36class Uuid {
37 public:
39 static constexpr size_t kSizeBytes = 16;
41 static constexpr size_t kStringSize =
42 std::string_view{"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}.size();
43
44 // Default constructor initializes the uuid to the Nil UUID
45 constexpr explicit Uuid() : uuid_() {}
46
53 constexpr explicit Uuid(span<const uint8_t, kSizeBytes> uuid_span) : uuid_() {
54 pw::copy(uuid_span.begin(), uuid_span.end(), uuid_.begin());
55 }
56
63 constexpr explicit Uuid(span<const std::byte, kSizeBytes> uuid_span)
64 : uuid_() {
65 // Manually copy to use static_cast which is constexpr
66 for (size_t i = 0; i < uuid_.size(); i++) {
67 uuid_[i] = static_cast<uint8_t>(uuid_span[i]);
68 }
69 }
70
74 static constexpr Result<Uuid> FromSpan(span<const uint8_t> uuid_span) {
75 if (uuid_span.size() != kSizeBytes) {
77 }
78 return Uuid(
79 span<const uint8_t, kSizeBytes>(uuid_span.data(), uuid_span.size()));
80 }
81
85 static constexpr Result<Uuid> FromSpan(ConstByteSpan uuid_span) {
86 if (uuid_span.size() != kSizeBytes) {
88 }
89 return Uuid(
90 span<const std::byte, kSizeBytes>(uuid_span.data(), uuid_span.size()));
91 }
92
99 template <size_t kSize, typename = std::enable_if_t<kSize == kSizeBytes>>
100 static constexpr Uuid FromSpan(const std::array<uint8_t, kSize>& uuid_array) {
101 return Uuid(uuid_array);
102 }
103
110 template <size_t kSize, typename = std::enable_if_t<kSize == kSizeBytes>>
111 static constexpr Uuid FromSpan(
112 const std::array<std::byte, kSize>& uuid_array) {
113 return Uuid(uuid_array);
114 }
115
122 template <size_t kSize, typename = std::enable_if_t<kSize == kSizeBytes>>
123 static constexpr Uuid FromSpan(const uint8_t (&uuid_array)[kSize]) {
124 return Uuid(span<const uint8_t, kSizeBytes>(uuid_array));
125 }
126
133 template <size_t kSize, typename = std::enable_if_t<kSize == kSizeBytes>>
134 static constexpr Uuid FromSpan(const std::byte (&uuid_array)[kSize]) {
135 return Uuid(span<const std::byte, kSizeBytes>(uuid_array));
136 }
137
141 static constexpr Result<Uuid> FromString(std::string_view string) {
142 Status status = ValidateString(string);
143 if (!status.ok()) {
144 return status;
145 }
146 return Uuid(string);
147 }
148
150 constexpr span<const uint8_t, kSizeBytes> GetSpan() const { return uuid_; }
151
152 constexpr bool operator==(const Uuid& other) const {
153 for (size_t i = 0; i < kSizeBytes; i++) {
154 if (uuid_[i] != other.uuid_[i]) {
155 return false;
156 }
157 }
158 return true;
159 }
160
161 constexpr bool operator!=(const Uuid& other) const {
162 return !(*this == other);
163 }
164
168
169 for (size_t i = uuid_.size(); i-- != 0;) {
170 out += string::NibbleToHex(uuid_[i] >> 4);
171 out += string::NibbleToHex(uuid_[i] & 0xf);
172 if ((i == 12) || (i == 10) || (i == 8) || (i == 6)) {
173 out += '-';
174 }
175 }
176 return out;
177 }
178
179 private:
183 constexpr explicit Uuid(std::string_view uuid_str) : uuid_() {
184 size_t out_hex_index = 2 * uuid_.size(); // UUID is stored little-endian.
185 for (size_t i = 0; i < kStringSize; i++) {
186 // Indices at which we expect to find a hyphen ('-') in a UUID string.
187 if (i == 8 || i == 13 || i == 18 || i == 23) {
188 PW_ASSERT(uuid_str[i] == '-');
189 continue;
190 }
191 PW_ASSERT(uuid_str[i] != '\0');
192
193 out_hex_index--;
194 uint16_t value = string::HexToNibble(uuid_str[i]);
195 PW_ASSERT(value <= 0xf);
196 if (out_hex_index % 2 == 0) {
197 uuid_[out_hex_index / 2] |= static_cast<uint8_t>(value);
198 } else {
199 uuid_[out_hex_index / 2] = static_cast<uint8_t>(value << 4);
200 }
201 }
202 }
203
212 static constexpr Status ValidateString(std::string_view uuid_str) {
213 if (kStringSize != uuid_str.size()) {
215 }
216 for (size_t i = 0; i < uuid_str.size(); i++) {
217 if (i == 8 || i == 13 || i == 18 || i == 23) {
218 if (uuid_str[i] != '-') {
220 }
221 continue;
222 }
223 if (string::IsHexDigit(uuid_str[i]) == 0) {
225 }
226 }
227 return OkStatus();
228 }
229
230 std::array<uint8_t, kSizeBytes> uuid_;
231};
232
233} // namespace pw::uuid
pw::InlineBasicString is a fixed-capacity version of std::basic_string. In brief:
Definition: string.h:68
Definition: result.h:143
Definition: status.h:120
static constexpr Status InvalidArgument()
Definition: status.h:164
constexpr bool ok() const
Definition: status.h:346
static constexpr Status FailedPrecondition()
Definition: status.h:243
Definition: span_impl.h:235
Represents a 128-bit universally unique identifier (UUID).
Definition: uuid.h:36
constexpr OutputIt copy(InputIt first, InputIt last, OutputIt d_first)
constexpr backport of <algorithm>'s std::copy for C++17.
Definition: algorithm.h:348
constexpr Status OkStatus()
Definition: status.h:450
static constexpr size_t kSizeBytes
Size of the UUID in bytes.
Definition: uuid.h:39
static constexpr Uuid FromSpan(const std::array< std::byte, kSize > &uuid_array)
Creates a Uuid from a std::array of 16 const bytes.
Definition: uuid.h:111
constexpr Uuid(span< const std::byte, kSizeBytes > uuid_span)
Creates a Uuid from a pw::span of 16 const std::byte.
Definition: uuid.h:63
static constexpr Uuid FromSpan(const std::array< uint8_t, kSize > &uuid_array)
Creates a Uuid from a std::array of 16 const uint8_t.
Definition: uuid.h:100
static constexpr Uuid FromSpan(const uint8_t(&uuid_array)[kSize])
Creates a Uuid from a C-style array of 16 const uint8_t.
Definition: uuid.h:123
static constexpr Uuid FromSpan(const std::byte(&uuid_array)[kSize])
Creates a Uuid from a C-style array of 16 const bytes.
Definition: uuid.h:134
static constexpr Result< Uuid > FromString(std::string_view string)
Create a Uuid from a string.
Definition: uuid.h:141
constexpr Uuid(span< const uint8_t, kSizeBytes > uuid_span)
Creates a Uuid from a pw::span of 16 const bytes.
Definition: uuid.h:53
static constexpr Result< Uuid > FromSpan(ConstByteSpan uuid_span)
Create a Uuid from a const std::byte span.
Definition: uuid.h:85
constexpr span< const uint8_t, kSizeBytes > GetSpan() const
Return the backing span holding the uuid.
Definition: uuid.h:150
constexpr InlineString< kStringSize > ToString() const
Convert the Uuid to a human readable string.
Definition: uuid.h:166
static constexpr size_t kStringSize
Length of the UUID's string representation.
Definition: uuid.h:41
static constexpr Result< Uuid > FromSpan(span< const uint8_t > uuid_span)
Create a Uuid from a const uint8_t span.
Definition: uuid.h:74
128-bit universally unique identifier library
Definition: uuid.h:31
pw::InlineBasicString and pw::InlineString are safer alternatives to std::basic_string and std::strin...