From 090d11a9ae949639925f9ed450adec2aff693d74 Mon Sep 17 00:00:00 2001 From: nick evans Date: Tue, 21 Nov 2023 09:18:15 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Use=20frozen=20const=20when=20parsi?= =?UTF-8?q?ng=20empty=20arrays=20[=F0=9F=9A=A7=20WIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO, record benchmarks --- lib/net/imap/response_parser.rb | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/net/imap/response_parser.rb b/lib/net/imap/response_parser.rb index f120f9ba..7cd7c391 100644 --- a/lib/net/imap/response_parser.rb +++ b/lib/net/imap/response_parser.rb @@ -62,6 +62,10 @@ def parse(str) T_TEXT = :TEXT # any char except CRLF T_EOF = :EOF # end of response string + # Use to avoid allocation when we know the result is empty + EMPTY_ARRAY = [].freeze + private_constant :EMPTY_ARRAY + module ResponseConditions OK = "OK" NO = "NO" @@ -596,7 +600,7 @@ def tagged_ext_simple # "(" [tagged-ext-comp] ")" def tagged_ext_val if lpar? - _ = peek_rpar? ? [] : tagged_ext_comp + _ = peek_rpar? ? EMPTY_ARRAY : tagged_ext_comp rpar _ else @@ -1356,7 +1360,7 @@ def mailbox_data__list # ; This is the list information pointed to by the ABNF # ; item "mailbox-data", which is defined above def mailbox_list - lpar; attr = peek_rpar? ? [] : mbx_list_flags; rpar + lpar; attr = peek_rpar? ? EMPTY_ARRAY : mbx_list_flags; rpar SP!; delim = nquoted SP!; name = mailbox # TODO: mbox-list-extended @@ -1456,8 +1460,12 @@ def acl_data # obsolete-search-response = "SEARCH" *(SP nz-number) def mailbox_data__search name = label_in("SEARCH", "SORT") - data = [] - while _ = SP? && nz_number? do data << _ end + if (_ = SP? && nz_number?) + data = [_] + while _ = SP? && nz_number? do data << _ end + else + data = EMPTY_ARRAY + end if lpar? label("MODSEQ"); SP! modseq = mod_sequence_value @@ -1506,7 +1514,7 @@ def thread_members else nested = thread_nested; break end end - members.reverse.inject(nested || []) {|subthreads, number| + members.reverse.inject(nested || EMPTY_ARRAY) {|subthreads, number| [ThreadMember.new(number, subthreads)] }.first end @@ -1678,7 +1686,7 @@ def namespace_response # namespace = nil / "(" 1*namespace-descr ")" def namespace - NIL? and return [] + NIL? and return EMPTY_ARRAY lpar list = [namespace_descr] list << namespace_descr until rpar? @@ -1805,13 +1813,13 @@ def resp_text_code data = case name when "CAPABILITY" then resp_code__capability - when "PERMANENTFLAGS" then SP? ? flag_perm__list : [] + when "PERMANENTFLAGS" then SP? ? flag_perm__list : EMPTY_ARRAY when "UIDNEXT" then SP!; nz_number when "UIDVALIDITY" then SP!; nz_number when "UNSEEN" then SP!; nz_number # rev1 only when "APPENDUID" then SP!; resp_code_apnd__data # rev2, UIDPLUS when "COPYUID" then SP!; resp_code_copy__data # rev2, UIDPLUS - when "BADCHARSET" then SP? ? charset__list : [] + when "BADCHARSET" then SP? ? charset__list : EMPTY_ARRAY when "ALERT", "PARSE", "READ-ONLY", "READ-WRITE", "TRYCREATE", "UNAVAILABLE", "AUTHENTICATIONFAILED", "AUTHORIZATIONFAILED", "EXPIRED", "PRIVACYREQUIRED", "CONTACTADMIN", "NOPERM", "INUSE", @@ -1942,7 +1950,7 @@ def x_gm_label; accept(T_BSLASH) ? atom.capitalize.to_sym : astring end # See https://developers.google.com/gmail/imap/imap-extensions def x_gm_labels - lpar; return [] if rpar? + lpar; return EMPTY_ARRAY if rpar? labels = [] labels << x_gm_label labels << x_gm_label while SP?