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
This commit is contained in:
Bart Meuris 2022-08-25 14:22:52 +02:00 committed by GitHub
parent 25349d381e
commit 948ea8c7ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 9 deletions

23
uuid.go
View file

@ -3,7 +3,10 @@ package bluetooth
// This file implements 16-bit and 128-bit UUIDs as defined in the Bluetooth // This file implements 16-bit and 128-bit UUIDs as defined in the Bluetooth
// specification. // specification.
import "errors" import (
"errors"
"strings"
)
// UUID is a single UUID as used in the Bluetooth stack. It is represented as a // 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. // [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 nibble = c - '0' + 0x0
} else if c >= 'a' && c <= 'f' { } else if c >= 'a' && c <= 'f' {
nibble = c - 'a' + 0xa nibble = c - 'a' + 0xa
} else if c >= 'A' && c <= 'F' {
nibble = c - 'A' + 0xa
} else { } else {
err = errInvalidUUID err = errInvalidUUID
return return
@ -112,13 +117,13 @@ func ParseUUID(s string) (uuid UUID, err error) {
// String returns a human-readable version of this UUID, such as // String returns a human-readable version of this UUID, such as
// 00001234-0000-1000-8000-00805f9b34fb. // 00001234-0000-1000-8000-00805f9b34fb.
func (uuid UUID) String() string { func (uuid UUID) String() string {
// TODO: make this more efficient. var s strings.Builder
s := "" s.Grow(36)
raw := uuid.Bytes() raw := uuid.Bytes()
for i := range raw { for i := range raw {
// Insert a hyphen at the correct locations. // Insert a hyphen at the correct locations.
if i == 4 || i == 6 || i == 8 || i == 10 { if i == 4 || i == 6 || i == 8 || i == 10 {
s += "-" s.WriteRune('-')
} }
// The character to convert to hex. // The character to convert to hex.
@ -127,19 +132,19 @@ func (uuid UUID) String() string {
// First nibble. // First nibble.
nibble := c >> 4 nibble := c >> 4
if nibble <= 9 { if nibble <= 9 {
s += string(nibble + '0') s.WriteByte(nibble + '0')
} else { } else {
s += string(nibble + 'a' - 10) s.WriteByte(nibble + 'a' - 10)
} }
// Second nibble. // Second nibble.
nibble = c & 0x0f nibble = c & 0x0f
if nibble <= 9 { if nibble <= 9 {
s += string(nibble + '0') s.WriteByte(nibble + '0')
} else { } else {
s += string(nibble + 'a' - 10) s.WriteByte(nibble + 'a' - 10)
} }
} }
return s return s.String()
} }

View file

@ -1,6 +1,7 @@
package bluetooth package bluetooth
import ( import (
"strings"
"testing" "testing"
) )
@ -38,3 +39,35 @@ func TestStringUUID(t *testing.T) {
t.Errorf("expected %s but got %s", uuidString, u.String()) 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()
}
}