From 948ea8c7eefa8cab81b8b6cddd2b5582c71b1047 Mon Sep 17 00:00:00 2001 From: Bart Meuris Date: Thu, 25 Aug 2022 14:22:52 +0200 Subject: [PATCH] Improve UUID (#107) Improvements to UUID: * uuid now works with upper and lowercase * sped up UUID.String() using stringbuilder, added benchmark * UUID.String(): grow builder to prevent allocs * make test in cicd happy --- uuid.go | 23 ++++++++++++++--------- uuid_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/uuid.go b/uuid.go index 97fe11b..b632fbc 100644 --- a/uuid.go +++ b/uuid.go @@ -3,7 +3,10 @@ package bluetooth // This file implements 16-bit and 128-bit UUIDs as defined in the Bluetooth // specification. -import "errors" +import ( + "errors" + "strings" +) // UUID is a single UUID as used in the Bluetooth stack. It is represented as a // [4]uint32 instead of a [16]byte for efficiency. @@ -90,6 +93,8 @@ func ParseUUID(s string) (uuid UUID, err error) { nibble = c - '0' + 0x0 } else if c >= 'a' && c <= 'f' { nibble = c - 'a' + 0xa + } else if c >= 'A' && c <= 'F' { + nibble = c - 'A' + 0xa } else { err = errInvalidUUID return @@ -112,13 +117,13 @@ func ParseUUID(s string) (uuid UUID, err error) { // String returns a human-readable version of this UUID, such as // 00001234-0000-1000-8000-00805f9b34fb. func (uuid UUID) String() string { - // TODO: make this more efficient. - s := "" + var s strings.Builder + s.Grow(36) raw := uuid.Bytes() for i := range raw { // Insert a hyphen at the correct locations. if i == 4 || i == 6 || i == 8 || i == 10 { - s += "-" + s.WriteRune('-') } // The character to convert to hex. @@ -127,19 +132,19 @@ func (uuid UUID) String() string { // First nibble. nibble := c >> 4 if nibble <= 9 { - s += string(nibble + '0') + s.WriteByte(nibble + '0') } else { - s += string(nibble + 'a' - 10) + s.WriteByte(nibble + 'a' - 10) } // Second nibble. nibble = c & 0x0f if nibble <= 9 { - s += string(nibble + '0') + s.WriteByte(nibble + '0') } else { - s += string(nibble + 'a' - 10) + s.WriteByte(nibble + 'a' - 10) } } - return s + return s.String() } diff --git a/uuid_test.go b/uuid_test.go index 5e47409..5cf35f4 100644 --- a/uuid_test.go +++ b/uuid_test.go @@ -1,6 +1,7 @@ package bluetooth import ( + "strings" "testing" ) @@ -38,3 +39,35 @@ func TestStringUUID(t *testing.T) { t.Errorf("expected %s but got %s", uuidString, u.String()) } } + +func TestStringUUIDUpperCase(t *testing.T) { + uuidString := strings.ToUpper("00001234-0000-1000-8000-00805f9b34fb") + u, e := ParseUUID(uuidString) + if e != nil { + t.Errorf("expected nil but got %v", e) + } + if !strings.EqualFold(u.String(), uuidString) { + t.Errorf("%s does not match %s ignoring case", uuidString, u.String()) + } +} + +func TestStringUUIDLowerCase(t *testing.T) { + uuidString := strings.ToLower("00001234-0000-1000-8000-00805f9b34fb") + u, e := ParseUUID(uuidString) + if e != nil { + t.Errorf("expected nil but got %v", e) + } + if !strings.EqualFold(u.String(), uuidString) { + t.Errorf("%s does not match %s ignoring case", uuidString, u.String()) + } +} + +func BenchmarkUUIDToString(b *testing.B) { + uuid, e := ParseUUID("00001234-0000-1000-8000-00805f9b34fb") + if e != nil { + b.Errorf("expected nil but got %v", e) + } + for i := 0; i < b.N; i++ { + _ = uuid.String() + } +}