PageRenderTime 35ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/github.com/twinj/uuid/uuid.go

https://bitbucket.org/seobutik/push-tracker
Go | 268 lines | 161 code | 40 blank | 67 comment | 28 complexity | 3bebd47e968dfc2b1fc45713f7d0a295 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, BSD-2-Clause
  1. // This package provides RFC4122 and DCE 1.1 UUIDs.
  2. //
  3. // Use NewV1, NewV2, NewV3, NewV4, NewV5, for generating new UUIDs.
  4. //
  5. // Use New([]byte), NewHex(string), and Parse(string) for
  6. // creating UUIDs from existing data.
  7. //
  8. // If you have a []byte you can simply cast it to the Uuid type.
  9. //
  10. // The original version was from Krzysztof Kowalik <chris@nu7hat.ch>
  11. // Unfortunately, that version was non compliant with RFC4122.
  12. //
  13. // The package has since been redesigned.
  14. //
  15. // The example code in the specification was also used as reference
  16. // for design.
  17. //
  18. // Copyright (C) 2016 twinj@github.com 2016 MIT licence
  19. package uuid
  20. import (
  21. "bytes"
  22. "crypto/md5"
  23. "crypto/sha1"
  24. "encoding/binary"
  25. "encoding/hex"
  26. "errors"
  27. "hash"
  28. "log"
  29. "regexp"
  30. )
  31. const (
  32. Nil Immutable = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  33. // The following standard UUIDs are for use with V3 or V5 UUIDs.
  34. NameSpaceDNS Immutable = "k\xa7\xb8\x10\x9d\xad\x11р\xb4\x00\xc0O\xd40\xc8"
  35. NameSpaceURL Immutable = "k\xa7\xb8\x11\x9d\xad\x11р\xb4\x00\xc0O\xd40\xc8"
  36. NameSpaceOID Immutable = "k\xa7\xb8\x12\x9d\xad\x11р\xb4\x00\xc0O\xd40\xc8"
  37. NameSpaceX500 Immutable = "k\xa7\xb8\x14\x9d\xad\x11р\xb4\x00\xc0O\xd40\xc8"
  38. )
  39. type Domain uint8
  40. const (
  41. DomainUser Domain = iota + 1
  42. DomainGroup
  43. )
  44. // UUID is the common interface implemented by all UUIDs
  45. type UUID interface {
  46. // Bytes retrieves the bytes from the underlying UUID
  47. Bytes() []byte
  48. // Size is the length of the underlying UUID implementation
  49. Size() int
  50. // String should return the canonical UUID representation, or the a
  51. // given uuid.Format
  52. String() string
  53. // Variant returns the UUID implementation variant
  54. Variant() uint8
  55. // Version returns the version number of the algorithm used to generate
  56. // the UUID.
  57. Version() Version
  58. }
  59. // New creates a UUID from a slice of bytes.
  60. func New(pData []byte) Uuid {
  61. o := array{}
  62. o.unmarshal(pData)
  63. return o[:]
  64. }
  65. // NewHex creates a UUID from a hex string
  66. // Will panic if hex string is invalid use Parse otherwise.
  67. func NewHex(pUuid string) Uuid {
  68. return Uuid(fromHex(pUuid))
  69. }
  70. const (
  71. // Pattern used to parse string representation of the UUID.
  72. // Current one allows to parse string where only one opening
  73. // or closing bracket or any of the hyphens are optional.
  74. // It is only used to extract the main bytes to create a UUID,
  75. // so these imperfections are of no consequence.
  76. hexPattern = `^(urn\:uuid\:)?[\{\(\[]?([[:xdigit:]]{8})-?([[:xdigit:]]{4})-?([1-5][[:xdigit:]]{3})-?([[:xdigit:]]{4})-?([[:xdigit:]]{12})[\]\}\)]?$`
  77. )
  78. var (
  79. parseUUIDRegex = regexp.MustCompile(hexPattern)
  80. )
  81. // Parse creates a UUID from a valid string representation.
  82. // Accepts UUID string in following formats:
  83. // 6ba7b8149dad11d180b400c04fd430c8
  84. // 6ba7b814-9dad-11d1-80b4-00c04fd430c8
  85. // {6ba7b814-9dad-11d1-80b4-00c04fd430c8}
  86. // urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8
  87. // [6ba7b814-9dad-11d1-80b4-00c04fd430c8]
  88. // (6ba7b814-9dad-11d1-80b4-00c04fd430c8)
  89. //
  90. func Parse(pUuid string) (Uuid, error) {
  91. id, err := parse(pUuid)
  92. return Uuid(id), err
  93. }
  94. func parse(pUuid string) ([]byte, error) {
  95. md := parseUUIDRegex.FindStringSubmatch(pUuid)
  96. if md == nil {
  97. return nil, errors.New("uuid.Parse: invalid string format this is probably not a UUID")
  98. }
  99. return fromHex(md[2] + md[3] + md[4] + md[5] + md[6]), nil
  100. }
  101. func fromHex(pUuid string) []byte {
  102. bytes, err := hex.DecodeString(pUuid)
  103. if err != nil {
  104. panic(err)
  105. }
  106. return bytes
  107. }
  108. // NewV1 generates a new RFC4122 version 1 UUID based on a 60 bit timestamp and
  109. // node ID.
  110. func NewV1() Uuid {
  111. return generator.NewV1()
  112. }
  113. // NewV2 generates a new DCE Security version UUID based on a 60 bit timestamp,
  114. // node id and POSIX UID.
  115. func NewV2(pDomain Domain) Uuid {
  116. return generator.NewV2(pDomain)
  117. }
  118. // NewV3 generates a new RFC4122 version 3 UUID based on the MD5 hash on a
  119. // namespace UUID and any type which implements the UniqueName interface
  120. // for the name. For strings and slices cast to a Name type
  121. func NewV3(pNamespace UUID, pNames ...UniqueName) Uuid {
  122. o := array{}
  123. copy(o[:], digest(md5.New(), pNamespace.Bytes(), pNames...))
  124. o.setRFC4122Version(3)
  125. return o[:]
  126. }
  127. // NewV4 generates a new RFC4122 version 4 UUID a cryptographically secure
  128. // random UUID.
  129. func NewV4() Uuid {
  130. o, err := v4()
  131. if err == nil {
  132. return o[:]
  133. }
  134. generator.err = err
  135. log.Printf("uuid.V4: There was an error getting random bytes [%s]\n", err)
  136. if ok := generator.HandleError(err); ok {
  137. o, err = v4()
  138. if err == nil {
  139. return o[:]
  140. }
  141. generator.err = err
  142. }
  143. return nil
  144. }
  145. func v4() (o array, err error) {
  146. generator.err = nil
  147. _, err = generator.Random(o[:])
  148. o.setRFC4122Version(4)
  149. return
  150. }
  151. // NewV5 generates an RFC4122 version 5 UUID based on the SHA-1 hash of a
  152. // namespace UUID and a unique name.
  153. func NewV5(pNamespace UUID, pNames ...UniqueName) Uuid {
  154. o := array{}
  155. copy(o[:], digest(sha1.New(), pNamespace.Bytes(), pNames...))
  156. o.setRFC4122Version(5)
  157. return o[:]
  158. }
  159. func digest(pHash hash.Hash, pName []byte, pNames ...UniqueName) []byte {
  160. for _, v := range pNames {
  161. pName = append(pName, v.String()...)
  162. }
  163. pHash.Write(pName)
  164. return pHash.Sum(nil)
  165. }
  166. // Compare returns an integer comparing two UUIDs lexicographically.
  167. // The result will be 0 if pId==pId2, -1 if pId < pId2, and +1 if pId > pId2.
  168. // A nil argument is equivalent to the Nil UUID.
  169. func Compare(pId, pId2 UUID) int {
  170. var b1, b2 []byte
  171. if pId == nil {
  172. b1 = []byte(Nil)
  173. } else {
  174. b1 = pId.Bytes()
  175. }
  176. if pId2 == nil {
  177. b2 = []byte(Nil)
  178. } else {
  179. b2 = pId2.Bytes()
  180. }
  181. tl1 := binary.BigEndian.Uint32(b1[:4])
  182. tl2 := binary.BigEndian.Uint32(b2[:4])
  183. if tl1 != tl2 {
  184. if tl1 < tl2 {
  185. return -1
  186. } else {
  187. return 1
  188. }
  189. }
  190. m1 := binary.BigEndian.Uint16(b1[4:6])
  191. m2 := binary.BigEndian.Uint16(b2[4:6])
  192. if m1 != m2 {
  193. if m1 < m2 {
  194. return -1
  195. } else {
  196. return 1
  197. }
  198. }
  199. m1 = binary.BigEndian.Uint16(b1[6:8])
  200. m2 = binary.BigEndian.Uint16(b2[6:8])
  201. if m1 != m2 {
  202. if m1 < m2 {
  203. return -1
  204. } else {
  205. return 1
  206. }
  207. }
  208. return bytes.Compare(b1[8:], b2[8:])
  209. }
  210. // Compares whether each UUID is the same
  211. func Equal(p1, p2 UUID) bool {
  212. return bytes.Equal(p1.Bytes(), p2.Bytes())
  213. }
  214. // Name is a string which implements UniqueName and satisfies the Stringer
  215. // interface. V3 and V5 UUIDs use this for hashing values together to produce
  216. // UUIDs based on a NameSpace.
  217. type Name string
  218. // String returns the uuid.Name as a string.
  219. func (o Name) String() string {
  220. return string(o)
  221. }
  222. // UniqueName is a Stinger interface made for easy passing of any Stringer type
  223. // into a Hashable UUID.
  224. type UniqueName interface {
  225. // Many go types implement this method for use with printing
  226. // Will convert the current type to its native string format
  227. String() string
  228. }