aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/nu7hatch/gouuid/uuid.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/nu7hatch/gouuid/uuid.go')
-rw-r--r--vendor/github.com/nu7hatch/gouuid/uuid.go173
1 files changed, 173 insertions, 0 deletions
diff --git a/vendor/github.com/nu7hatch/gouuid/uuid.go b/vendor/github.com/nu7hatch/gouuid/uuid.go
new file mode 100644
index 0000000..ac9623b
--- /dev/null
+++ b/vendor/github.com/nu7hatch/gouuid/uuid.go
@@ -0,0 +1,173 @@
+// This package provides immutable UUID structs and the functions
+// NewV3, NewV4, NewV5 and Parse() for generating versions 3, 4
+// and 5 UUIDs as specified in RFC 4122.
+//
+// Copyright (C) 2011 by Krzysztof Kowalik <chris@nu7hat.ch>
+package uuid
+
+import (
+ "crypto/md5"
+ "crypto/rand"
+ "crypto/sha1"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "hash"
+ "regexp"
+)
+
+// The UUID reserved variants.
+const (
+ ReservedNCS byte = 0x80
+ ReservedRFC4122 byte = 0x40
+ ReservedMicrosoft byte = 0x20
+ ReservedFuture byte = 0x00
+)
+
+// The following standard UUIDs are for use with NewV3() or NewV5().
+var (
+ NamespaceDNS, _ = ParseHex("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
+ NamespaceURL, _ = ParseHex("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
+ NamespaceOID, _ = ParseHex("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
+ NamespaceX500, _ = ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
+)
+
+// Pattern used to parse hex string representation of the UUID.
+// FIXME: do something to consider both brackets at one time,
+// current one allows to parse string with only one opening
+// or closing bracket.
+const hexPattern = "^(urn\\:uuid\\:)?\\{?([a-z0-9]{8})-([a-z0-9]{4})-" +
+ "([1-5][a-z0-9]{3})-([a-z0-9]{4})-([a-z0-9]{12})\\}?$"
+
+var re = regexp.MustCompile(hexPattern)
+
+// A UUID representation compliant with specification in
+// RFC 4122 document.
+type UUID [16]byte
+
+// ParseHex creates a UUID object from given hex string
+// representation. Function accepts UUID string in following
+// formats:
+//
+// uuid.ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
+// uuid.ParseHex("{6ba7b814-9dad-11d1-80b4-00c04fd430c8}")
+// uuid.ParseHex("urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8")
+//
+func ParseHex(s string) (u *UUID, err error) {
+ md := re.FindStringSubmatch(s)
+ if md == nil {
+ err = errors.New("Invalid UUID string")
+ return
+ }
+ hash := md[2] + md[3] + md[4] + md[5] + md[6]
+ b, err := hex.DecodeString(hash)
+ if err != nil {
+ return
+ }
+ u = new(UUID)
+ copy(u[:], b)
+ return
+}
+
+// Parse creates a UUID object from given bytes slice.
+func Parse(b []byte) (u *UUID, err error) {
+ if len(b) != 16 {
+ err = errors.New("Given slice is not valid UUID sequence")
+ return
+ }
+ u = new(UUID)
+ copy(u[:], b)
+ return
+}
+
+// Generate a UUID based on the MD5 hash of a namespace identifier
+// and a name.
+func NewV3(ns *UUID, name []byte) (u *UUID, err error) {
+ if ns == nil {
+ err = errors.New("Invalid namespace UUID")
+ return
+ }
+ u = new(UUID)
+ // Set all bits to MD5 hash generated from namespace and name.
+ u.setBytesFromHash(md5.New(), ns[:], name)
+ u.setVariant(ReservedRFC4122)
+ u.setVersion(3)
+ return
+}
+
+// Generate a random UUID.
+func NewV4() (u *UUID, err error) {
+ u = new(UUID)
+ // Set all bits to randomly (or pseudo-randomly) chosen values.
+ _, err = rand.Read(u[:])
+ if err != nil {
+ return
+ }
+ u.setVariant(ReservedRFC4122)
+ u.setVersion(4)
+ return
+}
+
+// Generate a UUID based on the SHA-1 hash of a namespace identifier
+// and a name.
+func NewV5(ns *UUID, name []byte) (u *UUID, err error) {
+ u = new(UUID)
+ // Set all bits to truncated SHA1 hash generated from namespace
+ // and name.
+ u.setBytesFromHash(sha1.New(), ns[:], name)
+ u.setVariant(ReservedRFC4122)
+ u.setVersion(5)
+ return
+}
+
+// Generate a MD5 hash of a namespace and a name, and copy it to the
+// UUID slice.
+func (u *UUID) setBytesFromHash(hash hash.Hash, ns, name []byte) {
+ hash.Write(ns[:])
+ hash.Write(name)
+ copy(u[:], hash.Sum([]byte{})[:16])
+}
+
+// Set the two most significant bits (bits 6 and 7) of the
+// clock_seq_hi_and_reserved to zero and one, respectively.
+func (u *UUID) setVariant(v byte) {
+ switch v {
+ case ReservedNCS:
+ u[8] = (u[8] | ReservedNCS) & 0xBF
+ case ReservedRFC4122:
+ u[8] = (u[8] | ReservedRFC4122) & 0x7F
+ case ReservedMicrosoft:
+ u[8] = (u[8] | ReservedMicrosoft) & 0x3F
+ }
+}
+
+// Variant returns the UUID Variant, which determines the internal
+// layout of the UUID. This will be one of the constants: RESERVED_NCS,
+// RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE.
+func (u *UUID) Variant() byte {
+ if u[8]&ReservedNCS == ReservedNCS {
+ return ReservedNCS
+ } else if u[8]&ReservedRFC4122 == ReservedRFC4122 {
+ return ReservedRFC4122
+ } else if u[8]&ReservedMicrosoft == ReservedMicrosoft {
+ return ReservedMicrosoft
+ }
+ return ReservedFuture
+}
+
+// Set the four most significant bits (bits 12 through 15) of the
+// time_hi_and_version field to the 4-bit version number.
+func (u *UUID) setVersion(v byte) {
+ u[6] = (u[6] & 0xF) | (v << 4)
+}
+
+// Version returns a version number of the algorithm used to
+// generate the UUID sequence.
+func (u *UUID) Version() uint {
+ return uint(u[6] >> 4)
+}
+
+// Returns unparsed version of the generated UUID sequence.
+func (u *UUID) String() string {
+ return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:])
+}