Skip to content

Instantly share code, notes, and snippets.

@dchest
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dchest/bdbedeab541b43087395 to your computer and use it in GitHub Desktop.
Save dchest/bdbedeab541b43087395 to your computer and use it in GitHub Desktop.
// Written by Dmitry Chestnykh. Public domain.
// Package uuid provides Universally unique identifiers.
package uuid
import (
"crypto/rand"
"fmt"
"io"
)
type UUID string
// Bytes returns a bytes representation of UUID or nil if UUID has bad format.
func (u UUID) Bytes() []byte {
var b [16]byte
n, err := fmt.Sscanf(string(u),
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
&b[0], &b[1], &b[2], &b[3], &b[4], &b[5], &b[6], &b[7], &b[8],
&b[9], &b[10], &b[11], &b[12], &b[13], &b[14], &b[15])
if n != 16 || err != nil {
return nil
}
return b[:]
}
// FromBytes returns UUID from bytes representation.
func FromBytes(b []byte) UUID {
return UUID(fmt.Sprintf("%08x-%04x-%04x-%04x-%012x", b[:4], b[4:6], b[6:8], b[8:10], b[10:]))
}
// New returns a new random UUID v4.
func New() UUID {
var b [16]byte
if _, err := io.ReadFull(rand.Reader, b[:]); err != nil {
panic("error reading random numbers: " + err.Error())
}
b[6] = (b[6] & 0x0f) | (4 << 4)
b[8] = (b[8] & 0xbf) | 0x80
return FromBytes(b[:])
}
package uuid
import (
"bytes"
"testing"
)
const id = UUID("5154e02d-57cd-4da9-9194-d199946681a6")
func TestBytes(t *testing.T) {
good := []byte{0x51, 0x54, 0xe0, 0x2d, 0x57, 0xcd, 0x4d, 0xa9, 0x91, 0x94, 0xd1, 0x99, 0x94, 0x66, 0x81, 0xa6}
b := id.Bytes()
if b == nil {
t.Fatalf("returned nil")
}
if !bytes.Equal(good, b) {
t.Fatalf("wrong result: expected %x, got %x", good, b)
}
}
func TestBadBytes(t *testing.T) {
bad := "ZZCAFA12-F257-11E3-B24E-B7BCECBA0006"
b := UUID(bad).Bytes()
if b != nil {
t.Fatalf("converted bad uuid (%s): %x", bad, b)
}
}
func TestFromBytes(t *testing.T) {
b := id.Bytes()
s := FromBytes(b)
if id != s {
t.Fatalf("wrong result: expected %s, got %s", id, s)
}
}
func TestNew(t *testing.T) {
m := make(map[UUID]interface{})
var yes interface{}
for i := 0; i < 10000; i++ {
v := New()
if _, ok := m[v]; ok {
t.Errorf("uuid: collision on %d: %s", i, v)
}
m[v] = yes
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment