├── .travis.yml ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── LICENSE ├── README.md ├── dce.go ├── doc.go ├── go.mod ├── go.sum ├── hash.go ├── marshal.go ├── marshal_test.go ├── node.go ├── seq_test.go ├── sql.go ├── sql_test.go ├── time.go ├── util.go ├── uuid.go ├── uuid_test.go ├── version1.go └── version4.go /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - "1.9" 5 | - "1.10" 6 | - "1.11" 7 | - tip 8 | 9 | arch: 10 | - amd64 11 | - ppc64le 12 | script: 13 | - go test -v ./... 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We definitely welcome patches and contribution to this project! 4 | 5 | ### Legal requirements 6 | 7 | In order to protect both you and ourselves, you will need to sign the 8 | [Contributor License Agreement](https://cla.developers.google.com/clas). 9 | 10 | You may have already signed it for other Google projects. 11 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Paul Borman 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009,2014 Google Inc. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project was automatically exported from code.google.com/p/go-uuid 2 | 3 | # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) 4 | 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. 5 | 6 | This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package). 7 | 8 | ###### Install 9 | `go get github.com/pborman/uuid` 10 | 11 | ###### Documentation 12 | [![GoDoc](https://godoc.org/github.com/pborman/uuid?status.svg)](http://godoc.org/github.com/pborman/uuid) 13 | 14 | Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: 15 | http://godoc.org/github.com/pborman/uuid 16 | -------------------------------------------------------------------------------- /dce.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | package uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | "fmt" 10 | "os" 11 | ) 12 | 13 | // A Domain represents a Version 2 domain 14 | type Domain byte 15 | 16 | // Domain constants for DCE Security (Version 2) UUIDs. 17 | const ( 18 | Person = Domain(0) 19 | Group = Domain(1) 20 | Org = Domain(2) 21 | ) 22 | 23 | // NewDCESecurity returns a DCE Security (Version 2) UUID. 24 | // 25 | // The domain should be one of Person, Group or Org. 26 | // On a POSIX system the id should be the users UID for the Person 27 | // domain and the users GID for the Group. The meaning of id for 28 | // the domain Org or on non-POSIX systems is site defined. 29 | // 30 | // For a given domain/id pair the same token may be returned for up to 31 | // 7 minutes and 10 seconds. 32 | func NewDCESecurity(domain Domain, id uint32) UUID { 33 | uuid := NewUUID() 34 | if uuid != nil { 35 | uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 36 | uuid[9] = byte(domain) 37 | binary.BigEndian.PutUint32(uuid[0:], id) 38 | } 39 | return uuid 40 | } 41 | 42 | // NewDCEPerson returns a DCE Security (Version 2) UUID in the person 43 | // domain with the id returned by os.Getuid. 44 | // 45 | // NewDCEPerson(Person, uint32(os.Getuid())) 46 | func NewDCEPerson() UUID { 47 | return NewDCESecurity(Person, uint32(os.Getuid())) 48 | } 49 | 50 | // NewDCEGroup returns a DCE Security (Version 2) UUID in the group 51 | // domain with the id returned by os.Getgid. 52 | // 53 | // NewDCEGroup(Group, uint32(os.Getgid())) 54 | func NewDCEGroup() UUID { 55 | return NewDCESecurity(Group, uint32(os.Getgid())) 56 | } 57 | 58 | // Domain returns the domain for a Version 2 UUID or false. 59 | func (uuid UUID) Domain() (Domain, bool) { 60 | if v, _ := uuid.Version(); v != 2 { 61 | return 0, false 62 | } 63 | return Domain(uuid[9]), true 64 | } 65 | 66 | // Id returns the id for a Version 2 UUID or false. 67 | func (uuid UUID) Id() (uint32, bool) { 68 | if v, _ := uuid.Version(); v != 2 { 69 | return 0, false 70 | } 71 | return binary.BigEndian.Uint32(uuid[0:4]), true 72 | } 73 | 74 | func (d Domain) String() string { 75 | switch d { 76 | case Person: 77 | return "Person" 78 | case Group: 79 | return "Group" 80 | case Org: 81 | return "Org" 82 | } 83 | return fmt.Sprintf("Domain%d", int(d)) 84 | } 85 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | // The uuid package generates and inspects UUIDs. 6 | // 7 | // UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security 8 | // Services. 9 | // 10 | // This package is a partial wrapper around the github.com/google/uuid package. 11 | // This package represents a UUID as []byte while github.com/google/uuid 12 | // represents a UUID as [16]byte. 13 | package uuid 14 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pborman/uuid 2 | 3 | require github.com/google/uuid v1.0.0 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= 2 | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 3 | -------------------------------------------------------------------------------- /hash.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | package uuid 6 | 7 | import ( 8 | "crypto/md5" 9 | "crypto/sha1" 10 | "hash" 11 | ) 12 | 13 | // Well known Name Space IDs and UUIDs 14 | var ( 15 | NameSpace_DNS = Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 16 | NameSpace_URL = Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8") 17 | NameSpace_OID = Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8") 18 | NameSpace_X500 = Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8") 19 | NIL = Parse("00000000-0000-0000-0000-000000000000") 20 | ) 21 | 22 | // NewHash returns a new UUID derived from the hash of space concatenated with 23 | // data generated by h. The hash should be at least 16 byte in length. The 24 | // first 16 bytes of the hash are used to form the UUID. The version of the 25 | // UUID will be the lower 4 bits of version. NewHash is used to implement 26 | // NewMD5 and NewSHA1. 27 | func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { 28 | h.Reset() 29 | h.Write(space) 30 | h.Write([]byte(data)) 31 | s := h.Sum(nil) 32 | uuid := make([]byte, 16) 33 | copy(uuid, s) 34 | uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) 35 | uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant 36 | return uuid 37 | } 38 | 39 | // NewMD5 returns a new MD5 (Version 3) UUID based on the 40 | // supplied name space and data. 41 | // 42 | // NewHash(md5.New(), space, data, 3) 43 | func NewMD5(space UUID, data []byte) UUID { 44 | return NewHash(md5.New(), space, data, 3) 45 | } 46 | 47 | // NewSHA1 returns a new SHA1 (Version 5) UUID based on the 48 | // supplied name space and data. 49 | // 50 | // NewHash(sha1.New(), space, data, 5) 51 | func NewSHA1(space UUID, data []byte) UUID { 52 | return NewHash(sha1.New(), space, data, 5) 53 | } 54 | -------------------------------------------------------------------------------- /marshal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 | 5 | package uuid 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | 11 | guuid "github.com/google/uuid" 12 | ) 13 | 14 | // MarshalText implements encoding.TextMarshaler. 15 | func (u UUID) MarshalText() ([]byte, error) { 16 | if len(u) != 16 { 17 | return nil, nil 18 | } 19 | var js [36]byte 20 | encodeHex(js[:], u) 21 | return js[:], nil 22 | } 23 | 24 | // UnmarshalText implements encoding.TextUnmarshaler. 25 | func (u *UUID) UnmarshalText(data []byte) error { 26 | if len(data) == 0 { 27 | return nil 28 | } 29 | id := Parse(string(data)) 30 | if id == nil { 31 | return errors.New("invalid UUID") 32 | } 33 | *u = id 34 | return nil 35 | } 36 | 37 | // MarshalBinary implements encoding.BinaryMarshaler. 38 | func (u UUID) MarshalBinary() ([]byte, error) { 39 | return u[:], nil 40 | } 41 | 42 | // UnmarshalBinary implements encoding.BinaryUnmarshaler. 43 | func (u *UUID) UnmarshalBinary(data []byte) error { 44 | if len(data) == 0 { 45 | return nil 46 | } 47 | if len(data) != 16 { 48 | return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) 49 | } 50 | var id [16]byte 51 | copy(id[:], data) 52 | *u = id[:] 53 | return nil 54 | } 55 | 56 | // MarshalText implements encoding.TextMarshaler. 57 | func (u Array) MarshalText() ([]byte, error) { 58 | var js [36]byte 59 | encodeHex(js[:], u[:]) 60 | return js[:], nil 61 | } 62 | 63 | // UnmarshalText implements encoding.TextUnmarshaler. 64 | func (u *Array) UnmarshalText(data []byte) error { 65 | id, err := guuid.ParseBytes(data) 66 | if err != nil { 67 | return err 68 | } 69 | *u = Array(id) 70 | return nil 71 | } 72 | 73 | // MarshalBinary implements encoding.BinaryMarshaler. 74 | func (u Array) MarshalBinary() ([]byte, error) { 75 | return u[:], nil 76 | } 77 | 78 | // UnmarshalBinary implements encoding.BinaryUnmarshaler. 79 | func (u *Array) UnmarshalBinary(data []byte) error { 80 | if len(data) != 16 { 81 | return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) 82 | } 83 | copy(u[:], data) 84 | return nil 85 | } 86 | -------------------------------------------------------------------------------- /marshal_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | 5 | package uuid 6 | 7 | import ( 8 | "bytes" 9 | "encoding/json" 10 | "reflect" 11 | "testing" 12 | ) 13 | 14 | var testUUID = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 15 | var testArray = testUUID.Array() 16 | 17 | func TestJSON(t *testing.T) { 18 | type S struct { 19 | ID1 UUID 20 | ID2 UUID 21 | } 22 | s1 := S{ID1: testUUID} 23 | data, err := json.Marshal(&s1) 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | var s2 S 28 | if err := json.Unmarshal(data, &s2); err != nil { 29 | t.Fatal(err) 30 | } 31 | if !reflect.DeepEqual(&s1, &s2) { 32 | t.Errorf("got %#v, want %#v", s2, s1) 33 | } 34 | } 35 | 36 | func TestJSONArray(t *testing.T) { 37 | type S struct { 38 | ID1 Array 39 | ID2 Array 40 | } 41 | s1 := S{ID1: testArray} 42 | data, err := json.Marshal(&s1) 43 | if err != nil { 44 | t.Fatal(err) 45 | } 46 | var s2 S 47 | if err := json.Unmarshal(data, &s2); err != nil { 48 | t.Fatal(err) 49 | } 50 | if !reflect.DeepEqual(&s1, &s2) { 51 | t.Errorf("got %#v, want %#v", s2, s1) 52 | } 53 | } 54 | 55 | func TestMarshal(t *testing.T) { 56 | data, err := testUUID.MarshalBinary() 57 | if err != nil { 58 | t.Fatalf("MarhsalBinary returned unexpected error %v", err) 59 | } 60 | if !bytes.Equal(data, testUUID) { 61 | t.Fatalf("MarhsalBinary returns %x, want %x", data, testUUID) 62 | } 63 | var u UUID 64 | u.UnmarshalBinary(data) 65 | if !Equal(data, u) { 66 | t.Fatalf("UnmarhsalBinary returns %v, want %v", u, testUUID) 67 | } 68 | } 69 | 70 | func TestMarshalArray(t *testing.T) { 71 | data, err := testArray.MarshalBinary() 72 | if err != nil { 73 | t.Fatalf("MarhsalBinary returned unexpected error %v", err) 74 | } 75 | if !bytes.Equal(data, testUUID) { 76 | t.Fatalf("MarhsalBinary returns %x, want %x", data, testUUID) 77 | } 78 | var a Array 79 | a.UnmarshalBinary(data) 80 | if a != testArray { 81 | t.Fatalf("UnmarhsalBinary returns %v, want %v", a, testArray) 82 | } 83 | } 84 | 85 | func TestMarshalTextArray(t *testing.T) { 86 | data, err := testArray.MarshalText() 87 | if err != nil { 88 | t.Fatalf("MarhsalText returned unexpected error %v", err) 89 | } 90 | var a Array 91 | a.UnmarshalText(data) 92 | if a != testArray { 93 | t.Fatalf("UnmarhsalText returns %v, want %v", a, testArray) 94 | } 95 | } 96 | 97 | func BenchmarkUUID_MarshalJSON(b *testing.B) { 98 | x := &struct { 99 | UUID UUID `json:"uuid"` 100 | }{} 101 | x.UUID = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 102 | if x.UUID == nil { 103 | b.Fatal("invalid uuid") 104 | } 105 | for i := 0; i < b.N; i++ { 106 | js, err := json.Marshal(x) 107 | if err != nil { 108 | b.Fatalf("marshal json: %#v (%v)", js, err) 109 | } 110 | } 111 | } 112 | 113 | func BenchmarkUUID_UnmarshalJSON(b *testing.B) { 114 | js := []byte(`{"uuid":"f47ac10b-58cc-0372-8567-0e02b2c3d479"}`) 115 | var x *struct { 116 | UUID UUID `json:"uuid"` 117 | } 118 | for i := 0; i < b.N; i++ { 119 | err := json.Unmarshal(js, &x) 120 | if err != nil { 121 | b.Fatalf("marshal json: %#v (%v)", js, err) 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /node.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | package uuid 6 | 7 | import ( 8 | guuid "github.com/google/uuid" 9 | ) 10 | 11 | // NodeInterface returns the name of the interface from which the NodeID was 12 | // derived. The interface "user" is returned if the NodeID was set by 13 | // SetNodeID. 14 | func NodeInterface() string { 15 | return guuid.NodeInterface() 16 | } 17 | 18 | // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. 19 | // If name is "" then the first usable interface found will be used or a random 20 | // Node ID will be generated. If a named interface cannot be found then false 21 | // is returned. 22 | // 23 | // SetNodeInterface never fails when name is "". 24 | func SetNodeInterface(name string) bool { 25 | return guuid.SetNodeInterface(name) 26 | } 27 | 28 | // NodeID returns a slice of a copy of the current Node ID, setting the Node ID 29 | // if not already set. 30 | func NodeID() []byte { 31 | return guuid.NodeID() 32 | } 33 | 34 | // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes 35 | // of id are used. If id is less than 6 bytes then false is returned and the 36 | // Node ID is not set. 37 | func SetNodeID(id []byte) bool { 38 | return guuid.SetNodeID(id) 39 | } 40 | 41 | // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is 42 | // not valid. The NodeID is only well defined for version 1 and 2 UUIDs. 43 | func (uuid UUID) NodeID() []byte { 44 | if len(uuid) != 16 { 45 | return nil 46 | } 47 | node := make([]byte, 6) 48 | copy(node, uuid[10:]) 49 | return node 50 | } 51 | -------------------------------------------------------------------------------- /seq_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | 5 | package uuid 6 | 7 | import ( 8 | "flag" 9 | "runtime" 10 | "testing" 11 | "time" 12 | ) 13 | 14 | // This test is only run when --regressions is passed on the go test line. 15 | var regressions = flag.Bool("regressions", false, "run uuid regression tests") 16 | 17 | // TestClockSeqRace tests for a particular race condition of returning two 18 | // identical Version1 UUIDs. The duration of 1 minute was chosen as the race 19 | // condition, before being fixed, nearly always occured in under 30 seconds. 20 | func TestClockSeqRace(t *testing.T) { 21 | if !*regressions { 22 | t.Skip("skipping regression tests") 23 | } 24 | duration := time.Minute 25 | 26 | done := make(chan struct{}) 27 | defer close(done) 28 | 29 | ch := make(chan UUID, 10000) 30 | ncpu := runtime.NumCPU() 31 | switch ncpu { 32 | case 0, 1: 33 | // We can't run the test effectively. 34 | t.Skip("skipping race test, only one CPU detected") 35 | return 36 | default: 37 | runtime.GOMAXPROCS(ncpu) 38 | } 39 | for i := 0; i < ncpu; i++ { 40 | go func() { 41 | for { 42 | select { 43 | case <-done: 44 | return 45 | case ch <- NewUUID(): 46 | } 47 | } 48 | }() 49 | } 50 | 51 | uuids := make(map[string]bool) 52 | cnt := 0 53 | start := time.Now() 54 | for u := range ch { 55 | s := u.String() 56 | if uuids[s] { 57 | t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s) 58 | return 59 | } 60 | uuids[s] = true 61 | if time.Since(start) > duration { 62 | return 63 | } 64 | cnt++ 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /sql.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 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 | 5 | package uuid 6 | 7 | import ( 8 | "database/sql/driver" 9 | "errors" 10 | "fmt" 11 | ) 12 | 13 | // Scan implements sql.Scanner so UUIDs can be read from databases transparently 14 | // Currently, database types that map to string and []byte are supported. Please 15 | // consult database-specific driver documentation for matching types. 16 | func (uuid *UUID) Scan(src interface{}) error { 17 | switch src.(type) { 18 | case string: 19 | // if an empty UUID comes from a table, we return a null UUID 20 | if src.(string) == "" { 21 | return nil 22 | } 23 | 24 | // see uuid.Parse for required string format 25 | parsed := Parse(src.(string)) 26 | 27 | if parsed == nil { 28 | return errors.New("Scan: invalid UUID format") 29 | } 30 | 31 | *uuid = parsed 32 | case []byte: 33 | b := src.([]byte) 34 | 35 | // if an empty UUID comes from a table, we return a null UUID 36 | if len(b) == 0 { 37 | return nil 38 | } 39 | 40 | // assumes a simple slice of bytes if 16 bytes 41 | // otherwise attempts to parse 42 | if len(b) == 16 { 43 | parsed := make([]byte, 16) 44 | copy(parsed, b) 45 | *uuid = UUID(parsed) 46 | } else { 47 | u := Parse(string(b)) 48 | 49 | if u == nil { 50 | return errors.New("Scan: invalid UUID format") 51 | } 52 | 53 | *uuid = u 54 | } 55 | 56 | default: 57 | return fmt.Errorf("Scan: unable to scan type %T into UUID", src) 58 | } 59 | 60 | return nil 61 | } 62 | 63 | // Value implements sql.Valuer so that UUIDs can be written to databases 64 | // transparently. Currently, UUIDs map to strings. Please consult 65 | // database-specific driver documentation for matching types. 66 | func (uuid UUID) Value() (driver.Value, error) { 67 | return uuid.String(), nil 68 | } 69 | -------------------------------------------------------------------------------- /sql_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 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 | 5 | package uuid 6 | 7 | import ( 8 | "strings" 9 | "testing" 10 | ) 11 | 12 | func TestScan(t *testing.T) { 13 | var ( 14 | stringTest = "f47ac10b-58cc-0372-8567-0e02b2c3d479" 15 | byteTest = []byte(Parse(stringTest)) 16 | badTypeTest = 6 17 | invalidTest = "f47ac10b-58cc-0372-8567-0e02b2c3d4" 18 | ) 19 | 20 | // sunny day tests 21 | 22 | var uuid UUID 23 | err := (&uuid).Scan(stringTest) 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | 28 | err = (&uuid).Scan([]byte(stringTest)) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | 33 | err = (&uuid).Scan(byteTest) 34 | if err != nil { 35 | t.Fatal(err) 36 | } 37 | 38 | // bad type tests 39 | 40 | err = (&uuid).Scan(badTypeTest) 41 | if err == nil { 42 | t.Error("int correctly parsed and shouldn't have") 43 | } 44 | if !strings.Contains(err.Error(), "unable to scan type") { 45 | t.Error("attempting to parse an int returned an incorrect error message") 46 | } 47 | 48 | // invalid/incomplete uuids 49 | 50 | err = (&uuid).Scan(invalidTest) 51 | if err == nil { 52 | t.Error("invalid uuid was parsed without error") 53 | } 54 | if !strings.Contains(err.Error(), "invalid UUID") { 55 | t.Error("attempting to parse an invalid UUID returned an incorrect error message") 56 | } 57 | 58 | err = (&uuid).Scan(byteTest[:len(byteTest)-2]) 59 | if err == nil { 60 | t.Error("invalid byte uuid was parsed without error") 61 | } 62 | if !strings.Contains(err.Error(), "invalid UUID") { 63 | t.Error("attempting to parse an invalid byte UUID returned an incorrect error message") 64 | } 65 | 66 | // empty tests 67 | 68 | uuid = nil 69 | var emptySlice []byte 70 | err = (&uuid).Scan(emptySlice) 71 | if err != nil { 72 | t.Fatal(err) 73 | } 74 | 75 | if uuid != nil { 76 | t.Error("UUID was not nil after scanning empty byte slice") 77 | } 78 | 79 | uuid = nil 80 | var emptyString string 81 | err = (&uuid).Scan(emptyString) 82 | if err != nil { 83 | t.Fatal(err) 84 | } 85 | 86 | if uuid != nil { 87 | t.Error("UUID was not nil after scanning empty string") 88 | } 89 | } 90 | 91 | func TestValue(t *testing.T) { 92 | stringTest := "f47ac10b-58cc-0372-8567-0e02b2c3d479" 93 | uuid := Parse(stringTest) 94 | val, _ := uuid.Value() 95 | if val != stringTest { 96 | t.Error("Value() did not return expected string") 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /time.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | 5 | package uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | 10 | guuid "github.com/google/uuid" 11 | ) 12 | 13 | // A Time represents a time as the number of 100's of nanoseconds since 15 Oct 14 | // 1582. 15 | type Time = guuid.Time 16 | 17 | // GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and 18 | // clock sequence as well as adjusting the clock sequence as needed. An error 19 | // is returned if the current time cannot be determined. 20 | func GetTime() (Time, uint16, error) { return guuid.GetTime() } 21 | 22 | // ClockSequence returns the current clock sequence, generating one if not 23 | // already set. The clock sequence is only used for Version 1 UUIDs. 24 | // 25 | // The uuid package does not use global static storage for the clock sequence or 26 | // the last time a UUID was generated. Unless SetClockSequence a new random 27 | // clock sequence is generated the first time a clock sequence is requested by 28 | // ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated 29 | // for 30 | func ClockSequence() int { return guuid.ClockSequence() } 31 | 32 | // SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to 33 | // -1 causes a new sequence to be generated. 34 | func SetClockSequence(seq int) { guuid.SetClockSequence(seq) } 35 | 36 | // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in 37 | // uuid. It returns false if uuid is not valid. The time is only well defined 38 | // for version 1 and 2 UUIDs. 39 | func (uuid UUID) Time() (Time, bool) { 40 | if len(uuid) != 16 { 41 | return 0, false 42 | } 43 | time := int64(binary.BigEndian.Uint32(uuid[0:4])) 44 | time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 45 | time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 46 | return Time(time), true 47 | } 48 | 49 | // ClockSequence returns the clock sequence encoded in uuid. It returns false 50 | // if uuid is not valid. The clock sequence is only well defined for version 1 51 | // and 2 UUIDs. 52 | func (uuid UUID) ClockSequence() (int, bool) { 53 | if len(uuid) != 16 { 54 | return 0, false 55 | } 56 | return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true 57 | } 58 | -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | package uuid 6 | 7 | // xvalues returns the value of a byte as a hexadecimal digit or 255. 8 | var xvalues = [256]byte{ 9 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 10 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 11 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 12 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 13 | 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 14 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15 | 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 16 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 17 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 18 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 19 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 20 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 21 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 23 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 24 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 25 | } 26 | 27 | // xtob converts the the first two hex bytes of x into a byte. 28 | func xtob(x string) (byte, bool) { 29 | b1 := xvalues[x[0]] 30 | b2 := xvalues[x[1]] 31 | return (b1 << 4) | b2, b1 != 255 && b2 != 255 32 | } 33 | -------------------------------------------------------------------------------- /uuid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | package uuid 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "encoding/hex" 11 | "io" 12 | 13 | guuid "github.com/google/uuid" 14 | ) 15 | 16 | // Array is a pass-by-value UUID that can be used as an effecient key in a map. 17 | type Array [16]byte 18 | 19 | // UUID converts uuid into a slice. 20 | func (uuid Array) UUID() UUID { 21 | return uuid[:] 22 | } 23 | 24 | // String returns the string representation of uuid, 25 | // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. 26 | func (uuid Array) String() string { 27 | return guuid.UUID(uuid).String() 28 | } 29 | 30 | // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC 31 | // 4122. 32 | type UUID []byte 33 | 34 | // A Version represents a UUIDs version. 35 | type Version = guuid.Version 36 | 37 | // A Variant represents a UUIDs variant. 38 | type Variant = guuid.Variant 39 | 40 | // Constants returned by Variant. 41 | const ( 42 | Invalid = guuid.Invalid // Invalid UUID 43 | RFC4122 = guuid.RFC4122 // The variant specified in RFC4122 44 | Reserved = guuid.Reserved // Reserved, NCS backward compatibility. 45 | Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility. 46 | Future = guuid.Future // Reserved for future definition. 47 | ) 48 | 49 | var rander = rand.Reader // random function 50 | 51 | // New returns a new random (version 4) UUID as a string. It is a convenience 52 | // function for NewRandom().String(). 53 | func New() string { 54 | return NewRandom().String() 55 | } 56 | 57 | // Parse decodes s into a UUID or returns nil. See github.com/google/uuid for 58 | // the formats parsed. 59 | func Parse(s string) UUID { 60 | gu, err := guuid.Parse(s) 61 | if err == nil { 62 | return gu[:] 63 | } 64 | return nil 65 | } 66 | 67 | // ParseBytes is like Parse, except it parses a byte slice instead of a string. 68 | func ParseBytes(b []byte) (UUID, error) { 69 | gu, err := guuid.ParseBytes(b) 70 | if err == nil { 71 | return gu[:], nil 72 | } 73 | return nil, err 74 | } 75 | 76 | // Equal returns true if uuid1 and uuid2 are equal. 77 | func Equal(uuid1, uuid2 UUID) bool { 78 | return bytes.Equal(uuid1, uuid2) 79 | } 80 | 81 | // Array returns an array representation of uuid that can be used as a map key. 82 | // Array panics if uuid is not valid. 83 | func (uuid UUID) Array() Array { 84 | if len(uuid) != 16 { 85 | panic("invalid uuid") 86 | } 87 | var a Array 88 | copy(a[:], uuid) 89 | return a 90 | } 91 | 92 | // String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 93 | // , or "" if uuid is invalid. 94 | func (uuid UUID) String() string { 95 | if len(uuid) != 16 { 96 | return "" 97 | } 98 | var buf [36]byte 99 | encodeHex(buf[:], uuid) 100 | return string(buf[:]) 101 | } 102 | 103 | // URN returns the RFC 2141 URN form of uuid, 104 | // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid. 105 | func (uuid UUID) URN() string { 106 | if len(uuid) != 16 { 107 | return "" 108 | } 109 | var buf [36 + 9]byte 110 | copy(buf[:], "urn:uuid:") 111 | encodeHex(buf[9:], uuid) 112 | return string(buf[:]) 113 | } 114 | 115 | func encodeHex(dst []byte, uuid UUID) { 116 | hex.Encode(dst[:], uuid[:4]) 117 | dst[8] = '-' 118 | hex.Encode(dst[9:13], uuid[4:6]) 119 | dst[13] = '-' 120 | hex.Encode(dst[14:18], uuid[6:8]) 121 | dst[18] = '-' 122 | hex.Encode(dst[19:23], uuid[8:10]) 123 | dst[23] = '-' 124 | hex.Encode(dst[24:], uuid[10:]) 125 | } 126 | 127 | // Variant returns the variant encoded in uuid. It returns Invalid if 128 | // uuid is invalid. 129 | func (uuid UUID) Variant() Variant { 130 | if len(uuid) != 16 { 131 | return Invalid 132 | } 133 | switch { 134 | case (uuid[8] & 0xc0) == 0x80: 135 | return RFC4122 136 | case (uuid[8] & 0xe0) == 0xc0: 137 | return Microsoft 138 | case (uuid[8] & 0xe0) == 0xe0: 139 | return Future 140 | default: 141 | return Reserved 142 | } 143 | } 144 | 145 | // Version returns the version of uuid. It returns false if uuid is not 146 | // valid. 147 | func (uuid UUID) Version() (Version, bool) { 148 | if len(uuid) != 16 { 149 | return 0, false 150 | } 151 | return Version(uuid[6] >> 4), true 152 | } 153 | 154 | // SetRand sets the random number generator to r, which implements io.Reader. 155 | // If r.Read returns an error when the package requests random data then 156 | // a panic will be issued. 157 | // 158 | // Calling SetRand with nil sets the random number generator to the default 159 | // generator. 160 | func SetRand(r io.Reader) { 161 | guuid.SetRand(r) 162 | } 163 | -------------------------------------------------------------------------------- /uuid_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | package uuid 6 | 7 | // Some of these tests can probably be removed as they are redundant with the 8 | // tests in github.com/google/uuid. 9 | 10 | import ( 11 | "bytes" 12 | "fmt" 13 | "os" 14 | "strings" 15 | "testing" 16 | ) 17 | 18 | type test struct { 19 | in string 20 | version Version 21 | variant Variant 22 | isuuid bool 23 | } 24 | 25 | var tests = []test{ 26 | {"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true}, 27 | {"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true}, 28 | {"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true}, 29 | {"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true}, 30 | {"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true}, 31 | {"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true}, 32 | {"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true}, 33 | {"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true}, 34 | {"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true}, 35 | {"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true}, 36 | {"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true}, 37 | {"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true}, 38 | {"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true}, 39 | {"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true}, 40 | {"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true}, 41 | {"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true}, 42 | 43 | {"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, 44 | {"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, 45 | {"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, 46 | {"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true}, 47 | {"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true}, 48 | {"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true}, 49 | {"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true}, 50 | {"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true}, 51 | {"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true}, 52 | {"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true}, 53 | {"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true}, 54 | {"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true}, 55 | {"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true}, 56 | {"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true}, 57 | {"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true}, 58 | {"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true}, 59 | {"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true}, 60 | {"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true}, 61 | 62 | {"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false}, 63 | {"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false}, 64 | {"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false}, 65 | {"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false}, 66 | {"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false}, 67 | {"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false}, 68 | } 69 | 70 | var constants = []struct { 71 | c interface{} 72 | name string 73 | }{ 74 | {Person, "Person"}, 75 | {Group, "Group"}, 76 | {Org, "Org"}, 77 | {Invalid, "Invalid"}, 78 | {RFC4122, "RFC4122"}, 79 | {Reserved, "Reserved"}, 80 | {Microsoft, "Microsoft"}, 81 | {Future, "Future"}, 82 | {Domain(17), "Domain17"}, 83 | {Variant(42), "BadVariant42"}, 84 | } 85 | 86 | func testTest(t *testing.T, in string, tt test) { 87 | uuid := Parse(in) 88 | if ok := (uuid != nil); ok != tt.isuuid { 89 | t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid) 90 | } 91 | if uuid == nil { 92 | return 93 | } 94 | 95 | if v := uuid.Variant(); v != tt.variant { 96 | t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant) 97 | } 98 | if v, _ := uuid.Version(); v != tt.version { 99 | t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version) 100 | } 101 | } 102 | 103 | func TestUUID(t *testing.T) { 104 | for _, tt := range tests { 105 | testTest(t, tt.in, tt) 106 | testTest(t, strings.ToUpper(tt.in), tt) 107 | } 108 | } 109 | 110 | func TestConstants(t *testing.T) { 111 | for x, tt := range constants { 112 | v, ok := tt.c.(fmt.Stringer) 113 | if !ok { 114 | t.Errorf("%x: %v: not a stringer", x, v) 115 | } else if s := v.String(); s != tt.name { 116 | v, _ := tt.c.(int) 117 | t.Errorf("%x: Constant %T:%d gives %q, expected %q", x, tt.c, v, s, tt.name) 118 | } 119 | } 120 | } 121 | 122 | func TestRandomUUID(t *testing.T) { 123 | m := make(map[string]bool) 124 | for x := 1; x < 32; x++ { 125 | uuid := NewRandom() 126 | s := uuid.String() 127 | if m[s] { 128 | t.Errorf("NewRandom returned duplicated UUID %s", s) 129 | } 130 | m[s] = true 131 | if v, _ := uuid.Version(); v != 4 { 132 | t.Errorf("Random UUID of version %s", v) 133 | } 134 | if uuid.Variant() != RFC4122 { 135 | t.Errorf("Random UUID is variant %d", uuid.Variant()) 136 | } 137 | } 138 | } 139 | 140 | func TestNew(t *testing.T) { 141 | m := make(map[string]bool) 142 | for x := 1; x < 32; x++ { 143 | s := New() 144 | if m[s] { 145 | t.Errorf("New returned duplicated UUID %s", s) 146 | } 147 | m[s] = true 148 | uuid := Parse(s) 149 | if uuid == nil { 150 | t.Errorf("New returned %q which does not decode", s) 151 | continue 152 | } 153 | if v, _ := uuid.Version(); v != 4 { 154 | t.Errorf("Random UUID of version %s", v) 155 | } 156 | if uuid.Variant() != RFC4122 { 157 | t.Errorf("Random UUID is variant %d", uuid.Variant()) 158 | } 159 | } 160 | } 161 | 162 | func TestCoding(t *testing.T) { 163 | text := "7d444840-9dc0-11d1-b245-5ffdce74fad2" 164 | urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2" 165 | data := UUID{ 166 | 0x7d, 0x44, 0x48, 0x40, 167 | 0x9d, 0xc0, 168 | 0x11, 0xd1, 169 | 0xb2, 0x45, 170 | 0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2, 171 | } 172 | if v := data.String(); v != text { 173 | t.Errorf("%x: encoded to %s, expected %s", data, v, text) 174 | } 175 | if v := data.URN(); v != urn { 176 | t.Errorf("%x: urn is %s, expected %s", data, v, urn) 177 | } 178 | 179 | uuid := Parse(text) 180 | if !Equal(uuid, data) { 181 | t.Errorf("%s: decoded to %s, expected %s", text, uuid, data) 182 | } 183 | } 184 | 185 | func TestVersion1(t *testing.T) { 186 | uuid1 := NewUUID() 187 | uuid2 := NewUUID() 188 | 189 | if Equal(uuid1, uuid2) { 190 | t.Errorf("%s:duplicate uuid", uuid1) 191 | } 192 | if v, _ := uuid1.Version(); v != 1 { 193 | t.Errorf("%s: version %s expected 1", uuid1, v) 194 | } 195 | if v, _ := uuid2.Version(); v != 1 { 196 | t.Errorf("%s: version %s expected 1", uuid2, v) 197 | } 198 | n1 := uuid1.NodeID() 199 | n2 := uuid2.NodeID() 200 | if !bytes.Equal(n1, n2) { 201 | t.Errorf("Different nodes %x != %x", n1, n2) 202 | } 203 | t1, ok := uuid1.Time() 204 | if !ok { 205 | t.Errorf("%s: invalid time", uuid1) 206 | } 207 | t2, ok := uuid2.Time() 208 | if !ok { 209 | t.Errorf("%s: invalid time", uuid2) 210 | } 211 | q1, ok := uuid1.ClockSequence() 212 | if !ok { 213 | t.Errorf("%s: invalid clock sequence", uuid1) 214 | } 215 | q2, ok := uuid2.ClockSequence() 216 | if !ok { 217 | t.Errorf("%s: invalid clock sequence", uuid2) 218 | } 219 | 220 | switch { 221 | case t1 == t2 && q1 == q2: 222 | t.Error("time stopped") 223 | case t1 > t2 && q1 == q2: 224 | t.Error("time reversed") 225 | case t1 < t2 && q1 != q2: 226 | t.Error("clock sequence chaned unexpectedly") 227 | } 228 | } 229 | 230 | func TestMD5(t *testing.T) { 231 | uuid := NewMD5(NameSpace_DNS, []byte("python.org")).String() 232 | want := "6fa459ea-ee8a-3ca4-894e-db77e160355e" 233 | if uuid != want { 234 | t.Errorf("MD5: got %q expected %q", uuid, want) 235 | } 236 | } 237 | 238 | func TestSHA1(t *testing.T) { 239 | uuid := NewSHA1(NameSpace_DNS, []byte("python.org")).String() 240 | want := "886313e1-3b8a-5372-9b90-0c9aee199e5d" 241 | if uuid != want { 242 | t.Errorf("SHA1: got %q expected %q", uuid, want) 243 | } 244 | } 245 | 246 | func testDCE(t *testing.T, name string, uuid UUID, domain Domain, id uint32) { 247 | if uuid == nil { 248 | t.Errorf("%s failed", name) 249 | return 250 | } 251 | if v, _ := uuid.Version(); v != 2 { 252 | t.Errorf("%s: %s: expected version 2, got %s", name, uuid, v) 253 | return 254 | } 255 | if v, ok := uuid.Domain(); !ok || v != domain { 256 | if !ok { 257 | t.Errorf("%s: %d: Domain failed", name, uuid) 258 | } else { 259 | t.Errorf("%s: %s: expected domain %d, got %d", name, uuid, domain, v) 260 | } 261 | } 262 | if v, ok := uuid.Id(); !ok || v != id { 263 | if !ok { 264 | t.Errorf("%s: %d: ID failed", name, uuid) 265 | } else { 266 | t.Errorf("%s: %s: expected id %d, got %d", name, uuid, id, v) 267 | } 268 | } 269 | } 270 | 271 | func TestDCE(t *testing.T) { 272 | testDCE(t, "NewDCESecurity", NewDCESecurity(42, 12345678), 42, 12345678) 273 | testDCE(t, "NewDCEPerson", NewDCEPerson(), Person, uint32(os.Getuid())) 274 | testDCE(t, "NewDCEGroup", NewDCEGroup(), Group, uint32(os.Getgid())) 275 | } 276 | 277 | type badRand struct{} 278 | 279 | func (r badRand) Read(buf []byte) (int, error) { 280 | for i := range buf { 281 | buf[i] = byte(i) 282 | } 283 | return len(buf), nil 284 | } 285 | 286 | func TestBadRand(t *testing.T) { 287 | SetRand(badRand{}) 288 | uuid1 := New() 289 | uuid2 := New() 290 | if uuid1 != uuid2 { 291 | t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2) 292 | } 293 | SetRand(nil) 294 | uuid1 = New() 295 | uuid2 = New() 296 | if uuid1 == uuid2 { 297 | t.Errorf("unexpected duplicates, got %q", uuid1) 298 | } 299 | } 300 | 301 | func TestUUID_Array(t *testing.T) { 302 | expect := Array{ 303 | 0xf4, 0x7a, 0xc1, 0x0b, 304 | 0x58, 0xcc, 305 | 0x03, 0x72, 306 | 0x85, 0x67, 307 | 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, 308 | } 309 | uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 310 | if uuid == nil { 311 | t.Fatal("invalid uuid") 312 | } 313 | if uuid.Array() != expect { 314 | t.Fatal("invalid array") 315 | } 316 | } 317 | 318 | func TestArray_UUID(t *testing.T) { 319 | array := Array{ 320 | 0xf4, 0x7a, 0xc1, 0x0b, 321 | 0x58, 0xcc, 322 | 0x03, 0x72, 323 | 0x85, 0x67, 324 | 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, 325 | } 326 | expect := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 327 | if expect == nil { 328 | t.Fatal("invalid uuid") 329 | } 330 | if !bytes.Equal(array.UUID(), expect) { 331 | t.Fatal("invalid uuid") 332 | } 333 | } 334 | 335 | func BenchmarkParse(b *testing.B) { 336 | for i := 0; i < b.N; i++ { 337 | uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 338 | if uuid == nil { 339 | b.Fatal("invalid uuid") 340 | } 341 | } 342 | } 343 | 344 | func BenchmarkNew(b *testing.B) { 345 | for i := 0; i < b.N; i++ { 346 | New() 347 | } 348 | } 349 | 350 | func BenchmarkUUID_String(b *testing.B) { 351 | uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 352 | if uuid == nil { 353 | b.Fatal("invalid uuid") 354 | } 355 | for i := 0; i < b.N; i++ { 356 | if uuid.String() == "" { 357 | b.Fatal("invalid uuid") 358 | } 359 | } 360 | } 361 | 362 | func BenchmarkUUID_URN(b *testing.B) { 363 | uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 364 | if uuid == nil { 365 | b.Fatal("invalid uuid") 366 | } 367 | for i := 0; i < b.N; i++ { 368 | if uuid.URN() == "" { 369 | b.Fatal("invalid uuid") 370 | } 371 | } 372 | } 373 | 374 | func BenchmarkUUID_Array(b *testing.B) { 375 | expect := Array{ 376 | 0xf4, 0x7a, 0xc1, 0x0b, 377 | 0x58, 0xcc, 378 | 0x03, 0x72, 379 | 0x85, 0x67, 380 | 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, 381 | } 382 | uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 383 | if uuid == nil { 384 | b.Fatal("invalid uuid") 385 | } 386 | for i := 0; i < b.N; i++ { 387 | if uuid.Array() != expect { 388 | b.Fatal("invalid array") 389 | } 390 | } 391 | } 392 | 393 | func BenchmarkArray_UUID(b *testing.B) { 394 | array := Array{ 395 | 0xf4, 0x7a, 0xc1, 0x0b, 396 | 0x58, 0xcc, 397 | 0x03, 0x72, 398 | 0x85, 0x67, 399 | 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, 400 | } 401 | expect := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") 402 | if expect == nil { 403 | b.Fatal("invalid uuid") 404 | } 405 | for i := 0; i < b.N; i++ { 406 | if !bytes.Equal(array.UUID(), expect) { 407 | b.Fatal("invalid uuid") 408 | } 409 | } 410 | } 411 | -------------------------------------------------------------------------------- /version1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | package uuid 6 | 7 | import ( 8 | guuid "github.com/google/uuid" 9 | ) 10 | 11 | // NewUUID returns a Version 1 UUID based on the current NodeID and clock 12 | // sequence, and the current time. If the NodeID has not been set by SetNodeID 13 | // or SetNodeInterface then it will be set automatically. If the NodeID cannot 14 | // be set NewUUID returns nil. If clock sequence has not been set by 15 | // SetClockSequence then it will be set automatically. If GetTime fails to 16 | // return the current NewUUID returns nil. 17 | func NewUUID() UUID { 18 | gu, err := guuid.NewUUID() 19 | if err == nil { 20 | return UUID(gu[:]) 21 | } 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /version4.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | 5 | package uuid 6 | 7 | import guuid "github.com/google/uuid" 8 | 9 | // NewRandom returns a Random (Version 4) UUID or panics. 10 | // 11 | // The strength of the UUIDs is based on the strength of the crypto/rand 12 | // package. 13 | // 14 | // A note about uniqueness derived from the UUID Wikipedia entry: 15 | // 16 | // Randomly generated UUIDs have 122 random bits. One's annual risk of being 17 | // hit by a meteorite is estimated to be one chance in 17 billion, that 18 | // means the probability is about 0.00000000006 (6 × 10−11), 19 | // equivalent to the odds of creating a few tens of trillions of UUIDs in a 20 | // year and having one duplicate. 21 | func NewRandom() UUID { 22 | if gu, err := guuid.NewRandom(); err == nil { 23 | return UUID(gu[:]) 24 | } 25 | return nil 26 | } 27 | --------------------------------------------------------------------------------