AJ ONeal
4 years ago
20 changed files with 946 additions and 0 deletions
@ -0,0 +1,9 @@ |
|||
language: go |
|||
|
|||
go: |
|||
- 1.4.3 |
|||
- 1.5.3 |
|||
- tip |
|||
|
|||
script: |
|||
- go test -v ./... |
@ -0,0 +1,10 @@ |
|||
# How to contribute |
|||
|
|||
We definitely welcome patches and contribution to this project! |
|||
|
|||
### Legal requirements |
|||
|
|||
In order to protect both you and ourselves, you will need to sign the |
|||
[Contributor License Agreement](https://cla.developers.google.com/clas). |
|||
|
|||
You may have already signed it for other Google projects. |
@ -0,0 +1,9 @@ |
|||
Paul Borman <borman@google.com> |
|||
bmatsuo |
|||
shawnps |
|||
theory |
|||
jboverfelt |
|||
dsymonds |
|||
cd1 |
|||
wallclockbuilder |
|||
dansouza |
@ -0,0 +1,27 @@ |
|||
Copyright (c) 2009,2014 Google Inc. All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are |
|||
met: |
|||
|
|||
* Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
* Redistributions in binary form must reproduce the above |
|||
copyright notice, this list of conditions and the following disclaimer |
|||
in the documentation and/or other materials provided with the |
|||
distribution. |
|||
* Neither the name of Google Inc. nor the names of its |
|||
contributors may be used to endorse or promote products derived from |
|||
this software without specific prior written permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,19 @@ |
|||
# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master) |
|||
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 is based on the github.com/pborman/uuid package (previously named |
|||
code.google.com/p/go-uuid). It differs from these earlier packages in that |
|||
a UUID is a 16 byte array rather than a byte slice. One loss due to this |
|||
change is the ability to represent an invalid UUID (vs a NIL UUID). |
|||
|
|||
###### Install |
|||
`go get github.com/google/uuid` |
|||
|
|||
###### Documentation |
|||
[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid) |
|||
|
|||
Full `go doc` style documentation for the package can be viewed online without |
|||
installing this package by using the GoDoc site here: |
|||
http://godoc.org/github.com/google/uuid |
@ -0,0 +1,80 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
package uuid |
|||
|
|||
import ( |
|||
"encoding/binary" |
|||
"fmt" |
|||
"os" |
|||
) |
|||
|
|||
// A Domain represents a Version 2 domain
|
|||
type Domain byte |
|||
|
|||
// Domain constants for DCE Security (Version 2) UUIDs.
|
|||
const ( |
|||
Person = Domain(0) |
|||
Group = Domain(1) |
|||
Org = Domain(2) |
|||
) |
|||
|
|||
// NewDCESecurity returns a DCE Security (Version 2) UUID.
|
|||
//
|
|||
// The domain should be one of Person, Group or Org.
|
|||
// On a POSIX system the id should be the users UID for the Person
|
|||
// domain and the users GID for the Group. The meaning of id for
|
|||
// the domain Org or on non-POSIX systems is site defined.
|
|||
//
|
|||
// For a given domain/id pair the same token may be returned for up to
|
|||
// 7 minutes and 10 seconds.
|
|||
func NewDCESecurity(domain Domain, id uint32) (UUID, error) { |
|||
uuid, err := NewUUID() |
|||
if err == nil { |
|||
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
|
|||
uuid[9] = byte(domain) |
|||
binary.BigEndian.PutUint32(uuid[0:], id) |
|||
} |
|||
return uuid, err |
|||
} |
|||
|
|||
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
|
|||
// domain with the id returned by os.Getuid.
|
|||
//
|
|||
// NewDCESecurity(Person, uint32(os.Getuid()))
|
|||
func NewDCEPerson() (UUID, error) { |
|||
return NewDCESecurity(Person, uint32(os.Getuid())) |
|||
} |
|||
|
|||
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
|
|||
// domain with the id returned by os.Getgid.
|
|||
//
|
|||
// NewDCESecurity(Group, uint32(os.Getgid()))
|
|||
func NewDCEGroup() (UUID, error) { |
|||
return NewDCESecurity(Group, uint32(os.Getgid())) |
|||
} |
|||
|
|||
// Domain returns the domain for a Version 2 UUID. Domains are only defined
|
|||
// for Version 2 UUIDs.
|
|||
func (uuid UUID) Domain() Domain { |
|||
return Domain(uuid[9]) |
|||
} |
|||
|
|||
// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
|
|||
// UUIDs.
|
|||
func (uuid UUID) ID() uint32 { |
|||
return binary.BigEndian.Uint32(uuid[0:4]) |
|||
} |
|||
|
|||
func (d Domain) String() string { |
|||
switch d { |
|||
case Person: |
|||
return "Person" |
|||
case Group: |
|||
return "Group" |
|||
case Org: |
|||
return "Org" |
|||
} |
|||
return fmt.Sprintf("Domain%d", int(d)) |
|||
} |
@ -0,0 +1,12 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
// Package uuid generates and inspects UUIDs.
|
|||
//
|
|||
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
|
|||
// Services.
|
|||
//
|
|||
// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to
|
|||
// maps or compared directly.
|
|||
package uuid |
@ -0,0 +1 @@ |
|||
module github.com/google/uuid |
@ -0,0 +1,53 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
package uuid |
|||
|
|||
import ( |
|||
"crypto/md5" |
|||
"crypto/sha1" |
|||
"hash" |
|||
) |
|||
|
|||
// Well known namespace IDs and UUIDs
|
|||
var ( |
|||
NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) |
|||
NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) |
|||
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) |
|||
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) |
|||
Nil UUID // empty UUID, all zeros
|
|||
) |
|||
|
|||
// NewHash returns a new UUID derived from the hash of space concatenated with
|
|||
// data generated by h. The hash should be at least 16 byte in length. The
|
|||
// first 16 bytes of the hash are used to form the UUID. The version of the
|
|||
// UUID will be the lower 4 bits of version. NewHash is used to implement
|
|||
// NewMD5 and NewSHA1.
|
|||
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { |
|||
h.Reset() |
|||
h.Write(space[:]) |
|||
h.Write(data) |
|||
s := h.Sum(nil) |
|||
var uuid UUID |
|||
copy(uuid[:], s) |
|||
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) |
|||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
|
|||
return uuid |
|||
} |
|||
|
|||
// NewMD5 returns a new MD5 (Version 3) UUID based on the
|
|||
// supplied name space and data. It is the same as calling:
|
|||
//
|
|||
// NewHash(md5.New(), space, data, 3)
|
|||
func NewMD5(space UUID, data []byte) UUID { |
|||
return NewHash(md5.New(), space, data, 3) |
|||
} |
|||
|
|||
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
|
|||
// supplied name space and data. It is the same as calling:
|
|||
//
|
|||
// NewHash(sha1.New(), space, data, 5)
|
|||
func NewSHA1(space UUID, data []byte) UUID { |
|||
return NewHash(sha1.New(), space, data, 5) |
|||
} |
@ -0,0 +1,37 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
package uuid |
|||
|
|||
import "fmt" |
|||
|
|||
// MarshalText implements encoding.TextMarshaler.
|
|||
func (uuid UUID) MarshalText() ([]byte, error) { |
|||
var js [36]byte |
|||
encodeHex(js[:], uuid) |
|||
return js[:], nil |
|||
} |
|||
|
|||
// UnmarshalText implements encoding.TextUnmarshaler.
|
|||
func (uuid *UUID) UnmarshalText(data []byte) error { |
|||
id, err := ParseBytes(data) |
|||
if err == nil { |
|||
*uuid = id |
|||
} |
|||
return err |
|||
} |
|||
|
|||
// MarshalBinary implements encoding.BinaryMarshaler.
|
|||
func (uuid UUID) MarshalBinary() ([]byte, error) { |
|||
return uuid[:], nil |
|||
} |
|||
|
|||
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
|
|||
func (uuid *UUID) UnmarshalBinary(data []byte) error { |
|||
if len(data) != 16 { |
|||
return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) |
|||
} |
|||
copy(uuid[:], data) |
|||
return nil |
|||
} |
@ -0,0 +1,90 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
package uuid |
|||
|
|||
import ( |
|||
"sync" |
|||
) |
|||
|
|||
var ( |
|||
nodeMu sync.Mutex |
|||
ifname string // name of interface being used
|
|||
nodeID [6]byte // hardware for version 1 UUIDs
|
|||
zeroID [6]byte // nodeID with only 0's
|
|||
) |
|||
|
|||
// 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 |
|||
} |
|||
|
|||
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
|
|||
// If name is "" then the first usable interface found will be used or a random
|
|||
// Node ID will be generated. If a named interface cannot be found then false
|
|||
// is returned.
|
|||
//
|
|||
// SetNodeInterface never fails when name is "".
|
|||
func SetNodeInterface(name string) bool { |
|||
defer nodeMu.Unlock() |
|||
nodeMu.Lock() |
|||
return setNodeInterface(name) |
|||
} |
|||
|
|||
func setNodeInterface(name string) bool { |
|||
iname, addr := getHardwareInterface(name) // null implementation for js
|
|||
if iname != "" && addr != nil { |
|||
ifname = iname |
|||
copy(nodeID[:], addr) |
|||
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 == "" { |
|||
ifname = "random" |
|||
randomBits(nodeID[:]) |
|||
return true |
|||
} |
|||
return false |
|||
} |
|||
|
|||
// 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 == zeroID { |
|||
setNodeInterface("") |
|||
} |
|||
nid := nodeID |
|||
return nid[:] |
|||
} |
|||
|
|||
// 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 { |
|||
if len(id) < 6 { |
|||
return false |
|||
} |
|||
defer nodeMu.Unlock() |
|||
nodeMu.Lock() |
|||
copy(nodeID[:], id) |
|||
ifname = "user" |
|||
return true |
|||
} |
|||
|
|||
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
|
|||
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
|
|||
func (uuid UUID) NodeID() []byte { |
|||
var node [6]byte |
|||
copy(node[:], uuid[10:]) |
|||
return node[:] |
|||
} |
@ -0,0 +1,12 @@ |
|||
// 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 } |
@ -0,0 +1,33 @@ |
|||
// 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) { |
|||
return ifs.Name, ifs.HardwareAddr |
|||
} |
|||
} |
|||
return "", nil |
|||
} |
@ -0,0 +1,59 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
package uuid |
|||
|
|||
import ( |
|||
"database/sql/driver" |
|||
"fmt" |
|||
) |
|||
|
|||
// Scan implements sql.Scanner so UUIDs can be read from databases transparently
|
|||
// Currently, database types that map to string and []byte are supported. Please
|
|||
// consult database-specific driver documentation for matching types.
|
|||
func (uuid *UUID) Scan(src interface{}) error { |
|||
switch src := src.(type) { |
|||
case nil: |
|||
return nil |
|||
|
|||
case string: |
|||
// if an empty UUID comes from a table, we return a null UUID
|
|||
if src == "" { |
|||
return nil |
|||
} |
|||
|
|||
// see Parse for required string format
|
|||
u, err := Parse(src) |
|||
if err != nil { |
|||
return fmt.Errorf("Scan: %v", err) |
|||
} |
|||
|
|||
*uuid = u |
|||
|
|||
case []byte: |
|||
// if an empty UUID comes from a table, we return a null UUID
|
|||
if len(src) == 0 { |
|||
return nil |
|||
} |
|||
|
|||
// assumes a simple slice of bytes if 16 bytes
|
|||
// otherwise attempts to parse
|
|||
if len(src) != 16 { |
|||
return uuid.Scan(string(src)) |
|||
} |
|||
copy((*uuid)[:], src) |
|||
|
|||
default: |
|||
return fmt.Errorf("Scan: unable to scan type %T into UUID", src) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
// Value implements sql.Valuer so that UUIDs can be written to databases
|
|||
// transparently. Currently, UUIDs map to strings. Please consult
|
|||
// database-specific driver documentation for matching types.
|
|||
func (uuid UUID) Value() (driver.Value, error) { |
|||
return uuid.String(), nil |
|||
} |
@ -0,0 +1,123 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
package uuid |
|||
|
|||
import ( |
|||
"encoding/binary" |
|||
"sync" |
|||
"time" |
|||
) |
|||
|
|||
// 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
|
|||
clockSeq 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 |
|||
} |
|||
|
|||
// 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 clockSeq == 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 { |
|||
clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000 |
|||
} |
|||
lasttime = now |
|||
return Time(now), clockSeq, nil |
|||
} |
|||
|
|||
// ClockSequence returns the current clock sequence, generating one if not
|
|||
// already set. The clock sequence is only used for Version 1 UUIDs.
|
|||
//
|
|||
// The uuid package does not use global static storage for the clock sequence or
|
|||
// the last time a UUID was generated. Unless SetClockSequence is used, a new
|
|||
// random clock sequence is generated the first time a clock sequence is
|
|||
// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
|
|||
func ClockSequence() int { |
|||
defer timeMu.Unlock() |
|||
timeMu.Lock() |
|||
return clockSequence() |
|||
} |
|||
|
|||
func clockSequence() int { |
|||
if clockSeq == 0 { |
|||
setClockSequence(-1) |
|||
} |
|||
return int(clockSeq & 0x3fff) |
|||
} |
|||
|
|||
// SetClockSequence 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]) |
|||
} |
|||
oldSeq := clockSeq |
|||
clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
|
|||
if oldSeq != clockSeq { |
|||
lasttime = 0 |
|||
} |
|||
} |
|||
|
|||
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
|||
// uuid. The time is only defined for version 1 and 2 UUIDs.
|
|||
func (uuid UUID) Time() Time { |
|||
time := int64(binary.BigEndian.Uint32(uuid[0:4])) |
|||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 |
|||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 |
|||
return Time(time) |
|||
} |
|||
|
|||
// ClockSequence returns the clock sequence encoded in uuid.
|
|||
// The clock sequence is only well defined for version 1 and 2 UUIDs.
|
|||
func (uuid UUID) ClockSequence() int { |
|||
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff |
|||
} |
@ -0,0 +1,43 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
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, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, |
|||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|||
} |
|||
|
|||
// xtob converts hex characters x1 and x2 into a byte.
|
|||
func xtob(x1, x2 byte) (byte, bool) { |
|||
b1 := xvalues[x1] |
|||
b2 := xvalues[x2] |
|||
return (b1 << 4) | b2, b1 != 255 && b2 != 255 |
|||
} |
@ -0,0 +1,245 @@ |
|||
// Copyright 2018 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.
|
|||
|
|||
package uuid |
|||
|
|||
import ( |
|||
"bytes" |
|||
"crypto/rand" |
|||
"encoding/hex" |
|||
"errors" |
|||
"fmt" |
|||
"io" |
|||
"strings" |
|||
) |
|||
|
|||
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
|
|||
// 4122.
|
|||
type UUID [16]byte |
|||
|
|||
// A Version represents a UUID's version.
|
|||
type Version byte |
|||
|
|||
// A Variant represents a UUID's variant.
|
|||
type Variant byte |
|||
|
|||
// 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.
|
|||
) |
|||
|
|||
var rander = rand.Reader // random function
|
|||
|
|||
// Parse decodes s into a UUID or returns an error. Both the standard UUID
|
|||
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
|||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
|
|||
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
|
|||
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
|
|||
func Parse(s string) (UUID, error) { |
|||
var uuid UUID |
|||
switch len(s) { |
|||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|||
case 36: |
|||
|
|||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|||
case 36 + 9: |
|||
if strings.ToLower(s[:9]) != "urn:uuid:" { |
|||
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) |
|||
} |
|||
s = s[9:] |
|||
|
|||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|||
case 36 + 2: |
|||
s = s[1:] |
|||
|
|||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|||
case 32: |
|||
var ok bool |
|||
for i := range uuid { |
|||
uuid[i], ok = xtob(s[i*2], s[i*2+1]) |
|||
if !ok { |
|||
return uuid, errors.New("invalid UUID format") |
|||
} |
|||
} |
|||
return uuid, nil |
|||
default: |
|||
return uuid, fmt.Errorf("invalid UUID length: %d", len(s)) |
|||
} |
|||
// s is now at least 36 bytes long
|
|||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { |
|||
return uuid, errors.New("invalid UUID format") |
|||
} |
|||
for i, x := range [16]int{ |
|||
0, 2, 4, 6, |
|||
9, 11, |
|||
14, 16, |
|||
19, 21, |
|||
24, 26, 28, 30, 32, 34} { |
|||
v, ok := xtob(s[x], s[x+1]) |
|||
if !ok { |
|||
return uuid, errors.New("invalid UUID format") |
|||
} |
|||
uuid[i] = v |
|||
} |
|||
return uuid, nil |
|||
} |
|||
|
|||
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
|
|||
func ParseBytes(b []byte) (UUID, error) { |
|||
var uuid UUID |
|||
switch len(b) { |
|||
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|||
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|||
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { |
|||
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) |
|||
} |
|||
b = b[9:] |
|||
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|||
b = b[1:] |
|||
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|||
var ok bool |
|||
for i := 0; i < 32; i += 2 { |
|||
uuid[i/2], ok = xtob(b[i], b[i+1]) |
|||
if !ok { |
|||
return uuid, errors.New("invalid UUID format") |
|||
} |
|||
} |
|||
return uuid, nil |
|||
default: |
|||
return uuid, fmt.Errorf("invalid UUID length: %d", len(b)) |
|||
} |
|||
// s is now at least 36 bytes long
|
|||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|||
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { |
|||
return uuid, errors.New("invalid UUID format") |
|||
} |
|||
for i, x := range [16]int{ |
|||
0, 2, 4, 6, |
|||
9, 11, |
|||
14, 16, |
|||
19, 21, |
|||
24, 26, 28, 30, 32, 34} { |
|||
v, ok := xtob(b[x], b[x+1]) |
|||
if !ok { |
|||
return uuid, errors.New("invalid UUID format") |
|||
} |
|||
uuid[i] = v |
|||
} |
|||
return uuid, nil |
|||
} |
|||
|
|||
// MustParse is like Parse but panics if the string cannot be parsed.
|
|||
// It simplifies safe initialization of global variables holding compiled UUIDs.
|
|||
func MustParse(s string) UUID { |
|||
uuid, err := Parse(s) |
|||
if err != nil { |
|||
panic(`uuid: Parse(` + s + `): ` + err.Error()) |
|||
} |
|||
return uuid |
|||
} |
|||
|
|||
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
|
|||
// does not have a length of 16. The bytes are copied from the slice.
|
|||
func FromBytes(b []byte) (uuid UUID, err error) { |
|||
err = uuid.UnmarshalBinary(b) |
|||
return uuid, err |
|||
} |
|||
|
|||
// Must returns uuid if err is nil and panics otherwise.
|
|||
func Must(uuid UUID, err error) UUID { |
|||
if err != nil { |
|||
panic(err) |
|||
} |
|||
return uuid |
|||
} |
|||
|
|||
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|||
// , or "" if uuid is invalid.
|
|||
func (uuid UUID) String() string { |
|||
var buf [36]byte |
|||
encodeHex(buf[:], uuid) |
|||
return string(buf[:]) |
|||
} |
|||
|
|||
// URN returns the RFC 2141 URN form of uuid,
|
|||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
|
|||
func (uuid UUID) URN() string { |
|||
var buf [36 + 9]byte |
|||
copy(buf[:], "urn:uuid:") |
|||
encodeHex(buf[9:], uuid) |
|||
return string(buf[:]) |
|||
} |
|||
|
|||
func encodeHex(dst []byte, uuid UUID) { |
|||
hex.Encode(dst, uuid[:4]) |
|||
dst[8] = '-' |
|||
hex.Encode(dst[9:13], uuid[4:6]) |
|||
dst[13] = '-' |
|||
hex.Encode(dst[14:18], uuid[6:8]) |
|||
dst[18] = '-' |
|||
hex.Encode(dst[19:23], uuid[8:10]) |
|||
dst[23] = '-' |
|||
hex.Encode(dst[24:], uuid[10:]) |
|||
} |
|||
|
|||
// Variant returns the variant encoded in uuid.
|
|||
func (uuid UUID) Variant() Variant { |
|||
switch { |
|||
case (uuid[8] & 0xc0) == 0x80: |
|||
return RFC4122 |
|||
case (uuid[8] & 0xe0) == 0xc0: |
|||
return Microsoft |
|||
case (uuid[8] & 0xe0) == 0xe0: |
|||
return Future |
|||
default: |
|||
return Reserved |
|||
} |
|||
} |
|||
|
|||
// Version returns the version of uuid.
|
|||
func (uuid UUID) Version() Version { |
|||
return Version(uuid[6] >> 4) |
|||
} |
|||
|
|||
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.
|
|||
//
|
|||
// 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 |
|||
} |
@ -0,0 +1,44 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
package uuid |
|||
|
|||
import ( |
|||
"encoding/binary" |
|||
) |
|||
|
|||
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
|
|||
// sequence, and the current time. If the NodeID has not been set by SetNodeID
|
|||
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
|
|||
// be set NewUUID returns nil. If clock sequence has not been set by
|
|||
// SetClockSequence then it will be set automatically. If GetTime fails to
|
|||
// return the current NewUUID returns nil and an error.
|
|||
//
|
|||
// In most cases, New should be used.
|
|||
func NewUUID() (UUID, error) { |
|||
nodeMu.Lock() |
|||
if nodeID == zeroID { |
|||
setNodeInterface("") |
|||
} |
|||
nodeMu.Unlock() |
|||
|
|||
var uuid UUID |
|||
now, seq, err := GetTime() |
|||
if err != nil { |
|||
return uuid, err |
|||
} |
|||
|
|||
timeLow := uint32(now & 0xffffffff) |
|||
timeMid := uint16((now >> 32) & 0xffff) |
|||
timeHi := uint16((now >> 48) & 0x0fff) |
|||
timeHi |= 0x1000 // Version 1
|
|||
|
|||
binary.BigEndian.PutUint32(uuid[0:], timeLow) |
|||
binary.BigEndian.PutUint16(uuid[4:], timeMid) |
|||
binary.BigEndian.PutUint16(uuid[6:], timeHi) |
|||
binary.BigEndian.PutUint16(uuid[8:], seq) |
|||
copy(uuid[10:], nodeID[:]) |
|||
|
|||
return uuid, nil |
|||
} |
@ -0,0 +1,38 @@ |
|||
// Copyright 2016 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.
|
|||
|
|||
package uuid |
|||
|
|||
import "io" |
|||
|
|||
// New creates a new random UUID or panics. New is equivalent to
|
|||
// the expression
|
|||
//
|
|||
// uuid.Must(uuid.NewRandom())
|
|||
func New() UUID { |
|||
return Must(NewRandom()) |
|||
} |
|||
|
|||
// NewRandom returns a Random (Version 4) UUID.
|
|||
//
|
|||
// The strength of the UUIDs is based on the strength of the crypto/rand
|
|||
// package.
|
|||
//
|
|||
// A note about uniqueness derived from the UUID Wikipedia entry:
|
|||
//
|
|||
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
|||
// hit by a meteorite is estimated to be one chance in 17 billion, that
|
|||
// means the probability is about 0.00000000006 (6 × 10−11),
|
|||
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
|||
// year and having one duplicate.
|
|||
func NewRandom() (UUID, error) { |
|||
var uuid UUID |
|||
_, err := io.ReadFull(rander, uuid[:]) |
|||
if err != nil { |
|||
return Nil, err |
|||
} |
|||
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
|
|||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
|||
return uuid, nil |
|||
} |
Loading…
Reference in new issue