Merge branch 'master' into google
diff --git a/.travis.yml b/.travis.yml
index 64353cc..3deb4a1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,9 @@
language: go
go:
- - 1.9
+ - "1.9"
+ - "1.10"
+ - "1.11"
- tip
script:
diff --git a/README.md b/README.md
index b0396b2..810ad40 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,8 @@
# uuid 
The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services.
+This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package).
+
###### Install
`go get github.com/pborman/uuid`
diff --git a/doc.go b/doc.go
index d8bd013..727d761 100644
--- a/doc.go
+++ b/doc.go
@@ -4,5 +4,10 @@
// The uuid package generates and inspects UUIDs.
//
-// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services.
+// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
+// Services.
+//
+// This package is a partial wrapper around the github.com/google/uuid package.
+// This package represents a UUID as []byte while github.com/google/uuid
+// represents a UUID as [16]byte.
package uuid
diff --git a/marshal.go b/marshal.go
index 6621dd5..35b8935 100644
--- a/marshal.go
+++ b/marshal.go
@@ -7,6 +7,8 @@
import (
"errors"
"fmt"
+
+ guuid "github.com/google/uuid"
)
// MarshalText implements encoding.TextMarshaler.
@@ -60,11 +62,11 @@
// UnmarshalText implements encoding.TextUnmarshaler.
func (u *Array) UnmarshalText(data []byte) error {
- id := Parse(string(data))
- if id == nil {
- return errors.New("invalid UUID")
+ id, err := guuid.ParseBytes(data)
+ if err != nil {
+ return err
}
- *u = id.Array()
+ *u = Array(id)
return nil
}
diff --git a/node.go b/node.go
index c1397cb..e524e01 100644
--- a/node.go
+++ b/node.go
@@ -5,22 +5,14 @@
package uuid
import (
- "sync"
-)
-
-var (
- nodeMu sync.Mutex
- ifname string // name of interface being used
- nodeID []byte // hardware for version 1 UUIDs
+ guuid "github.com/google/uuid"
)
// NodeInterface returns the name of the interface from which the NodeID was
// derived. The interface "user" is returned if the NodeID was set by
// SetNodeID.
func NodeInterface() string {
- defer nodeMu.Unlock()
- nodeMu.Lock()
- return ifname
+ return guuid.NodeInterface()
}
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
@@ -30,70 +22,20 @@
//
// SetNodeInterface never fails when name is "".
func SetNodeInterface(name string) bool {
- defer nodeMu.Unlock()
- nodeMu.Lock()
- if nodeID != nil {
- return true
- }
- return setNodeInterface(name)
-}
-
-func setNodeInterface(name string) bool {
-
- iname, addr := getHardwareInterface(name) // null implementation for js
- if iname != "" && setNodeID(addr) {
- ifname = iname
- return true
- }
-
- // We found no interfaces with a valid hardware address. If name
- // does not specify a specific interface generate a random Node ID
- // (section 4.1.6)
- if name == "" {
- if nodeID == nil {
- nodeID = make([]byte, 6)
- }
- randomBits(nodeID)
- return true
- }
- return false
+ return guuid.SetNodeInterface(name)
}
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
// if not already set.
func NodeID() []byte {
- defer nodeMu.Unlock()
- nodeMu.Lock()
- if nodeID == nil {
- setNodeInterface("")
- }
- nid := make([]byte, 6)
- copy(nid, nodeID)
- return nid
+ return guuid.NodeID()
}
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
// of id are used. If id is less than 6 bytes then false is returned and the
// Node ID is not set.
func SetNodeID(id []byte) bool {
- defer nodeMu.Unlock()
- nodeMu.Lock()
- if setNodeID(id) {
- ifname = "user"
- return true
- }
- return false
-}
-
-func setNodeID(id []byte) bool {
- if len(id) < 6 {
- return false
- }
- if nodeID == nil {
- nodeID = make([]byte, 6)
- }
- copy(nodeID, id)
- return true
+ return guuid.SetNodeID(id)
}
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
diff --git a/node_js.go b/node_js.go
deleted file mode 100644
index 24b78ed..0000000
--- a/node_js.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build js
-
-package uuid
-
-// getHardwareInterface returns nil values for the JS version of the code.
-// This remvoves the "net" dependency, because it is not used in the browser.
-// Using the "net" library inflates the size of the transpiled JS code by 673k bytes.
-func getHardwareInterface(name string) (string, []byte) { return "", nil }
diff --git a/node_net.go b/node_net.go
deleted file mode 100644
index 330b544..0000000
--- a/node_net.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !js
-
-package uuid
-
-import "net"
-
-var interfaces []net.Interface // cached list of interfaces
-
-// getHardwareInterface returns the name and hardware address of interface name.
-// If name is "" then the name and hardware address of one of the system's
-// interfaces is returned. If no interfaces are found (name does not exist or
-// there are no interfaces) then "", nil is returned.
-//
-// Only addresses of at least 6 bytes are returned.
-func getHardwareInterface(name string) (string, []byte) {
- if interfaces == nil {
- var err error
- interfaces, err = net.Interfaces()
- if err != nil {
- return "", nil
- }
- }
- for _, ifs := range interfaces {
- if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
- if setNodeID(ifs.HardwareAddr) {
- ifname = ifs.Name
- return ifname, nodeID
- }
- }
- }
- return "", nil
-}
diff --git a/time.go b/time.go
index eedf242..5c0960d 100644
--- a/time.go
+++ b/time.go
@@ -6,65 +6,18 @@
import (
"encoding/binary"
- "sync"
- "time"
+
+ guuid "github.com/google/uuid"
)
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
-type Time int64
-
-const (
- lillian = 2299160 // Julian day of 15 Oct 1582
- unix = 2440587 // Julian day of 1 Jan 1970
- epoch = unix - lillian // Days between epochs
- g1582 = epoch * 86400 // seconds between epochs
- g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
-)
-
-var (
- timeMu sync.Mutex
- lasttime uint64 // last time we returned
- clock_seq uint16 // clock sequence for this run
-
- timeNow = time.Now // for testing
-)
-
-// UnixTime converts t the number of seconds and nanoseconds using the Unix
-// epoch of 1 Jan 1970.
-func (t Time) UnixTime() (sec, nsec int64) {
- sec = int64(t - g1582ns100)
- nsec = (sec % 10000000) * 100
- sec /= 10000000
- return sec, nsec
-}
+type Time = guuid.Time
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// clock sequence as well as adjusting the clock sequence as needed. An error
// is returned if the current time cannot be determined.
-func GetTime() (Time, uint16, error) {
- defer timeMu.Unlock()
- timeMu.Lock()
- return getTime()
-}
-
-func getTime() (Time, uint16, error) {
- t := timeNow()
-
- // If we don't have a clock sequence already, set one.
- if clock_seq == 0 {
- setClockSequence(-1)
- }
- now := uint64(t.UnixNano()/100) + g1582ns100
-
- // If time has gone backwards with this clock sequence then we
- // increment the clock sequence
- if now <= lasttime {
- clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000
- }
- lasttime = now
- return Time(now), clock_seq, nil
-}
+func GetTime() (Time, uint16, error) { return guuid.GetTime() }
// ClockSequence returns the current clock sequence, generating one if not
// already set. The clock sequence is only used for Version 1 UUIDs.
@@ -74,39 +27,11 @@
// clock sequence is generated the first time a clock sequence is requested by
// ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated
// for
-func ClockSequence() int {
- defer timeMu.Unlock()
- timeMu.Lock()
- return clockSequence()
-}
-
-func clockSequence() int {
- if clock_seq == 0 {
- setClockSequence(-1)
- }
- return int(clock_seq & 0x3fff)
-}
+func ClockSequence() int { return guuid.ClockSequence() }
// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to
// -1 causes a new sequence to be generated.
-func SetClockSequence(seq int) {
- defer timeMu.Unlock()
- timeMu.Lock()
- setClockSequence(seq)
-}
-
-func setClockSequence(seq int) {
- if seq == -1 {
- var b [2]byte
- randomBits(b[:]) // clock sequence
- seq = int(b[0])<<8 | int(b[1])
- }
- old_seq := clock_seq
- clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant
- if old_seq != clock_seq {
- lasttime = 0
- }
-}
+func SetClockSequence(seq int) { guuid.SetClockSequence(seq) }
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid. It returns false if uuid is not valid. The time is only well defined
diff --git a/util.go b/util.go
index fc8e052..255b5e2 100644
--- a/util.go
+++ b/util.go
@@ -4,17 +4,6 @@
package uuid
-import (
- "io"
-)
-
-// randomBits completely fills slice b with random data.
-func randomBits(b []byte) {
- if _, err := io.ReadFull(rander, b); err != nil {
- panic(err.Error()) // rand should never fail
- }
-}
-
// xvalues returns the value of a byte as a hexadecimal digit or 255.
var xvalues = [256]byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
diff --git a/uuid.go b/uuid.go
index 7c643cf..a2429b0 100644
--- a/uuid.go
+++ b/uuid.go
@@ -8,9 +8,9 @@
"bytes"
"crypto/rand"
"encoding/hex"
- "fmt"
"io"
- "strings"
+
+ guuid "github.com/google/uuid"
)
// Array is a pass-by-value UUID that can be used as an effecient key in a map.
@@ -24,7 +24,7 @@
// String returns the string representation of uuid,
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (uuid Array) String() string {
- return uuid.UUID().String()
+ return guuid.UUID(uuid).String()
}
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
@@ -32,18 +32,18 @@
type UUID []byte
// A Version represents a UUIDs version.
-type Version byte
+type Version = guuid.Version
// A Variant represents a UUIDs variant.
-type Variant byte
+type Variant = guuid.Variant
// Constants returned by Variant.
const (
- Invalid = Variant(iota) // Invalid UUID
- RFC4122 // The variant specified in RFC4122
- Reserved // Reserved, NCS backward compatibility.
- Microsoft // Reserved, Microsoft Corporation backward compatibility.
- Future // Reserved for future definition.
+ Invalid = guuid.Invalid // Invalid UUID
+ RFC4122 = guuid.RFC4122 // The variant specified in RFC4122
+ Reserved = guuid.Reserved // Reserved, NCS backward compatibility.
+ Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility.
+ Future = guuid.Future // Reserved for future definition.
)
var rander = rand.Reader // random function
@@ -58,31 +58,20 @@
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
func Parse(s string) UUID {
- if len(s) == 36+9 {
- if strings.ToLower(s[:9]) != "urn:uuid:" {
- return nil
- }
- s = s[9:]
- } else if len(s) != 36 {
- return nil
+ gu, err := guuid.Parse(s)
+ if err == nil {
+ return gu[:]
}
- if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
- return nil
+ return nil
+}
+
+// ParseBytes is like Parse, except it parses a byte slice instead of a string.
+func ParseBytes(b []byte) (UUID, error) {
+ gu, err := guuid.ParseBytes(b)
+ if err == nil {
+ return gu[:], nil
}
- var uuid [16]byte
- for i, x := range [16]int{
- 0, 2, 4, 6,
- 9, 11,
- 14, 16,
- 19, 21,
- 24, 26, 28, 30, 32, 34} {
- if v, ok := xtob(s[x:]); !ok {
- return nil
- } else {
- uuid[i] = v
- }
- }
- return uuid[:]
+ return nil, err
}
// Equal returns true if uuid1 and uuid2 are equal.
@@ -163,29 +152,6 @@
return Version(uuid[6] >> 4), true
}
-func (v Version) String() string {
- if v > 15 {
- return fmt.Sprintf("BAD_VERSION_%d", v)
- }
- return fmt.Sprintf("VERSION_%d", v)
-}
-
-func (v Variant) String() string {
- switch v {
- case RFC4122:
- return "RFC4122"
- case Reserved:
- return "Reserved"
- case Microsoft:
- return "Microsoft"
- case Future:
- return "Future"
- case Invalid:
- return "Invalid"
- }
- return fmt.Sprintf("BadVariant%d", int(v))
-}
-
// SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
@@ -193,9 +159,5 @@
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
- if r == nil {
- rander = rand.Reader
- return
- }
- rander = r
+ guuid.SetRand(r)
}
diff --git a/uuid_test.go b/uuid_test.go
index 0d69bb8..7e9d144 100644
--- a/uuid_test.go
+++ b/uuid_test.go
@@ -4,14 +4,15 @@
package uuid
+// Some of these tests can probably be removed as they are redundant with the
+// tests in github.com/google/uuid.
+
import (
"bytes"
"fmt"
"os"
- "runtime"
"strings"
"testing"
- "time"
)
type test struct {
@@ -158,51 +159,6 @@
}
}
-func clockSeq(t *testing.T, uuid UUID) int {
- seq, ok := uuid.ClockSequence()
- if !ok {
- t.Fatalf("%s: invalid clock sequence", uuid)
- }
- return seq
-}
-
-func TestClockSeq(t *testing.T) {
- // Fake time.Now for this test to return a monotonically advancing time; restore it at end.
- defer func(orig func() time.Time) { timeNow = orig }(timeNow)
- monTime := time.Now()
- timeNow = func() time.Time {
- monTime = monTime.Add(1 * time.Second)
- return monTime
- }
-
- SetClockSequence(-1)
- uuid1 := NewUUID()
- uuid2 := NewUUID()
-
- if clockSeq(t, uuid1) != clockSeq(t, uuid2) {
- t.Errorf("clock sequence %d != %d", clockSeq(t, uuid1), clockSeq(t, uuid2))
- }
-
- SetClockSequence(-1)
- uuid2 = NewUUID()
-
- // Just on the very off chance we generated the same sequence
- // two times we try again.
- if clockSeq(t, uuid1) == clockSeq(t, uuid2) {
- SetClockSequence(-1)
- uuid2 = NewUUID()
- }
- if clockSeq(t, uuid1) == clockSeq(t, uuid2) {
- t.Errorf("Duplicate clock sequence %d", clockSeq(t, uuid1))
- }
-
- SetClockSequence(0x1234)
- uuid1 = NewUUID()
- if seq := clockSeq(t, uuid1); seq != 0x1234 {
- t.Errorf("%s: expected seq 0x1234 got 0x%04x", uuid1, seq)
- }
-}
-
func TestCoding(t *testing.T) {
text := "7d444840-9dc0-11d1-b245-5ffdce74fad2"
urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2"
@@ -271,74 +227,6 @@
}
}
-func TestNode(t *testing.T) {
- // This test is mostly to make sure we don't leave nodeMu locked.
- ifname = ""
- if ni := NodeInterface(); ni != "" {
- t.Errorf("NodeInterface got %q, want %q", ni, "")
- }
- nodeID = nil // Reset global state for next test
- if SetNodeInterface("xyzzy") {
- t.Error("SetNodeInterface succeeded on a bad interface name")
- }
- nodeID = nil // Reset global state for next test
- if !SetNodeInterface("") {
- t.Error("SetNodeInterface failed")
- }
-
- if runtime.GOARCH != "js" {
- if ni := NodeInterface(); ni == "" {
- t.Error("NodeInterface returned an empty string")
- }
- }
-
- ni := NodeID()
- if len(ni) != 6 {
- t.Errorf("ni got %d bytes, want 6", len(ni))
- }
- hasData := false
- for _, b := range ni {
- if b != 0 {
- hasData = true
- }
- }
- if !hasData {
- t.Error("nodeid is all zeros")
- }
-
- id := []byte{1, 2, 3, 4, 5, 6, 7, 8}
- SetNodeID(id)
- ni = NodeID()
- if !bytes.Equal(ni, id[:6]) {
- t.Errorf("got nodeid %v, want %v", ni, id[:6])
- }
-
- if ni := NodeInterface(); ni != "user" {
- t.Errorf("got inteface %q, want %q", ni, "user")
- }
-}
-
-func TestNodeAndTime(t *testing.T) {
- // Time is February 5, 1998 12:30:23.136364800 AM GMT
-
- uuid := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2")
- node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2}
-
- ts, ok := uuid.Time()
- if ok {
- c := time.Unix(ts.UnixTime())
- want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC)
- if !c.Equal(want) {
- t.Errorf("Got time %v, want %v", c, want)
- }
- } else {
- t.Errorf("%s: bad time", uuid)
- }
- if !bytes.Equal(node, uuid.NodeID()) {
- t.Errorf("Expected node %v got %v", node, uuid.NodeID())
- }
-}
-
func TestMD5(t *testing.T) {
uuid := NewMD5(NameSpace_DNS, []byte("python.org")).String()
want := "6fa459ea-ee8a-3ca4-894e-db77e160355e"
@@ -355,36 +243,6 @@
}
}
-func TestNodeID(t *testing.T) {
- nid := []byte{1, 2, 3, 4, 5, 6}
- nodeID = nil // Reset global state for next test
- SetNodeInterface("")
- s := NodeInterface()
- if runtime.GOARCH != "js" {
- if s == "" || s == "user" {
- t.Errorf("NodeInterface %q after SetInterface", s)
- }
- }
- node1 := NodeID()
- if node1 == nil {
- t.Error("NodeID nil after SetNodeInterface", s)
- }
- SetNodeID(nid)
- s = NodeInterface()
- if s != "user" {
- t.Errorf("Expected NodeInterface %q got %q", "user", s)
- }
- node2 := NodeID()
- if node2 == nil {
- t.Error("NodeID nil after SetNodeID", s)
- }
- if bytes.Equal(node1, node2) {
- t.Error("NodeID not changed after SetNodeID", s)
- } else if !bytes.Equal(nid, node2) {
- t.Errorf("NodeID is %x, expected %x", node2, nid)
- }
-}
-
func testDCE(t *testing.T, name string, uuid UUID, domain Domain, id uint32) {
if uuid == nil {
t.Errorf("%s failed", name)
diff --git a/version1.go b/version1.go
index 577af6a..7af948d 100644
--- a/version1.go
+++ b/version1.go
@@ -5,7 +5,7 @@
package uuid
import (
- "encoding/binary"
+ guuid "github.com/google/uuid"
)
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
@@ -15,25 +15,9 @@
// SetClockSequence then it will be set automatically. If GetTime fails to
// return the current NewUUID returns nil.
func NewUUID() UUID {
- SetNodeInterface("")
-
- now, seq, err := GetTime()
- if err != nil {
- return nil
+ gu, err := guuid.NewUUID()
+ if err == nil {
+ return UUID(gu[:])
}
-
- uuid := make([]byte, 16)
-
- time_low := uint32(now & 0xffffffff)
- time_mid := uint16((now >> 32) & 0xffff)
- time_hi := uint16((now >> 48) & 0x0fff)
- time_hi |= 0x1000 // Version 1
-
- binary.BigEndian.PutUint32(uuid[0:], time_low)
- binary.BigEndian.PutUint16(uuid[4:], time_mid)
- binary.BigEndian.PutUint16(uuid[6:], time_hi)
- binary.BigEndian.PutUint16(uuid[8:], seq)
- copy(uuid[10:], nodeID)
-
- return uuid
+ return nil
}
diff --git a/version4.go b/version4.go
index 37a7f45..b459d46 100644
--- a/version4.go
+++ b/version4.go
@@ -4,6 +4,8 @@
package uuid
+import guuid "github.com/google/uuid"
+
// Random returns a Random (Version 4) UUID or panics.
//
// The strength of the UUIDs is based on the strength of the crypto/rand
@@ -17,9 +19,8 @@
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() UUID {
- uuid := make([]byte, 16)
- randomBits([]byte(uuid))
- uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
- uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
- return uuid
+ if gu, err := guuid.NewRandom(); err == nil {
+ return UUID(gu[:])
+ }
+ return nil
}