| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_LIB_UUID_UUID_H_ |
| #define SRC_LIB_UUID_UUID_H_ |
| |
| #include <stdint.h> |
| |
| #include <iosfwd> |
| #include <optional> |
| #include <string> |
| |
| namespace uuid { |
| |
| // Number of bytes in a UUID. |
| constexpr size_t kUuidSize = 16; |
| |
| // The internal components of a UUID. |
| // |
| // c.f., RFC 4122 Section 4.1.2. |
| // |
| // Most users should the |Uuid| type directly, below. |
| struct RawUuid { |
| uint32_t time_low; |
| uint16_t time_mid; |
| uint16_t time_hi_and_version; |
| uint8_t clock_seq_hi_and_reserved; |
| uint8_t clock_seq_low; |
| uint8_t node[6]; |
| }; |
| |
| static_assert(sizeof(RawUuid) == kUuidSize); |
| |
| // A Universally Unique Identifier (UUID) or, equivalently, a Globally Unique |
| // Identifier (GUID) is a 128-bit identifier. UUIDs can be independently |
| // generated while having strong guarantees that no two generated UUIDs will |
| // have the same value. |
| // |
| // The format and algorithm for generating UUID is described in RFC 4122. |
| class Uuid { |
| public: |
| // Generate the empty UUID ("00000000-0000-0000-0000-000000000000"). |
| constexpr Uuid() : raw_{} {} |
| |
| // Generate a UUID from the given 16-byte array. |
| // |
| // We assume that the buffer is stored in host-native endian order. |
| explicit Uuid(const uint8_t* buffer) { memcpy(&raw_, buffer, kUuidSize); } |
| |
| // Generate a UUID from a RawUuid. |
| constexpr explicit Uuid(RawUuid raw) : raw_(raw) {} |
| |
| // Generate a UUID from the given 16 bytes. |
| // |
| // This constructor can be used to generate compile-time constant UUIDs: |
| // |
| // constexpr Uuid kMyUuid = {0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, |
| // 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; |
| // |
| // The input bytes are assumed to be in host-native endian format. |
| constexpr Uuid(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, |
| uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10, uint8_t b11, uint8_t b12, |
| uint8_t b13, uint8_t b14, uint8_t b15) |
| : bytes_{b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15} {} |
| |
| // Generate a new v4 UUID. |
| // |
| // This method generates a version 4 (random) UUID, using 122 bits of entropy |
| // provided by the kernel. The algorithm is described in RFC 4122, |
| // section 4.4. |
| static Uuid Generate(); |
| |
| // Parse a UUID of the format returned by ToString. |
| // Returns std::nullopt if the string was invalid. |
| static std::optional<Uuid> FromString(std::string_view uuid); |
| |
| // Generate a string representation of this UUID. The returned string will |
| // be of the form: |
| // |
| // 00112233-4455-6677-8899-aabbccddeeff |
| // |
| std::string ToString() const; |
| |
| // Raw bytes of the UUID, in host-endian format. |
| const uint8_t* bytes() const { return bytes_; } |
| |
| // Raw fields of the UUID. |
| const RawUuid& raw() const { return raw_; } |
| |
| private: |
| union { |
| RawUuid raw_; |
| uint8_t bytes_[kUuidSize]; |
| }; |
| }; |
| |
| static_assert(sizeof(Uuid) == kUuidSize); |
| |
| // Equality / inequality. |
| inline bool operator==(const Uuid& a, const Uuid& b) { |
| return memcmp(a.bytes(), b.bytes(), kUuidSize) == 0; |
| } |
| inline bool operator!=(const Uuid& a, const Uuid& b) { return !(a == b); } |
| |
| // Writes Uuid.ToString() to the given stream. |
| std::ostream& operator<<(std::ostream& out, const Uuid& uuid); |
| |
| // Generate a 128-bit (pseudo) random UUID in the form of version 4 as described |
| // in RFC 4122, section 4.4. |
| // The format of UUID version 4 must be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, |
| // where y is one of [8, 9, A, B]. |
| // The hexadecimal values "a" through "f" are output as lower case characters. |
| std::string Generate(); |
| |
| // Returns true if the input string conforms to the version 4 UUID format. |
| // Note that this does NOT check if the hexadecimal values "a" through "f" |
| // are in lower case characters, as Version 4 RFC says they're |
| // case insensitive. (Use IsValidOutputString for checking if the |
| // given string is valid output string) |
| bool IsValid(const std::string& guid); |
| |
| // Returns true if the input string is valid version 4 UUID output string. |
| // This also checks if the hexadecimal values "a" through "f" are in lower |
| // case characters. |
| bool IsValidOutputString(const std::string& guid); |
| |
| } // namespace uuid |
| |
| #endif // SRC_LIB_UUID_UUID_H_ |