-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
enhance #10 : avoid allocations on parseUUID
#12
Changes from 2 commits
446522c
4023410
0f275bc
7b52e05
4c42601
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -4,7 +4,6 @@ import ( | ||||||||||
"encoding/hex" | |||||||||||
"errors" | |||||||||||
"fmt" | |||||||||||
"strings" | |||||||||||
) | |||||||||||
|
|||||||||||
// Helper function to encode timestamp into the UUID byte array. | |||||||||||
|
@@ -31,12 +30,30 @@ func decodeTimestamp(uuidBytes []byte) uint64 { | ||||||||||
|
|||||||||||
// Helper function to parse and sanitize a UUID string. | |||||||||||
func parseUUID(uuid string) ([]byte, error) { | |||||||||||
uuid = strings.ReplaceAll(uuid, "-", "") | |||||||||||
if len(uuid) != 32 { | |||||||||||
if len(uuid) == 32 { | |||||||||||
// Fast path for UUIDs without dashes | |||||||||||
return hex.DecodeString(uuid) | |||||||||||
} else if len(uuid) == 36 { | |||||||||||
// Validate dash positions | |||||||||||
if uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-' { | |||||||||||
return nil, errors.New("invalid UUID format") | |||||||||||
} | |||||||||||
} else { | |||||||||||
return nil, errors.New("invalid UUID length") | |||||||||||
} | |||||||||||
|
|||||||||||
return hex.DecodeString(uuid) | |||||||||||
// Remove dashes while copying characters | |||||||||||
result := make([]byte, 32) | |||||||||||
j := 0 | |||||||||||
for i := 0; i < len(uuid); i++ { | |||||||||||
if uuid[i] == '-' { | |||||||||||
continue | |||||||||||
} | |||||||||||
result[j] = uuid[i] | |||||||||||
j++ | |||||||||||
} | |||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not a simple strings.ReplaceAll? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! Primary reason was to address #10 . When I attempted 'Benchmarking', the current implementation was faster and avoids memory allocations. Here are the benchmark results comparing the two:
How? This approach processes the |
|||||||||||
|
|||||||||||
return hex.DecodeString(string(result)) | |||||||||||
} | |||||||||||
|
|||||||||||
// Helper function to check if a UUID is all zeros. | |||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -561,3 +561,56 @@ func TestNewWithParams_MaxValues(t *testing.T) { | |
t.Errorf("Generated UUID with max values is invalid: %s", uuid) | ||
} | ||
} | ||
|
||
func TestFromString_InvalidInputs(t *testing.T) { | ||
tests := []string{ | ||
"123", // Too short | ||
"123e4567e89b12d3a4564266141740000000", // Too long | ||
"123e4567e89b12d3a45642661417400g", // Invalid character | ||
"123e-4567-e89b-12d3-a456-426614174000", // Misplaced dashes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure thing! Added in the latest commit. |
||
} | ||
|
||
for _, input := range tests { | ||
t.Run("Invalid UUID "+input, func(t *testing.T) { | ||
_, err := uuidv8.FromString(input) | ||
if err == nil { | ||
t.Errorf("Expected error, got nil for input: %s", input) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestFromStringOrNil_InvalidInputs(t *testing.T) { | ||
tests := []string{ | ||
"123", // Too short | ||
"123e4567e89b12d3a4564266141740000000", // Too long | ||
"123e4567e89b12d3a45642661417400g", // Invalid character | ||
"", // Empty string | ||
} | ||
|
||
for _, input := range tests { | ||
t.Run("Invalid UUID "+input, func(t *testing.T) { | ||
result := uuidv8.FromStringOrNil(input) | ||
if result != nil { | ||
t.Errorf("Expected nil for input: %s, got %v", input, result) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestIsValidUUIDv8_InvalidUUIDs(t *testing.T) { | ||
invalidUUIDs := []string{ | ||
"123", // Too short | ||
"123e4567e89b12d3a4564266141740000000", // Too long | ||
"123e4567e89b12d3a45642661417400g", // Invalid character | ||
"", // Empty string | ||
} | ||
|
||
for _, uuid := range invalidUUIDs { | ||
t.Run("Invalid UUID "+uuid, func(t *testing.T) { | ||
if uuidv8.IsValidUUIDv8(uuid) { | ||
t.Errorf("Expected UUID %s to be invalid", uuid) | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if you consider this
#12 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or this