Skip to content

Commit 6a2e69a

Browse files
committed
⚡ Make response-data case statement faster
Several versions were tried: `Hash[name].call`, `case name when regexp`, `case name.to_sym`, etc, but benchmarks clearly showed `case string.upcase when "str"` as fastest. This change also documents which RFC covers which response types.
1 parent a054a09 commit 6a2e69a

File tree

1 file changed

+29
-39
lines changed

1 file changed

+29
-39
lines changed

lib/net/imap/response_parser.rb

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ def unescape_quoted(quoted)
284284

285285
def_char_matchers :SP, " ", :T_SPACE
286286
def_char_matchers :PLUS, "+", :T_PLUS
287+
def_char_matchers :STAR, "*", :T_STAR
287288

288289
def_char_matchers :lpar, "(", :T_LPAR
289290
def_char_matchers :rpar, ")", :T_RPAR
@@ -440,46 +441,35 @@ def continue_req
440441
end
441442

442443
def response_data
443-
match(T_STAR)
444-
match(T_SPACE)
445-
token = lookahead
446-
if token.symbol == T_NUMBER
447-
return numeric_response
448-
elsif token.symbol == T_ATOM
449-
case token.value
450-
when /\A(?:OK|NO|BAD|BYE|PREAUTH)\z/ni
451-
return response_cond
452-
when /\A(?:FLAGS)\z/ni
453-
return flags_response
454-
when /\A(?:ID)\z/ni
455-
return id_response
456-
when /\A(?:LIST|LSUB|XLIST)\z/ni
457-
return list_response
458-
when /\A(?:NAMESPACE)\z/ni
459-
return namespace_response
460-
when /\A(?:QUOTA)\z/ni
461-
return getquota_response
462-
when /\A(?:QUOTAROOT)\z/ni
463-
return getquotaroot_response
464-
when /\A(?:ACL)\z/ni
465-
return getacl_response
466-
when /\A(?:SEARCH|SORT)\z/ni
467-
return search_response
468-
when /\A(?:THREAD)\z/ni
469-
return thread_response
470-
when /\A(?:STATUS)\z/ni
471-
return status_response
472-
when /\A(?:CAPABILITY)\z/ni
473-
return capability_data__untagged
474-
when /\A(?:NOOP)\z/ni
475-
return ignored_response
476-
when /\A(?:ENABLED)\z/ni
477-
return enable_data
478-
else
479-
return unparsed_response
444+
STAR!; SP!
445+
token = lookahead!(T_NUMBER, T_ATOM)
446+
case token.symbol
447+
when T_NUMBER then numeric_response
448+
when T_ATOM
449+
case token.value.upcase
450+
when "OK" then response_cond # RFC3501, RFC9051
451+
when "BAD" then response_cond # RFC3501, RFC9051
452+
when "NO" then response_cond # RFC3501, RFC9051
453+
when "PREAUTH" then response_cond # RFC3501, RFC9051
454+
when "BYE" then response_cond # RFC3501, RFC9051
455+
when "FLAGS" then flags_response # RFC3501, RFC9051
456+
when "ID" then id_response # RFC2971
457+
when "LIST" then list_response # RFC3501, RFC9051
458+
when "LSUB" then list_response # RFC3501 (obsolete)
459+
when "XLIST" then list_response # deprecated
460+
when "NAMESPACE" then namespace_response # RFC2342, RFC9051
461+
when "QUOTA" then getquota_response # RFC2087, RFC9208
462+
when "QUOTAROOT" then getquotaroot_response # RFC2087, RFC9208
463+
when "ACL" then getacl_response # RFC4314
464+
when "SEARCH" then search_response # RFC3501 (obsolete)
465+
when "SORT" then search_response # RFC5256, RFC7162
466+
when "THREAD" then thread_response # RFC5256
467+
when "STATUS" then status_response # RFC3501, RFC9051
468+
when "CAPABILITY" then capability_data__untagged # RFC3501, RFC9051
469+
when "ENABLED" then enable_data # RFC5161, RFC9051
470+
when "NOOP" then ignored_response
471+
else unparsed_response
480472
end
481-
else
482-
parse_error("unexpected token %s", token.symbol)
483473
end
484474
end
485475

0 commit comments

Comments
 (0)