uuid.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // Copyright 2018 Google Inc. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package uuid
  5. import (
  6. "bytes"
  7. "crypto/rand"
  8. "encoding/hex"
  9. "errors"
  10. "fmt"
  11. "io"
  12. "strings"
  13. "sync"
  14. )
  15. // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
  16. // 4122.
  17. type UUID [16]byte
  18. // A Version represents a UUID's version.
  19. type Version byte
  20. // A Variant represents a UUID's variant.
  21. type Variant byte
  22. // Constants returned by Variant.
  23. const (
  24. Invalid = Variant(iota) // Invalid UUID
  25. RFC4122 // The variant specified in RFC4122
  26. Reserved // Reserved, NCS backward compatibility.
  27. Microsoft // Reserved, Microsoft Corporation backward compatibility.
  28. Future // Reserved for future definition.
  29. )
  30. const randPoolSize = 16 * 16
  31. var (
  32. rander = rand.Reader // random function
  33. poolEnabled = false
  34. poolMu sync.Mutex
  35. poolPos = randPoolSize // protected with poolMu
  36. pool [randPoolSize]byte // protected with poolMu
  37. )
  38. type invalidLengthError struct{ len int }
  39. func (err invalidLengthError) Error() string {
  40. return fmt.Sprintf("invalid UUID length: %d", err.len)
  41. }
  42. // IsInvalidLengthError is matcher function for custom error invalidLengthError
  43. func IsInvalidLengthError(err error) bool {
  44. _, ok := err.(invalidLengthError)
  45. return ok
  46. }
  47. // Parse decodes s into a UUID or returns an error if it cannot be parsed. Both
  48. // the standard UUID forms defined in RFC 4122
  49. // (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
  50. // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are decoded. In addition,
  51. // Parse accepts non-standard strings such as the raw hex encoding
  52. // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and 38 byte "Microsoft style" encodings,
  53. // e.g. {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. Only the middle 36 bytes are
  54. // examined in the latter case. Parse should not be used to validate strings as
  55. // it parses non-standard encodings as indicated above.
  56. func Parse(s string) (UUID, error) {
  57. var uuid UUID
  58. switch len(s) {
  59. // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  60. case 36:
  61. // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  62. case 36 + 9:
  63. if !strings.EqualFold(s[:9], "urn:uuid:") {
  64. return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
  65. }
  66. s = s[9:]
  67. // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
  68. case 36 + 2:
  69. s = s[1:]
  70. // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  71. case 32:
  72. var ok bool
  73. for i := range uuid {
  74. uuid[i], ok = xtob(s[i*2], s[i*2+1])
  75. if !ok {
  76. return uuid, errors.New("invalid UUID format")
  77. }
  78. }
  79. return uuid, nil
  80. default:
  81. return uuid, invalidLengthError{len(s)}
  82. }
  83. // s is now at least 36 bytes long
  84. // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  85. if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
  86. return uuid, errors.New("invalid UUID format")
  87. }
  88. for i, x := range [16]int{
  89. 0, 2, 4, 6,
  90. 9, 11,
  91. 14, 16,
  92. 19, 21,
  93. 24, 26, 28, 30, 32, 34,
  94. } {
  95. v, ok := xtob(s[x], s[x+1])
  96. if !ok {
  97. return uuid, errors.New("invalid UUID format")
  98. }
  99. uuid[i] = v
  100. }
  101. return uuid, nil
  102. }
  103. // ParseBytes is like Parse, except it parses a byte slice instead of a string.
  104. func ParseBytes(b []byte) (UUID, error) {
  105. var uuid UUID
  106. switch len(b) {
  107. case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  108. case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  109. if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) {
  110. return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
  111. }
  112. b = b[9:]
  113. case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
  114. b = b[1:]
  115. case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  116. var ok bool
  117. for i := 0; i < 32; i += 2 {
  118. uuid[i/2], ok = xtob(b[i], b[i+1])
  119. if !ok {
  120. return uuid, errors.New("invalid UUID format")
  121. }
  122. }
  123. return uuid, nil
  124. default:
  125. return uuid, invalidLengthError{len(b)}
  126. }
  127. // s is now at least 36 bytes long
  128. // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  129. if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
  130. return uuid, errors.New("invalid UUID format")
  131. }
  132. for i, x := range [16]int{
  133. 0, 2, 4, 6,
  134. 9, 11,
  135. 14, 16,
  136. 19, 21,
  137. 24, 26, 28, 30, 32, 34,
  138. } {
  139. v, ok := xtob(b[x], b[x+1])
  140. if !ok {
  141. return uuid, errors.New("invalid UUID format")
  142. }
  143. uuid[i] = v
  144. }
  145. return uuid, nil
  146. }
  147. // MustParse is like Parse but panics if the string cannot be parsed.
  148. // It simplifies safe initialization of global variables holding compiled UUIDs.
  149. func MustParse(s string) UUID {
  150. uuid, err := Parse(s)
  151. if err != nil {
  152. panic(`uuid: Parse(` + s + `): ` + err.Error())
  153. }
  154. return uuid
  155. }
  156. // FromBytes creates a new UUID from a byte slice. Returns an error if the slice
  157. // does not have a length of 16. The bytes are copied from the slice.
  158. func FromBytes(b []byte) (uuid UUID, err error) {
  159. err = uuid.UnmarshalBinary(b)
  160. return uuid, err
  161. }
  162. // Must returns uuid if err is nil and panics otherwise.
  163. func Must(uuid UUID, err error) UUID {
  164. if err != nil {
  165. panic(err)
  166. }
  167. return uuid
  168. }
  169. // String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  170. // , or "" if uuid is invalid.
  171. func (uuid UUID) String() string {
  172. var buf [36]byte
  173. encodeHex(buf[:], uuid)
  174. return string(buf[:])
  175. }
  176. // URN returns the RFC 2141 URN form of uuid,
  177. // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
  178. func (uuid UUID) URN() string {
  179. var buf [36 + 9]byte
  180. copy(buf[:], "urn:uuid:")
  181. encodeHex(buf[9:], uuid)
  182. return string(buf[:])
  183. }
  184. func encodeHex(dst []byte, uuid UUID) {
  185. hex.Encode(dst, uuid[:4])
  186. dst[8] = '-'
  187. hex.Encode(dst[9:13], uuid[4:6])
  188. dst[13] = '-'
  189. hex.Encode(dst[14:18], uuid[6:8])
  190. dst[18] = '-'
  191. hex.Encode(dst[19:23], uuid[8:10])
  192. dst[23] = '-'
  193. hex.Encode(dst[24:], uuid[10:])
  194. }
  195. // Variant returns the variant encoded in uuid.
  196. func (uuid UUID) Variant() Variant {
  197. switch {
  198. case (uuid[8] & 0xc0) == 0x80:
  199. return RFC4122
  200. case (uuid[8] & 0xe0) == 0xc0:
  201. return Microsoft
  202. case (uuid[8] & 0xe0) == 0xe0:
  203. return Future
  204. default:
  205. return Reserved
  206. }
  207. }
  208. // Version returns the version of uuid.
  209. func (uuid UUID) Version() Version {
  210. return Version(uuid[6] >> 4)
  211. }
  212. func (v Version) String() string {
  213. if v > 15 {
  214. return fmt.Sprintf("BAD_VERSION_%d", v)
  215. }
  216. return fmt.Sprintf("VERSION_%d", v)
  217. }
  218. func (v Variant) String() string {
  219. switch v {
  220. case RFC4122:
  221. return "RFC4122"
  222. case Reserved:
  223. return "Reserved"
  224. case Microsoft:
  225. return "Microsoft"
  226. case Future:
  227. return "Future"
  228. case Invalid:
  229. return "Invalid"
  230. }
  231. return fmt.Sprintf("BadVariant%d", int(v))
  232. }
  233. // SetRand sets the random number generator to r, which implements io.Reader.
  234. // If r.Read returns an error when the package requests random data then
  235. // a panic will be issued.
  236. //
  237. // Calling SetRand with nil sets the random number generator to the default
  238. // generator.
  239. func SetRand(r io.Reader) {
  240. if r == nil {
  241. rander = rand.Reader
  242. return
  243. }
  244. rander = r
  245. }
  246. // EnableRandPool enables internal randomness pool used for Random
  247. // (Version 4) UUID generation. The pool contains random bytes read from
  248. // the random number generator on demand in batches. Enabling the pool
  249. // may improve the UUID generation throughput significantly.
  250. //
  251. // Since the pool is stored on the Go heap, this feature may be a bad fit
  252. // for security sensitive applications.
  253. //
  254. // Both EnableRandPool and DisableRandPool are not thread-safe and should
  255. // only be called when there is no possibility that New or any other
  256. // UUID Version 4 generation function will be called concurrently.
  257. func EnableRandPool() {
  258. poolEnabled = true
  259. }
  260. // DisableRandPool disables the randomness pool if it was previously
  261. // enabled with EnableRandPool.
  262. //
  263. // Both EnableRandPool and DisableRandPool are not thread-safe and should
  264. // only be called when there is no possibility that New or any other
  265. // UUID Version 4 generation function will be called concurrently.
  266. func DisableRandPool() {
  267. poolEnabled = false
  268. defer poolMu.Unlock()
  269. poolMu.Lock()
  270. poolPos = randPoolSize
  271. }
  272. // UUIDs is a slice of UUID types.
  273. type UUIDs []UUID
  274. // Strings returns a string slice containing the string form of each UUID in uuids.
  275. func (uuids UUIDs) Strings() []string {
  276. var uuidStrs = make([]string, len(uuids))
  277. for i, uuid := range uuids {
  278. uuidStrs[i] = uuid.String()
  279. }
  280. return uuidStrs
  281. }