Skip to content
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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/hex"
"errors"
"fmt"
"strings"
)

// Helper function to encode timestamp into the UUID byte array.
Expand All @@ -29,14 +28,32 @@ func decodeTimestamp(uuidBytes []byte) uint64 {
uint64(uuidBytes[3])<<16 | uint64(uuidBytes[4])<<8 | uint64(uuidBytes[5])
}

// Helper function to parse and sanitize a UUID string.
// Helper function to parse and sanitize a UUID string.
func parseUUID(uuid string) ([]byte, error) {
uuid = strings.ReplaceAll(uuid, "-", "")
if len(uuid) != 32 {
switch len(uuid) {
case 32:
// Fast path for UUIDs without dashes
return hex.DecodeString(uuid)
case 36:
// Validate dash positions
if uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-' {
return nil, errors.New("invalid UUID format")
}

// Remove dashes while copying characters
result := make([]byte, 32)
j := 0
for i := 0; i < len(uuid); i++ {
if uuid[i] != '-' {
result[j] = uuid[i]
j++
}
}
return hex.DecodeString(string(result))
default:
return nil, errors.New("invalid UUID length")
}

return hex.DecodeString(uuid)
}

// Helper function to check if a UUID is all zeros.
Expand Down
72 changes: 72 additions & 0 deletions uuidv8_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,3 +720,75 @@ func TestUUIDv8_Scan_EdgeCases(t *testing.T) {
})
}
}

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
"123e4567-e89b-12d3-a456-426614174000-", // Extra dash at the end
"--123e4567-e89b-12d3-a456-426614174000", // Extra dash at the start
"123e4567-e89b-12d3-a456-42-6614174000", // Randomly placed dash
"------------------------------------", // 36 dashes
"9a3d4049-0e2c-8080-0102-030405060000", // Valid UUID with dashes
}

for _, input := range tests {
t.Run("Testing UUID: "+input, func(t *testing.T) {
_, err := uuidv8.FromString(input)
// The last case is valid; others should fail
if input == "9a3d4049-0e2c-8080-0102-030405060000" {
if err != nil {
t.Errorf("Expected valid UUID but got error for input: %s", input)
}
} else {
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
"123e4567-e89b-12d3-a456-426614174000-", // Extra dash at the end
"--123e4567-e89b-12d3-a456-426614174000", // Extra dash at the start
"123e4567-e89b-12d3-a456-42-6614174000", // Randomly placed dash
}

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
"123e4567-e89b-12d3-a456-426614174000-", // Extra dash at the end
"--123e4567-e89b-12d3-a456-426614174000", // Extra dash at the start
"123e4567-e89b-12d3-a456-42-6614174000", // Randomly placed dash

}

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)
}
})
}
}
Loading