Skip to content

Commit 8d06a25

Browse files
committed
⚡️ Simplify and speed up mailbox-list parsing
Note that this fixes `MBX_LIST_FLAGS` and `#mbx_list_flags`, which were previously unused, and uses them too. This gives a significant performance boost: Warming up -------------------------------------- list_with_various_flag_capitalizations 38.976k i/s - 39.270k times in 1.007548s (25.66μs/i) rfc3501_7.2.2_LIST_response_example 50.042k i/s - 52.294k times in 1.044997s (19.98μs/i) utf8_in_list_mailbox 41.722k i/s - 44.550k times in 1.067774s (23.97μs/i) xlist_inbox 43.242k i/s - 46.387k times in 1.072725s (23.13μs/i) Calculating ------------------------------------- v0.4.5-8-g4611404d 0.4.5 list_with_various_flag_capitalizations 39.943k 35.777k i/s - 116.927k times in 2.927367s 3.268215s rfc3501_7.2.2_LIST_response_example 51.684k 45.809k i/s - 150.126k times in 2.904669s 3.277229s utf8_in_list_mailbox 42.525k 36.422k i/s - 125.166k times in 2.943368s 3.436526s xlist_inbox 43.099k 39.834k i/s - 129.726k times in 3.009982s 3.256683s Comparison: list_with_various_flag_capitalizations v0.4.5-8-g4611404d: 39942.7 i/s 0.4.5: 35777.0 i/s - 1.12x slower rfc3501_7.2.2_LIST_response_example v0.4.5-8-g4611404d: 51684.4 i/s 0.4.5: 45808.8 i/s - 1.13x slower utf8_in_list_mailbox v0.4.5-8-g4611404d: 42524.8 i/s 0.4.5: 36422.3 i/s - 1.17x slower xlist_inbox v0.4.5-8-g4611404d: 43098.6 i/s 0.4.5: 39833.8 i/s - 1.08x slower
1 parent d3facc2 commit 8d06a25

File tree

1 file changed

+23
-39
lines changed

1 file changed

+23
-39
lines changed

lib/net/imap/response_parser.rb

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ module RFC3629
198198
# ; revisions of this specification.
199199
# flag-keyword = "$MDNSent" / "$Forwarded" / "$Junk" /
200200
# "$NotJunk" / "$Phishing" / atom
201+
#
201202
# flag-perm = flag / "\*"
202203
#
203204
# Not checking for max one mbx-list-sflag in the parser.
@@ -220,19 +221,15 @@ module RFC3629
220221
MBX_FLAG = FLAG_EXTENSION
221222

222223
# flag-list = "(" [flag *(SP flag)] ")"
223-
#
224-
# part of resp-text-code:
225-
# >>>
226-
# "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")"
227-
#
228-
# parens from mailbox-list are included in the regexp:
229-
# >>>
230-
# mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
231-
# *(SP mbx-list-oflag) /
232-
# mbx-list-oflag *(SP mbx-list-oflag)
233-
FLAG_LIST = /\G\((#{FLAG }(?:#{SP}#{FLAG })*|)\)/ni
234-
FLAG_PERM_LIST = /\G\((#{FLAG_PERM}(?:#{SP}#{FLAG_PERM})*|)\)/ni
235-
MBX_LIST_FLAGS = /\G\((#{MBX_FLAG }(?:#{SP}#{MBX_FLAG })*|)\)/ni
224+
# resp-text-code =/ "PERMANENTFLAGS" SP
225+
# "(" [flag-perm *(SP flag-perm)] ")"
226+
# mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
227+
# *(SP mbx-list-oflag) /
228+
# mbx-list-oflag *(SP mbx-list-oflag)
229+
# (Not checking for max one mbx-list-sflag in the parser.)
230+
FLAG_LIST = /\G\((#{FLAG }(?:#{SP}#{FLAG })*|)\)/ni
231+
FLAG_PERM_LIST = /\G\((#{FLAG_PERM}(?:#{SP}#{FLAG_PERM})*|)\)/ni
232+
MBX_LIST_FLAGS = /\G (#{MBX_FLAG }(?:#{SP}#{MBX_FLAG })*) /nix
236233

237234
# RFC3501:
238235
# QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
@@ -1350,18 +1347,17 @@ def mailbox_data__list
13501347
alias mailbox_data__lsub mailbox_data__list
13511348
alias mailbox_data__xlist mailbox_data__list
13521349

1350+
# mailbox-list = "(" [mbx-list-flags] ")" SP
1351+
# (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
1352+
# [SP mbox-list-extended]
1353+
# ; This is the list information pointed to by the ABNF
1354+
# ; item "mailbox-data", which is defined above
13531355
def mailbox_list
1354-
attr = flag_list
1355-
match(T_SPACE)
1356-
token = match(T_QUOTED, T_NIL)
1357-
if token.symbol == T_NIL
1358-
delim = nil
1359-
else
1360-
delim = token.value
1361-
end
1362-
match(T_SPACE)
1363-
name = astring
1364-
return MailboxList.new(attr, delim, name)
1356+
lpar; attr = peek_rpar? ? [] : mbx_list_flags; rpar
1357+
SP!; delim = nquoted
1358+
SP!; name = mailbox
1359+
# TODO: mbox-list-extended
1360+
MailboxList.new(attr, delim, name)
13651361
end
13661362

13671363
def getquota_response
@@ -1941,22 +1937,10 @@ def flag_perm__list
19411937
.map! { _1.start_with?("\\") ? _1[1..].capitalize.to_sym : _1 }
19421938
end
19431939

1944-
# Not checking for max one mbx-list-sflag in the parser.
1945-
# >>>
1946-
# mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
1947-
# *(SP mbx-list-oflag) /
1948-
# mbx-list-oflag *(SP mbx-list-oflag)
1949-
# mbx-list-oflag = "\Noinferiors" / child-mbox-flag /
1950-
# "\Subscribed" / "\Remote" / flag-extension
1951-
# ; Other flags; multiple from this list are
1952-
# ; possible per LIST response, but each flag
1953-
# ; can only appear once per LIST response
1954-
# mbx-list-sflag = "\NonExistent" / "\Noselect" / "\Marked" /
1955-
# "\Unmarked"
1956-
# ; Selectability flags; only one per LIST response
1957-
def parens__mbx_list_flags
1940+
# See Patterns::MBX_LIST_FLAGS
1941+
def mbx_list_flags
19581942
match_re(Patterns::MBX_LIST_FLAGS, "mbx-list-flags")[1]
1959-
.split(nil).map! { _1.capitalize.to_sym }
1943+
.split(nil).map! { _1[1..].capitalize.to_sym }
19601944
end
19611945

19621946
# See https://developers.google.com/gmail/imap/imap-extensions

0 commit comments

Comments
 (0)