From 3f8b0b0fa251a060ead95bb8ec08ac4f01d0f6c3 Mon Sep 17 00:00:00 2001 From: Maxim Bublis Date: Wed, 4 Dec 2013 19:01:44 +0400 Subject: [PATCH] Added FromString parser --- benchmarks_test.go | 21 +++++++++++++++++++++ uuid.go | 29 +++++++++++++++++++++++++++++ uuid_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/benchmarks_test.go b/benchmarks_test.go index 542e659..fd261d1 100644 --- a/benchmarks_test.go +++ b/benchmarks_test.go @@ -32,6 +32,27 @@ func BenchmarkFromBytes(b *testing.B) { } } +func BenchmarkFromString(b *testing.B) { + s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" + for i := 0; i < b.N; i++ { + FromString(s) + } +} + +func BenchmarkFromStringUrn(b *testing.B) { + s := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" + for i := 0; i < b.N; i++ { + FromString(s) + } +} + +func BenchmarkFromStringWithBrackets(b *testing.B) { + s := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" + for i := 0; i < b.N; i++ { + FromString(s) + } +} + func BenchmarkNewV1(b *testing.B) { for i := 0; i < b.N; i++ { NewV1() diff --git a/uuid.go b/uuid.go index ef7de47..4c90106 100644 --- a/uuid.go +++ b/uuid.go @@ -30,10 +30,12 @@ import ( "crypto/rand" "crypto/sha1" "encoding/binary" + "encoding/hex" "fmt" "hash" "net" "os" + "strings" "time" ) @@ -192,6 +194,31 @@ func FromBytes(input []byte) (u UUID, err error) { return } +// FromString returns UUID parsed from string input. +// Following formats are supported: +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" +func FromString(input string) (u UUID, err error) { + s := strings.Replace(input, "-", "", -1) + + if len(s) == 41 && s[:9] == "urn:uuid:" { + s = s[9:] + } else if len(s) == 34 && s[0] == '{' && s[33] == '}' { + s = s[1:33] + } + + if len(s) != 32 { + err = fmt.Errorf("Invalid UUID string: %s", input) + return + } + + b := []byte(s) + _, err = hex.Decode(u[:], b) + + return +} + // NewV1 returns UUID based on current timestamp and MAC address. func NewV1() UUID { u := UUID{} @@ -228,7 +255,9 @@ func NewV2(domain byte) UUID { binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) binary.BigEndian.PutUint16(u[8:], clockSequence) u[9] = domain + copy(u[10:], hardwareAddr[:]) + u.SetVersion(2) u.SetVariant() diff --git a/uuid_test.go b/uuid_test.go index 7f3fc40..0dec83d 100644 --- a/uuid_test.go +++ b/uuid_test.go @@ -137,6 +137,46 @@ func TestFromBytes(t *testing.T) { } } +func TestFromString(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" + s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" + s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" + + _, err := FromString("") + if err == nil { + t.Errorf("Should return error trying to parse empty string, got %s", err) + } + + u1, err := FromString(s1) + if err != nil { + t.Errorf("Error parsing UUID from string: %s", err) + } + + if !Equal(u, u1) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1) + } + + u2, err := FromString(s2) + if err != nil { + t.Errorf("Error parsing UUID from string: %s", err) + } + + if !Equal(u, u2) { + t.Errorf("UUIDs should be equal: %s and %s", u, u2) + } + + u3, err := FromString(s3) + if err != nil { + t.Errorf("Error parsing UUID from string: %s", err) + } + + if !Equal(u, u3) { + t.Errorf("UUIDs should be equal: %s and %s", u, u3) + } +} + func TestNewV1(t *testing.T) { u := NewV1()