diff --git a/uuid.go b/uuid.go index c4482cd..744330c 100644 --- a/uuid.go +++ b/uuid.go @@ -13,6 +13,14 @@ import ( "strings" ) +// Array is a pass-by-value UUID that can be used as an effecient key in a map. +type Array [16]byte + +// UUID converts uuid into a slice. +func (uuid Array) UUID() UUID { + return uuid[:] +} + // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC // 4122. type UUID []byte @@ -76,6 +84,17 @@ func Equal(uuid1, uuid2 UUID) bool { return bytes.Equal(uuid1, uuid2) } +// Array returns an array representation of uuid that can be used as a map key. +// Array panics if uuid is not valid. +func (uuid UUID) Array() Array { + if len(uuid) != 16 { + panic("invalid uuid") + } + var a Array + copy(a[:], uuid) + return a +} + // String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx // , or "" if uuid is invalid. func (uuid UUID) String() string { diff --git a/uuid_test.go b/uuid_test.go index 3835cc8..e6163c7 100644 --- a/uuid_test.go +++ b/uuid_test.go @@ -300,7 +300,7 @@ func TestNode(t *testing.T) { t.Error("nodeid is all zeros") } - id := []byte{1,2,3,4,5,6,7,8} + id := []byte{1, 2, 3, 4, 5, 6, 7, 8} SetNodeID(id) ni = NodeID() if !bytes.Equal(ni, id[:6]) { @@ -431,6 +431,41 @@ func TestBadRand(t *testing.T) { } } +func TestUUID_Array(t *testing.T) { + uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") + expect := []byte{ + 0xf4, 0x7a, 0xc1, 0x0b, + 0x58, 0xcc, + 0x03, 0x72, + 0x85, 0x67, + 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, + } + if uuid == nil { + t.Fatal("invalid uuid") + } + array := uuid.Array() + if !bytes.Equal(array[:], expect) { + t.Fatal("invalid array") + } +} + +func TestArray_UUID(t *testing.T) { + array := Array{ + 0xf4, 0x7a, 0xc1, 0x0b, + 0x58, 0xcc, + 0x03, 0x72, + 0x85, 0x67, + 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, + } + expect := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") + if expect == nil { + t.Fatal("invalid uuid") + } + if !bytes.Equal(array.UUID(), expect) { + t.Fatal("invalid uuid") + } +} + func BenchmarkParse(b *testing.B) { for i := 0; i < b.N; i++ { uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") @@ -469,3 +504,42 @@ func BenchmarkUUID_URN(b *testing.B) { } } } + +func BenchmarkUUID_Array(b *testing.B) { + uuid := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") + expect := []byte{ + 0xf4, 0x7a, 0xc1, 0x0b, + 0x58, 0xcc, + 0x03, 0x72, + 0x85, 0x67, + 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, + } + if uuid == nil { + b.Fatal("invalid uuid") + } + for i := 0; i < b.N; i++ { + array := uuid.Array() + if !bytes.Equal(array[:], expect) { + b.Fatal("invalid array") + } + } +} + +func BenchmarkArray_UUID(b *testing.B) { + array := Array{ + 0xf4, 0x7a, 0xc1, 0x0b, + 0x58, 0xcc, + 0x03, 0x72, + 0x85, 0x67, + 0x0e, 0x02, 0xb2, 0xc3, 0xd4, 0x79, + } + expect := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") + if expect == nil { + b.Fatal("invalid uuid") + } + for i := 0; i < b.N; i++ { + if !bytes.Equal(array.UUID(), expect) { + b.Fatal("invalid uuid") + } + } +}