github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/uuid/uuid.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 // Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru> 12 // Use of this source code is governed by a MIT-style 13 // license that can be found in licenses/MIT-gofrs.txt. 14 15 // This code originated in github.com/gofrs/uuid. 16 17 package uuid 18 19 import ( 20 "encoding/binary" 21 "encoding/hex" 22 "fmt" 23 "math" 24 "time" 25 26 "github.com/cockroachdb/cockroachdb-parser/pkg/util/timeutil" 27 "github.com/cockroachdb/cockroachdb-parser/pkg/util/uint128" 28 "github.com/cockroachdb/errors" 29 ) 30 31 // Size of a UUID in bytes. 32 const Size = 16 33 34 // RFC4122StrSize of a size of the RFC-4122 string representation of UUID. 35 const RFC4122StrSize = 36 36 37 // Bytes represents a byte slice which is intended to be interpreted as a binary 38 // encoding of a UUID. 39 type Bytes []byte 40 41 // GetUUID constructs a UUID from the bytes. If the data is not valid, a zero 42 // value will be returned. 43 func (b Bytes) GetUUID() UUID { return FromBytesOrNil(b) } 44 45 // String returns the string representation of the underlying UUID. 46 func (b Bytes) String() string { 47 return b.GetUUID().String() 48 } 49 50 // UUID is an array type to represent the value of a UUID, as defined in RFC-4122. 51 type UUID [Size]byte 52 53 // UUID versions. 54 const ( 55 _ byte = iota 56 V1 // Version 1 (date-time and MAC address) 57 _ // Version 2 (date-time and MAC address, DCE security version) 58 V3 // Version 3 (namespace name-based) 59 V4 // Version 4 (random) 60 V5 // Version 5 (namespace name-based) 61 ) 62 63 // UUID layout variants. 64 const ( 65 VariantNCS byte = iota 66 VariantRFC4122 67 VariantMicrosoft 68 VariantFuture 69 ) 70 71 // Timestamp is the count of 100-nanosecond intervals since 00:00:00.00, 72 // 15 October 1582 within a V1 UUID. This type has no meaning for V2-V5 73 // UUIDs since they don't have an embedded timestamp. 74 type Timestamp uint64 75 76 const _100nsPerSecond = 10000000 77 78 // Time returns the UTC time.Time representation of a Timestamp 79 func (t Timestamp) Time() (time.Time, error) { 80 secs := uint64(t) / _100nsPerSecond 81 nsecs := 100 * (uint64(t) % _100nsPerSecond) 82 return timeutil.Unix(int64(secs)-(epochStart/_100nsPerSecond), int64(nsecs)), nil 83 } 84 85 // TimestampFromV1 returns the Timestamp embedded within a V1 UUID. 86 // Returns an error if the UUID is any version other than 1. 87 func TimestampFromV1(u UUID) (Timestamp, error) { 88 if u.Version() != 1 { 89 err := fmt.Errorf("uuid: %s is version %d, not version 1", u, u.Version()) 90 return 0, err 91 } 92 low := binary.BigEndian.Uint32(u[0:4]) 93 mid := binary.BigEndian.Uint16(u[4:6]) 94 hi := binary.BigEndian.Uint16(u[6:8]) & 0xfff 95 return Timestamp(uint64(low) + (uint64(mid) << 32) + (uint64(hi) << 48)), nil 96 } 97 98 // String parse helpers. 99 var urnPrefix = []byte("urn:uuid:") 100 101 // Nil is the nil UUID, as specified in RFC-4122, which has all 128 bits set to 102 // zero. 103 var Nil = UUID{} 104 105 // Max is the maximum possible UUID, which has all 128 bits set to 1. 106 var Max = FromUint128(uint128.FromInts(math.MaxUint64, math.MaxUint64)) 107 108 // Predefined namespace UUIDs. 109 var ( 110 NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) 111 NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) 112 NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) 113 NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) 114 ) 115 116 // Version returns the algorithm version used to generate the UUID. 117 func (u UUID) Version() byte { 118 return u[6] >> 4 119 } 120 121 // Variant returns the UUID layout variant. 122 func (u UUID) Variant() byte { 123 switch { 124 case (u[8] >> 7) == 0x00: 125 return VariantNCS 126 case (u[8] >> 6) == 0x02: 127 return VariantRFC4122 128 case (u[8] >> 5) == 0x06: 129 return VariantMicrosoft 130 case (u[8] >> 5) == 0x07: 131 fallthrough 132 default: 133 return VariantFuture 134 } 135 } 136 137 // bytes returns a byte slice representation of the UUID. It incurs an 138 // allocation if the return value escapes. 139 func (u UUID) bytes() []byte { 140 return u[:] 141 } 142 143 // bytesMut returns a mutable byte slice representation of the UUID. Unlike 144 // bytes, it does not necessarily incur an allocation if the return value 145 // escapes. Instead, the return value escaping will cause the method's receiver 146 // (and any struct that it is a part of) to escape. 147 func (u *UUID) bytesMut() []byte { 148 return u[:] 149 } 150 151 // String returns a canonical RFC-4122 string representation of the UUID: 152 // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. 153 func (u UUID) String() string { 154 buf := make([]byte, RFC4122StrSize) 155 u.StringBytes(buf) 156 return string(buf) 157 } 158 159 // StringBytes writes the result of String directly into a buffer, which must 160 // have a length of at least 36. 161 func (u UUID) StringBytes(buf []byte) { 162 _ = buf[:RFC4122StrSize] 163 hex.Encode(buf[0:8], u[0:4]) 164 buf[8] = '-' 165 hex.Encode(buf[9:13], u[4:6]) 166 buf[13] = '-' 167 hex.Encode(buf[14:18], u[6:8]) 168 buf[18] = '-' 169 hex.Encode(buf[19:23], u[8:10]) 170 buf[23] = '-' 171 hex.Encode(buf[24:], u[10:]) 172 } 173 174 // SetVersion sets the version bits. 175 func (u *UUID) SetVersion(v byte) { 176 u[6] = (u[6] & 0x0f) | (v << 4) 177 } 178 179 // SetVariant sets the variant bits. 180 func (u *UUID) SetVariant(v byte) { 181 switch v { 182 case VariantNCS: 183 u[8] = (u[8]&(0xff>>1) | (0x00 << 7)) 184 case VariantRFC4122: 185 u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) 186 case VariantMicrosoft: 187 u[8] = (u[8]&(0xff>>3) | (0x06 << 5)) 188 case VariantFuture: 189 fallthrough 190 default: 191 u[8] = (u[8]&(0xff>>3) | (0x07 << 5)) 192 } 193 } 194 195 // Must is a helper that wraps a call to a function returning (UUID, error) 196 // and panics if the error is non-nil. It is intended for use in variable 197 // initializations such as 198 // 199 // var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000")) 200 func Must(u UUID, err error) UUID { 201 if err != nil { 202 panic(err) 203 } 204 return u 205 } 206 207 // DeterministicV4 overwrites this UUID with one computed deterministically to 208 // evenly fill the space of possible V4 UUIDs. `n` represents how many UUIDs 209 // will fill the space and `i` is an index into these `n` (and thus must be in 210 // the range `[0,n)`). The resulting UUIDs will be unique, evenly-spaced, and 211 // sorted. 212 func (u *UUID) DeterministicV4(i, n uint64) { 213 if i >= n { 214 panic(errors.Errorf(`i must be in [0,%d) was %d`, n, i)) 215 } 216 // V4 uuids are generated by simply filling 16 bytes with random data (then 217 // setting the version and variant), so they're randomly distributed through 218 // the space of possible values. This also means they're roughly evenly 219 // distributed. We guarantee these values to be similarly distributed. 220 // 221 // So, space the row indexes out to fill the space of the integers 222 // representable with 8 bytes. Then, because this involves some floats (and 223 // who knows what kind of crazy rounding things can happen when floats are 224 // involved), make sure they're unique by sticking the index 225 // in the lower 8 bytes. Note that we need to use BigEndian encodings to keep 226 // the uuids sorted in the same order as the ints. 227 spacing := uint64(float64(i) * float64(math.MaxUint64) / float64(n)) 228 binary.BigEndian.PutUint64(u[0:8], spacing) 229 binary.BigEndian.PutUint64(u[8:16], i) 230 u.SetVersion(V4) 231 u.SetVariant(VariantRFC4122) 232 }