@@ -18,21 +18,9 @@ class IMAP
18
18
#
19
19
# == Creating sequence sets
20
20
#
21
- # SequenceSet.new with no arguments creates an empty sequence set. Note
22
- # that an empty sequence set is invalid in the \IMAP grammar.
23
- #
24
- # set = Net::IMAP::SequenceSet.new
25
- # set.empty? #=> true
26
- # set.valid? #=> false
27
- # set.valid_string #!> raises DataFormatError
28
- # set << 1..10
29
- # set.empty? #=> false
30
- # set.valid? #=> true
31
- # set.valid_string #=> "1:10"
32
- #
33
21
# SequenceSet.new may receive a single optional argument: a non-zero 32 bit
34
22
# unsigned integer, a range, a <tt>sequence-set</tt> formatted string,
35
- # another sequence set , a Set (containing only numbers or <tt>*</tt>), or an
23
+ # another SequenceSet , a Set (containing only numbers or <tt>*</tt>), or an
36
24
# Array containing any of these (array inputs may be nested).
37
25
#
38
26
# set = Net::IMAP::SequenceSet.new(1)
@@ -48,30 +36,92 @@ class IMAP
48
36
# set = Net::IMAP::SequenceSet.new(1, 2, 3..7, 5, 6..10, 2048, 1024)
49
37
# set.valid_string #=> "1:10,55,1024:2048"
50
38
#
51
- # Use ::[] with one or more arguments to create a frozen SequenceSet . An
52
- # invalid ( empty) set cannot be created with ::[] .
39
+ # SequenceSet.new with no arguments creates an empty sequence set . Note
40
+ # that an empty sequence set is invalid in the \IMAP grammar .
53
41
#
42
+ # set = Net::IMAP::SequenceSet.new
43
+ # set.empty? #=> true
44
+ # set.valid? #=> false
45
+ # set.valid_string #!> raises DataFormatError
46
+ # set << 1..10
47
+ # set.empty? #=> false
48
+ # set.valid? #=> true
49
+ # set.valid_string #=> "1:10"
50
+ #
51
+ # Using SequenceSet.new with another SequenceSet input behaves the same as
52
+ # calling #dup on the other set. The input's #string will be preserved.
53
+ #
54
+ # input = Net::IMAP::SequenceSet.new("1,2,3:7,5,6:10,2048,1024")
55
+ # copy = Net::IMAP::SequenceSet.new(input)
56
+ # input.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
57
+ # copy.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
58
+ # copy2 = input.dup # same as calling new with a SequenceSet input
59
+ # copy == input #=> true, same set membership
60
+ # copy.eql? input #=> true, same string value
61
+ # copy.equal? input #=> false, different objects
62
+ #
63
+ # copy.normalize!
64
+ # copy.valid_string #=> "1:10,1024,2048"
65
+ # copy == input #=> true, same set membership
66
+ # copy.eql? input #=> false, different string value
67
+ #
68
+ # copy << 999
69
+ # copy.valid_string #=> "1:10,999,1024,2048"
70
+ # copy == input #=> false, different set membership
71
+ # copy.eql? input #=> false, different string value
72
+ #
73
+ # Use ::[] to coerce one or more arguments into a valid frozen SequenceSet.
74
+ # A valid frozen SequenceSet is returned directly, without allocating a new
75
+ # object. ::[] will not create an invalid (empty) set.
76
+ #
77
+ # Net::IMAP::SequenceSet[] #!> raises ArgumentError
78
+ # Net::IMAP::SequenceSet[nil] #!> raises DataFormatError
79
+ # Net::IMAP::SequenceSet[""] #!> raises DataFormatError
80
+ #
81
+ # # String order is preserved
54
82
# set = Net::IMAP::SequenceSet["1,2,3:7,5,6:10,2048,1024"]
55
83
# set.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
84
+ # set.frozen? #=> true
85
+ #
86
+ # # Other inputs are normalized
56
87
# set = Net::IMAP::SequenceSet[1, 2, [3..7, 5], 6..10, 2048, 1024]
57
88
# set.valid_string #=> "1:10,55,1024:2048"
89
+ # set.frozen? #=> true
90
+ #
91
+ # frozen = set
92
+ # unfrozen = set.dup
93
+ # frozen.equal? Net::IMAP::SequenceSet[frozen] #=> true
94
+ # unfrozen.equal? Net::IMAP::SequenceSet[unfrozen] #=> false
95
+ #
96
+ # Objects which respond to +to_sequence_set+ (such as SearchResult and
97
+ # ThreadMember) can be coerced to a SequenceSet with ::new, ::try_convert,
98
+ # or ::[].
99
+ #
100
+ # search = imap.uid_search(["SUBJECT", "hello", "NOT", "SEEN"])
101
+ # seqset = Net::IMAP::SequenceSet(search) - already_fetched
102
+ # fetch = imap.uid_fetch(seqset, "FAST")
58
103
#
59
104
# == Ordered and Normalized sets
60
105
#
61
106
# Sometimes the order of the set's members is significant, such as with the
62
107
# +ESORT+, <tt>CONTEXT=SORT</tt>, and +UIDPLUS+ extensions. So, when a
63
- # sequence set is created by the parser or with a single string value, that
64
- # #string representation is preserved.
108
+ # sequence set is created from a single string (such as by the parser), that
109
+ # #string representation is preserved. Assigning a string with #string= or
110
+ # #replace will also preserve that string. Use #each_entry, #entries, or
111
+ # #each_ordered_number to enumerate the entries in their #string order.
112
+ # Hash equality (using #eql?) is based on the string representation.
65
113
#
66
- # Internally, SequenceSet stores a normalized representation which sorts all
67
- # entries, de-duplicates numbers, and coalesces adjacent or overlapping
68
- # ranges. Most methods use this normalized representation to achieve
69
- # <tt>O(lg n)</tt> porformance. Use #entries or #each_entry to enumerate
70
- # the set in its original order.
114
+ # Internally, SequenceSet uses a normalized uint32 set representation which
115
+ # sorts and de-duplicates all numbers and coalesces adjacent or overlapping
116
+ # entries. Many methods use this sorted set representation for <tt>O(lg
117
+ # n)</tt> searches. Use #each_element, #elements, #each_range, #ranges,
118
+ # #each_number, or #numbers to enumerate the set in sorted order. Basic
119
+ # object equality (using #==) is based on set membership, without regard to
120
+ # #entry order or #string normalization.
71
121
#
72
- # Most modification methods convert #string to its normalized form. To
73
- # preserve #string order while modifying a set, use #append, #string=, or
74
- # #replace .
122
+ # Most modification methods reset #string to its # normalized form, so that
123
+ # #entries and #elements are identical. Use #append to preserve #entries
124
+ # order while modifying a set .
75
125
#
76
126
# == Using <tt>*</tt>
77
127
#
@@ -178,8 +228,7 @@ class IMAP
178
228
#
179
229
# <i>Set membership:</i>
180
230
# - #include? (aliased as #member?):
181
- # Returns whether a given element (nz-number, range, or <tt>*</tt>) is
182
- # contained by the set.
231
+ # Returns whether a given element is contained by the set.
183
232
# - #include_star?: Returns whether the set contains <tt>*</tt>.
184
233
#
185
234
# <i>Minimum and maximum value elements:</i>
@@ -337,6 +386,8 @@ class << self
337
386
# An empty SequenceSet is invalid and will raise a DataFormatError.
338
387
#
339
388
# Use ::new to create a mutable or empty SequenceSet.
389
+ #
390
+ # Related: ::new, ::try_convert
340
391
def []( first , *rest )
341
392
if rest . empty?
342
393
if first . is_a? ( SequenceSet ) && first . frozen? && first . valid?
@@ -358,6 +409,8 @@ def [](first, *rest)
358
409
#
359
410
# If +obj.to_sequence_set+ doesn't return a SequenceSet, an exception is
360
411
# raised.
412
+ #
413
+ # Related: ::new, ::[]
361
414
def try_convert ( obj )
362
415
return obj if obj . is_a? ( SequenceSet )
363
416
return nil unless obj . respond_to? ( :to_sequence_set )
@@ -376,10 +429,69 @@ def full; FULL end
376
429
end
377
430
378
431
# Create a new SequenceSet object from +input+, which may be another
379
- # SequenceSet, an IMAP formatted +sequence-set+ string, a number, a
380
- # range, <tt>:*</tt>, a Set of numbers, or an Array of these.
381
- #
382
- # Use ::[] to create a frozen (non-empty) SequenceSet.
432
+ # SequenceSet, an IMAP formatted +sequence-set+ string, a non-zero 32 bit
433
+ # unsigned integer, a range, <tt>:*</tt>, a Set of numbers or <tt>*</tt>,
434
+ # an object that responds to +to_sequence_set+ (such as SearchResult) or
435
+ # an Array of these (array inputs may be nested).
436
+ #
437
+ # set = Net::IMAP::SequenceSet.new(1)
438
+ # set.valid_string #=> "1"
439
+ # set = Net::IMAP::SequenceSet.new(1..100)
440
+ # set.valid_string #=> "1:100"
441
+ # set = Net::IMAP::SequenceSet.new(1...100)
442
+ # set.valid_string #=> "1:99"
443
+ # set = Net::IMAP::SequenceSet.new([1, 2, 5..])
444
+ # set.valid_string #=> "1:2,5:*"
445
+ # set = Net::IMAP::SequenceSet.new("1,2,3:7,5,6:10,2048,1024")
446
+ # set.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
447
+ # set = Net::IMAP::SequenceSet.new(1, 2, 3..7, 5, 6..10, 2048, 1024)
448
+ # set.valid_string #=> "1:10,55,1024:2048"
449
+ #
450
+ # With no arguments (or +nil+) creates an empty sequence set. Note that
451
+ # an empty sequence set is invalid in the \IMAP grammar.
452
+ #
453
+ # set = Net::IMAP::SequenceSet.new
454
+ # set.empty? #=> true
455
+ # set.valid? #=> false
456
+ # set.valid_string #!> raises DataFormatError
457
+ # set << 1..10
458
+ # set.empty? #=> false
459
+ # set.valid? #=> true
460
+ # set.valid_string #=> "1:10"
461
+ #
462
+ # When +input+ is a SequenceSet, ::new behaves the same as calling #dup on
463
+ # that other set. The input's #string will be preserved.
464
+ #
465
+ # input = Net::IMAP::SequenceSet.new("1,2,3:7,5,6:10,2048,1024")
466
+ # copy = Net::IMAP::SequenceSet.new(input)
467
+ # input.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
468
+ # copy.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
469
+ # copy2 = input.dup # same as calling new with a SequenceSet input
470
+ # copy == input #=> true, same set membership
471
+ # copy.eql? input #=> true, same string value
472
+ # copy.equal? input #=> false, different objects
473
+ #
474
+ # copy.normalize!
475
+ # copy.valid_string #=> "1:10,1024,2048"
476
+ # copy == input #=> true, same set membership
477
+ # copy.eql? input #=> false, different string value
478
+ #
479
+ # copy << 999
480
+ # copy.valid_string #=> "1:10,999,1024,2048"
481
+ # copy == input #=> false, different set membership
482
+ # copy.eql? input #=> false, different string value
483
+ #
484
+ # === Alternative set creation methods
485
+ #
486
+ # * ::[] returns a frozen validated (non-empty) SequenceSet, without
487
+ # allocating a new object when the input is already a valid frozen
488
+ # SequenceSet.
489
+ # * ::try_convert calls +to_sequence_set+ on inputs that support it and
490
+ # returns +nil+ for inputs that don't.
491
+ # * ::empty and ::full both return frozen singleton sets which can be
492
+ # combined with set operations (#|, #&, #^, #-, etc) to make new sets.
493
+ #
494
+ # See SequenceSet@Creating+sequence+sets.
383
495
def initialize ( input = nil ) input ? replace ( input ) : clear end
384
496
385
497
# Removes all elements and returns self.
@@ -525,7 +637,7 @@ def ===(other)
525
637
# Returns whether +other+ is contained within the set. +other+ may be any
526
638
# object that would be accepted by ::new.
527
639
#
528
- # Related: #===, #include?, #include_star?
640
+ # Related: #===, #include?, #include_star?, #intersect?
529
641
def cover? ( other ) input_to_tuples ( other ) . none? { !include_tuple? ( _1 ) } end
530
642
531
643
# Returns +true+ when a given number or range is in +self+, and +false+
@@ -551,7 +663,7 @@ def cover?(other) input_to_tuples(other).none? { !include_tuple?(_1) } end
551
663
# set.include?(200..) #=> true
552
664
# set.include?(100..) #=> false
553
665
#
554
- # Related: #include_star?, #cover?, #===
666
+ # Related: #include_star?, #cover?, #===, #intersect?
555
667
def include? ( element )
556
668
tuple = input_to_tuple element rescue nil
557
669
!!include_tuple? ( tuple ) if tuple
@@ -568,7 +680,7 @@ def include_star?; @tuples.last&.last == STAR_INT end
568
680
# Net::IMAP::SequenceSet["5:10"].intersect? "7,9,11" #=> true
569
681
# Net::IMAP::SequenceSet["5:10"].intersect? "11:33" #=> false
570
682
#
571
- # Related: #intersection, #disjoint?
683
+ # Related: #intersection, #disjoint?, #cover?, #include?
572
684
def intersect? ( other )
573
685
valid? && input_to_tuples ( other ) . any? { intersect_tuple? _1 }
574
686
end
@@ -685,7 +797,7 @@ def |(other) remain_frozen dup.merge other end
685
797
# ==== Set identities
686
798
#
687
799
# <tt>lhs - rhs</tt> is equivalent to:
688
- # * <tt>~r - ~l </tt>
800
+ # * <tt>~rhs - ~lhs </tt>
689
801
# * <tt>lhs & ~rhs</tt>
690
802
# * <tt>~(~lhs | rhs)</tt>
691
803
# * <tt>lhs & (lhs ^ rhs)</tt>
@@ -1504,7 +1616,15 @@ def inspect
1504
1616
end
1505
1617
end
1506
1618
1507
- # Returns self
1619
+ ##
1620
+ # :method: to_sequence_set
1621
+ # :call-seq: to_sequence_set -> self
1622
+ #
1623
+ # Returns +self+
1624
+ #
1625
+ # Related: ::try_convert
1626
+
1627
+ # :nodoc: (work around rdoc bug)
1508
1628
alias to_sequence_set itself
1509
1629
1510
1630
# Unstable API: currently for internal use only (Net::IMAP#validate_data)
0 commit comments