summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2025-07-12 19:31:31 +0900
committergit <svn-admin@ruby-lang.org>2025-07-12 10:32:48 +0000
commitcf7b871a94f2d44eb35676a3dbf9278a73a612c1 (patch)
tree0f2197c630e56da95c4187706c4728dd1e71e587
parent22b81b5bf56d7c5053008697d9e6b2a9c4eb79f4 (diff)
[ruby/uri] Improve performance of `URI::MailTo::EMAIL_REGEXP`
Fix the performance regression at #172 for valid emails. ``` yml prelude: | require 'uri/mailto' n = 1000 re = URI::MailTo::EMAIL_REGEXP benchmark: n.t..t.: re.match?("n.t..t.@docomo.ne.jp") example: re.match?("example@example.info") ``` | |released| 788274b| c5974f0| this| |:--------|-------:|-------:|-------:|-------:| |n.t..t. | 3.795M| 4.864M| 4.993M| 8.739M| | | -| 1.28x| 1.32x| 2.30x| |example | 3.911M| 3.740M| 2.838M| 3.880M| | | 1.38x| 1.32x| -| 1.37x| https://github.com/ruby/uri/commit/7363a134ac
-rw-r--r--lib/uri/mailto.rb6
-rw-r--r--test/uri/test_mailto.rb16
2 files changed, 21 insertions, 1 deletions
diff --git a/lib/uri/mailto.rb b/lib/uri/mailto.rb
index bd63aa0334..f747b79ec7 100644
--- a/lib/uri/mailto.rb
+++ b/lib/uri/mailto.rb
@@ -52,7 +52,11 @@ module URI
HEADER_REGEXP = /\A(?<hfield>(?:%\h\h|[!$'-.0-;@-Z_a-z~])*=(?:%\h\h|[!$'-.0-;@-Z_a-z~])*)(?:&\g<hfield>)*\z/
# practical regexp for email address
# https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
- EMAIL_REGEXP = /\A(?!\.)(?!.*\.{2})[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+(?<!\.)@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/
+ EMAIL_REGEXP = %r[\A#{
+ atext = %q[(?:[a-zA-Z0-9!\#$%&'*+\/=?^_`{|}~-]+)]
+ }(?:\.#{atext})*@#{
+ label = %q[(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)]
+ }(?:\.#{label})*\z]
# :startdoc:
#
diff --git a/test/uri/test_mailto.rb b/test/uri/test_mailto.rb
index 36e28df2e7..66f3edd05f 100644
--- a/test/uri/test_mailto.rb
+++ b/test/uri/test_mailto.rb
@@ -210,6 +210,22 @@ class URI::TestMailTo < Test::Unit::TestCase
end
end
+ def test_email_regexp
+ re = URI::MailTo::EMAIL_REGEXP
+
+ rate = 1000
+ longlabel = '.' + 'invalid'.ljust(63, 'd')
+ endlabel = ''
+ pre = ->(n) {'a@invalid' + longlabel*(n*rate) + endlabel}
+ assert_linear_performance(1..10, pre: pre) do |to|
+ re =~ to or flunk
+ end
+ endlabel = '.' + 'email'.rjust(64, 'd')
+ assert_linear_performance(1..10, pre: pre) do |to|
+ re =~ to and flunk
+ end
+ end
+
def test_to_s
u = URI::MailTo.build([nil, 'subject=Ruby'])