diff --git a/regexes.go b/regexes.go index 871cf7df7..fdf925aa9 100644 --- a/regexes.go +++ b/regexes.go @@ -18,7 +18,7 @@ const ( rgbaRegexString = "^rgba\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$" hslRegexString = "^hsl\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*\\)$" hslaRegexString = "^hsla\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$" - emailRegexString = "^(?:(?:(?:(?:[a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(?:\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|(?:(?:\\x22)(?:(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(?:\\x20|\\x09)+)?(?:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(\\x20|\\x09)+)?(?:\\x22))))@(?:(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$" + emailRegexString = `^(?:"(?:[^"]|\\")*"|[\p{L}\p{N}\p{M}._%+-]+)@[\p{L}\p{N}\p{M}.-]+\.[\p{L}\p{M}]{2,}$` e164RegexString = "^\\+[1-9]?[0-9]{7,14}$" base32RegexString = "^(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}=|[A-Z2-7]{8})$" base64RegexString = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$" diff --git a/validator_test.go b/validator_test.go index 5eadb2502..2eb7293ed 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8762,6 +8762,91 @@ func TestEmail(t *testing.T) { AssertError(t, errs, "", "", "", "", "email") } +func BenchmarkEmailValidation(b *testing.B) { + validate := New() + + // Valid email test cases + validEmails := []string{ + "test@mail.com", + "Dörte@Sörensen.example.com", + "θσερ@εχαμπλε.ψομ", + "юзер@екзампл.ком", + "उपयोगकर्ता@उदाहरण.कॉम", + "用户@例子.广告", + `"test test"@email.com`, + } + + // Invalid email test cases + invalidEmails := []string{ + "mail@domain_with_underscores.org", + "", + "test@email", + "test@email.", + "@email.com", + `"@email.com`, + } + + // Define sub-benchmarks + b.Run("Valid_Emails", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, email := range validEmails { + _ = validate.Var(email, "email") + } + } + }) + + b.Run("Invalid_Emails", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, email := range invalidEmails { + _ = validate.Var(email, "email") + } + } + }) + + b.Run("Mixed_Types", func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = validate.Var(true, "email") // Test with boolean + _ = validate.Var("test@mail.com", "email") // Test with string + } + }) + + // Benchmark individual cases + for _, email := range validEmails { + b.Run("Valid_"+email, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = validate.Var(email, "email") + } + }) + } + + for _, email := range invalidEmails { + name := email + if name == "" { + name = "Empty" + } + b.Run("Invalid_"+name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = validate.Var(email, "email") + } + }) + } + + // Benchmark single instance vs new validator + b.Run("Single_Validator", func(b *testing.B) { + v := New() + for i := 0; i < b.N; i++ { + _ = v.Var("test@mail.com", "email") + } + }) + + b.Run("New_Validator_Each_Time", func(b *testing.B) { + for i := 0; i < b.N; i++ { + v := New() + _ = v.Var("test@mail.com", "email") + } + }) +} + func TestHexColor(t *testing.T) { validate := New() @@ -12080,7 +12165,7 @@ func TestExcludedIf(t *testing.T) { test11 := struct { Field1 bool - Field2 *string `validate:"excluded_if=Field1 false"` + Field2 *string `validate:"excluded_if=Field1 false"` }{ Field1: false, Field2: nil,