Skip to content

Commit 74d7e0c

Browse files
authored
perf: Improve error handling performance by removing expensive formatting. Replace fmt.Errorf calls with lightweight error literals to improve parsing performance, following the same approach as Google's UUID library. (#247)
1 parent cd2dded commit 74d7e0c

File tree

3 files changed

+26
-13
lines changed

3 files changed

+26
-13
lines changed

codec.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121

2222
package uuid
2323

24-
import "fmt"
25-
2624
// FromBytes returns a UUID generated from the raw byte slice input.
2725
// It will return an error if the slice isn't 16 bytes long.
2826
func FromBytes(input []byte) (UUID, error) {
@@ -73,22 +71,22 @@ func parseBytes(b []byte, u *UUID) error {
7371
case 36: // canonical
7472
case 34, 38:
7573
if b[0] != '{' || b[len(b)-1] != '}' {
76-
return fmt.Errorf("%w %q", ErrIncorrectFormatInString, b)
74+
return ErrInvalidBraces
7775
}
7876
b = b[1 : len(b)-1]
7977
case 41, 45:
8078
if string(b[:9]) != "urn:uuid:" {
81-
return fmt.Errorf("%w %q", ErrIncorrectFormatInString, b[:9])
79+
return ErrInvalidURNPrefix
8280
}
8381
b = b[9:]
8482
default:
85-
return fmt.Errorf("%w %d in string %q", ErrIncorrectLength, len(b), b)
83+
return ErrIncorrectLength
8684
}
8785

8886
// canonical (36 chars with dashes at fixed positions)
8987
if len(b) == 36 {
9088
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
91-
return fmt.Errorf("%w %q", ErrIncorrectFormatInString, b)
89+
return ErrInvalidDashes
9290
}
9391
for i, x := range [16]byte{
9492
0, 2, 4, 6,
@@ -198,7 +196,7 @@ func (u UUID) MarshalBinary() ([]byte, error) {
198196
// It will return an error if the slice isn't 16 bytes long.
199197
func (u *UUID) UnmarshalBinary(data []byte) error {
200198
if len(data) != Size {
201-
return fmt.Errorf("%w, got %d bytes", ErrIncorrectByteLength, len(data))
199+
return ErrIncorrectByteLength
202200
}
203201
copy(u[:], data)
204202

error.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package uuid
22

3+
import "fmt"
4+
35
// Error is a custom error type for UUID-related errors
46
type Error string
57

@@ -34,6 +36,19 @@ const (
3436
ErrInvalidVersion = Error("uuid:")
3537
)
3638

39+
// Wrapped errors for backward compatibility. These wrap ErrIncorrectFormatInString
40+
// so code like errors.Is(err, uuid.ErrIncorrectFormatInString) continues to work.
41+
var (
42+
// ErrInvalidBraces is returned when braced format has invalid braces.
43+
ErrInvalidBraces = fmt.Errorf("%w: invalid braces", ErrIncorrectFormatInString)
44+
45+
// ErrInvalidURNPrefix is returned when URN format has invalid prefix.
46+
ErrInvalidURNPrefix = fmt.Errorf("%w: invalid URN prefix", ErrIncorrectFormatInString)
47+
48+
// ErrInvalidDashes is returned when canonical format has dashes not in expected positions.
49+
ErrInvalidDashes = fmt.Errorf("%w: dashes were not in expected positions", ErrIncorrectFormatInString)
50+
)
51+
3752
// Error returns the string representation of the UUID error.
3853
func (e Error) Error() string {
3954
return string(e)

error_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,25 @@ func TestParseErrors(t *testing.T) {
5151
uuidStr string
5252
expected string
5353
}{
54-
{ // 34 chars - With brackets
54+
{ // 34 chars - With braces
5555
function: "parse",
5656
uuidStr: "..................................",
57-
expected: "uuid: incorrect UUID format in string \"..................................\"",
57+
expected: "uuid: incorrect UUID format in string: invalid braces",
5858
},
5959
{ // 41 chars - urn:uuid:
6060
function: "parse",
6161
uuidStr: "123456789................................",
62-
expected: "uuid: incorrect UUID format in string \"123456789\"",
62+
expected: "uuid: incorrect UUID format in string: invalid URN prefix",
6363
},
6464
{ // other
6565
function: "parse",
6666
uuidStr: "....",
67-
expected: "uuid: incorrect UUID length 4 in string \"....\"",
67+
expected: "uuid: incorrect UUID length",
6868
},
6969
{ // 36 chars - canonical, but not correct format
7070
function: "parse",
7171
uuidStr: "....................................",
72-
expected: "uuid: incorrect UUID format in string \"....................................\"",
72+
expected: "uuid: incorrect UUID format in string: dashes were not in expected positions",
7373
},
7474
{ // 36 chars - canonical, invalid data
7575
function: "parse",
@@ -118,7 +118,7 @@ func TestParseErrors(t *testing.T) {
118118
func TestUnmarshalBinaryError(t *testing.T) {
119119
id := UUID{}
120120
b := make([]byte, 33)
121-
expectedErr := "uuid: UUID must be exactly 16 bytes long, got 33 bytes"
121+
expectedErr := "uuid: UUID must be exactly 16 bytes long"
122122
err := id.UnmarshalBinary([]byte(b))
123123
if err == nil {
124124
t.Error("expected an error")

0 commit comments

Comments
 (0)