@@ -537,7 +537,7 @@ module Net
537
537
# ==== RFC9394: +PARTIAL+
538
538
# - Updates #search, #uid_search with the +PARTIAL+ return option which adds
539
539
# ESearchResult#partial return data.
540
- # - TODO: Updates #uid_fetch with the +partial+ modifier.
540
+ # - Updates #uid_fetch with the +partial+ modifier.
541
541
#
542
542
# == References
543
543
#
@@ -2437,14 +2437,37 @@ def fetch(...)
2437
2437
end
2438
2438
2439
2439
# :call-seq:
2440
- # uid_fetch(set, attr, changedsince: nil) -> array of FetchData
2440
+ # uid_fetch(set, attr, changedsince: nil, partial: nil ) -> array of FetchData
2441
2441
#
2442
2442
# Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2443
2443
# to retrieve data associated with a message in the mailbox.
2444
2444
#
2445
2445
# Similar to #fetch, but the +set+ parameter contains unique identifiers
2446
2446
# instead of message sequence numbers.
2447
2447
#
2448
+ # When #uid_fetch may also be given a +partial+ range, which can be used to
2449
+ # limit the number of results. <em>Requires the +PARTIAL+
2450
+ # capabability.</em> {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
2451
+ #
2452
+ # For example:
2453
+ #
2454
+ # # Without partial, the size of the results may be unknown beforehand:
2455
+ # results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS))
2456
+ # # ... maybe wait for a long time ... and allocate a lot of memory ...
2457
+ # results.size # => 0..2**32-1
2458
+ # process results # may also take a long time and use a lot of memory...
2459
+ #
2460
+ # # Using partial, the results may be paginated:
2461
+ # loop do
2462
+ # results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS),
2463
+ # partial: 1..500)
2464
+ # # fetch should return quickly and allocate little memory
2465
+ # results.size # => 0..500
2466
+ # break if results.empty?
2467
+ # next_uid_to_fetch = results.last.uid + 1
2468
+ # process results
2469
+ # end
2470
+ #
2448
2471
# >>>
2449
2472
# *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
2450
2473
# part of any +FETCH+ response caused by a +UID+ command, regardless of
@@ -3412,8 +3435,26 @@ def search_internal(cmd, ...)
3412
3435
end
3413
3436
end
3414
3437
3415
- def fetch_internal ( cmd , set , attr , mod = nil , changedsince : nil )
3438
+ def partial_range ( range )
3439
+ case range
3440
+ in /\a (?:\d +:\d +|-\d +:-\d +)\z /
3441
+ range
3442
+ in Range
3443
+ minmax = range . minmax . map { Integer _1 }
3444
+ if minmax . all? ( 1 ..2 **32 -1 ) || minmax . all? ( -2 **32 ..-1 )
3445
+ minmax . join ( ":" )
3446
+ else
3447
+ raise ArgumentError , "invalid partial-range"
3448
+ end
3449
+ end
3450
+ end
3451
+
3452
+ def fetch_internal ( cmd , set , attr , mod = nil , partial : nil , changedsince : nil )
3416
3453
set = SequenceSet [ set ]
3454
+ if partial
3455
+ mod ||= [ ]
3456
+ mod << "PARTIAL" << partial_range ( partial )
3457
+ end
3417
3458
if changedsince
3418
3459
mod ||= [ ]
3419
3460
mod << "CHANGEDSINCE" << Integer ( changedsince )
0 commit comments