net-imap 0.4.20 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of net-imap might be problematic. Click here for more details.

@@ -14,13 +14,6 @@ module Net
14
14
  # receive a SequenceSet as an argument, for example IMAP#search, IMAP#fetch,
15
15
  # and IMAP#store.
16
16
  #
17
- # == EXPERIMENTAL API
18
- #
19
- # SequenceSet is currently experimental. Only two methods, ::[] and
20
- # #valid_string, are considered stable. Although the API isn't expected to
21
- # change much, any other methods may be removed or changed without
22
- # deprecation.
23
- #
24
17
  # == Creating sequence sets
25
18
  #
26
19
  # SequenceSet.new with no arguments creates an empty sequence set. Note
@@ -37,7 +30,8 @@ module Net
37
30
  #
38
31
  # SequenceSet.new may receive a single optional argument: a non-zero 32 bit
39
32
  # unsigned integer, a range, a <tt>sequence-set</tt> formatted string,
40
- # another sequence set, or an enumerable containing any of these.
33
+ # another sequence set, a Set (containing only numbers or <tt>*</tt>), or an
34
+ # Array containing any of these (array inputs may be nested).
41
35
  #
42
36
  # set = Net::IMAP::SequenceSet.new(1)
43
37
  # set.valid_string #=> "1"
@@ -60,20 +54,18 @@ module Net
60
54
  # set = Net::IMAP::SequenceSet[1, 2, [3..7, 5], 6..10, 2048, 1024]
61
55
  # set.valid_string #=> "1:10,55,1024:2048"
62
56
  #
63
- # == Ordered and Normalized sets
64
- #
65
- # Sometimes the order of the set's members is significant, such as with the
66
- # +ESORT+, <tt>CONTEXT=SORT</tt>, and +UIDPLUS+ extensions. So, when a
67
- # sequence set is created by the parser or with a single string value, that
68
- # #string representation is preserved.
57
+ # == Normalized form
69
58
  #
70
- # Internally, SequenceSet stores a normalized representation which sorts all
71
- # entries, de-duplicates numbers, and coalesces adjacent or overlapping
72
- # ranges. Most methods use this normalized representation to achieve
73
- # <tt>O(lg n)</tt> porformance. Use #entries or #each_entry to enumerate
74
- # the set in its original order.
59
+ # When a sequence set is created with a single String value, that #string
60
+ # representation is preserved. SequenceSet's internal representation
61
+ # implicitly sorts all entries, de-duplicates numbers, and coalesces
62
+ # adjacent or overlapping ranges. Most enumeration methods and offset-based
63
+ # methods use this normalized representation. Most modification methods
64
+ # will convert #string to its normalized form.
75
65
  #
76
- # Most modification methods convert #string to its normalized form. To
66
+ # In some cases the order of the string representation is significant, such
67
+ # as the +ESORT+, <tt>CONTEXT=SORT</tt>, and +UIDPLUS+ extensions. Use
68
+ # #entries or #each_entry to enumerate the set in its original order. To
77
69
  # preserve #string order while modifying a set, use #append, #string=, or
78
70
  # #replace.
79
71
  #
@@ -166,7 +158,7 @@ module Net
166
158
  # - #===:
167
159
  # Returns whether a given object is fully contained within +self+, or
168
160
  # +nil+ if the object cannot be converted to a compatible type.
169
- # - #cover?:
161
+ # - #cover? (aliased as #===):
170
162
  # Returns whether a given object is fully contained within +self+.
171
163
  # - #intersect? (aliased as #overlap?):
172
164
  # Returns whether +self+ and a given object have any common elements.
@@ -178,7 +170,7 @@ module Net
178
170
  #
179
171
  # <i>Set membership:</i>
180
172
  # - #include? (aliased as #member?):
181
- # Returns whether a given element (nz-number, range, or <tt>*</tt>) is
173
+ # Returns whether a given object (nz-number, range, or <tt>*</tt>) is
182
174
  # contained by the set.
183
175
  # - #include_star?: Returns whether the set contains <tt>*</tt>.
184
176
  #
@@ -187,41 +179,30 @@ module Net
187
179
  # - #max: Returns the maximum number in the set.
188
180
  # - #minmax: Returns the minimum and maximum numbers in the set.
189
181
  #
190
- # <i>Accessing value by offset in sorted set:</i>
182
+ # <i>Accessing value by offset:</i>
191
183
  # - #[] (aliased as #slice): Returns the number or consecutive subset at a
192
- # given offset or range of offsets in the sorted set.
193
- # - #at: Returns the number at a given offset in the sorted set.
194
- # - #find_index: Returns the given number's offset in the sorted set.
195
- #
196
- # <i>Accessing value by offset in ordered entries</i>
197
- # - #ordered_at: Returns the number at a given offset in the ordered entries.
198
- # - #find_ordered_index: Returns the index of the given number's first
199
- # occurrence in entries.
184
+ # given offset or range of offsets.
185
+ # - #at: Returns the number at a given offset.
186
+ # - #find_index: Returns the given number's offset in the set
200
187
  #
201
188
  # <i>Set cardinality:</i>
202
189
  # - #count (aliased as #size): Returns the count of numbers in the set.
203
- # Duplicated numbers are not counted.
204
190
  # - #empty?: Returns whether the set has no members. \IMAP syntax does not
205
191
  # allow empty sequence sets.
206
192
  # - #valid?: Returns whether the set has any members.
207
193
  # - #full?: Returns whether the set contains every possible value, including
208
194
  # <tt>*</tt>.
209
195
  #
210
- # <i>Denormalized properties:</i>
211
- # - #has_duplicates?: Returns whether the ordered entries repeat any
212
- # numbers.
213
- # - #count_duplicates: Returns the count of repeated numbers in the ordered
214
- # entries.
215
- # - #count_with_duplicates: Returns the count of numbers in the ordered
216
- # entries, including any repeated numbers.
217
- #
218
196
  # === Methods for Iterating
219
197
  #
220
- # <i>Normalized (sorted and coalesced):</i>
221
198
  # - #each_element: Yields each number and range in the set, sorted and
222
199
  # coalesced, and returns +self+.
223
200
  # - #elements (aliased as #to_a): Returns an Array of every number and range
224
201
  # in the set, sorted and coalesced.
202
+ # - #each_entry: Yields each number and range in the set, unsorted and
203
+ # without deduplicating numbers or coalescing ranges, and returns +self+.
204
+ # - #entries: Returns an Array of every number and range in the set,
205
+ # unsorted and without deduplicating numbers or coalescing ranges.
225
206
  # - #each_range:
226
207
  # Yields each element in the set as a Range and returns +self+.
227
208
  # - #ranges: Returns an Array of every element in the set, converting
@@ -231,25 +212,17 @@ module Net
231
212
  # ranges into all of their contained numbers.
232
213
  # - #to_set: Returns a Set containing all of the #numbers in the set.
233
214
  #
234
- # <i>Order preserving:</i>
235
- # - #each_entry: Yields each number and range in the set, unsorted and
236
- # without deduplicating numbers or coalescing ranges, and returns +self+.
237
- # - #entries: Returns an Array of every number and range in the set,
238
- # unsorted and without deduplicating numbers or coalescing ranges.
239
- # - #each_ordered_number: Yields each number in the ordered entries and
240
- # returns +self+.
241
- #
242
215
  # === Methods for \Set Operations
243
216
  # These methods do not modify +self+.
244
217
  #
245
218
  # - #| (aliased as #union and #+): Returns a new set combining all members
246
- # from +self+ with all members from the other set.
219
+ # from +self+ with all members from the other object.
247
220
  # - #& (aliased as #intersection): Returns a new set containing all members
248
- # common to +self+ and the other set.
221
+ # common to +self+ and the other object.
249
222
  # - #- (aliased as #difference): Returns a copy of +self+ with all members
250
- # in the other set removed.
223
+ # in the other object removed.
251
224
  # - #^ (aliased as #xor): Returns a new set containing all members from
252
- # +self+ and the other set except those common to both.
225
+ # +self+ and the other object except those common to both.
253
226
  # - #~ (aliased as #complement): Returns a new set containing all members
254
227
  # that are not in +self+
255
228
  # - #limit: Returns a copy of +self+ which has replaced <tt>*</tt> with a
@@ -258,39 +231,28 @@ module Net
258
231
  # === Methods for Assigning
259
232
  # These methods add or replace elements in +self+.
260
233
  #
261
- # <i>Normalized (sorted and coalesced):</i>
262
- #
263
- # These methods always update #string to be fully sorted and coalesced.
264
- #
265
- # - #add (aliased as #<<): Adds a given element to the set; returns +self+.
266
- # - #add?: If the given element is not fully included the set, adds it and
234
+ # - #add (aliased as #<<): Adds a given object to the set; returns +self+.
235
+ # - #add?: If the given object is not an element in the set, adds it and
267
236
  # returns +self+; otherwise, returns +nil+.
268
- # - #merge: Adds all members of the given sets into this set; returns +self+.
269
- # - #complement!: Replaces the contents of the set with its own #complement.
270
- #
271
- # <i>Order preserving:</i>
272
- #
273
- # These methods _may_ cause #string to not be sorted or coalesced.
274
- #
275
- # - #append: Adds the given entry to the set, appending it to the existing
237
+ # - #merge: Merges multiple elements into the set; returns +self+.
238
+ # - #append: Adds a given object to the set, appending it to the existing
276
239
  # string, and returns +self+.
277
240
  # - #string=: Assigns a new #string value and replaces #elements to match.
278
241
  # - #replace: Replaces the contents of the set with the contents
279
242
  # of a given object.
243
+ # - #complement!: Replaces the contents of the set with its own #complement.
280
244
  #
281
245
  # === Methods for Deleting
282
- # These methods remove elements from +self+, and update #string to be fully
283
- # sorted and coalesced.
246
+ # These methods remove elements from +self+.
284
247
  #
285
248
  # - #clear: Removes all elements in the set; returns +self+.
286
- # - #delete: Removes a given element from the set; returns +self+.
287
- # - #delete?: If the given element is included in the set, removes it and
249
+ # - #delete: Removes a given object from the set; returns +self+.
250
+ # - #delete?: If the given object is an element in the set, removes it and
288
251
  # returns it; otherwise, returns +nil+.
289
252
  # - #delete_at: Removes the number at a given offset.
290
253
  # - #slice!: Removes the number or consecutive numbers at a given offset or
291
254
  # range of offsets.
292
- # - #subtract: Removes all members of the given sets from this set; returns
293
- # +self+.
255
+ # - #subtract: Removes each given object from the set; returns +self+.
294
256
  # - #limit!: Replaces <tt>*</tt> with a given maximum value and removes all
295
257
  # members over that maximum; returns +self+.
296
258
  #
@@ -321,18 +283,14 @@ module Net
321
283
  private_constant :STAR_INT, :STARS
322
284
 
323
285
  COERCIBLE = ->{ _1.respond_to? :to_sequence_set }
324
- ENUMABLE = ->{ _1.respond_to?(:each) && _1.respond_to?(:empty?) }
325
- private_constant :COERCIBLE, :ENUMABLE
286
+ private_constant :COERCIBLE
326
287
 
327
288
  class << self
328
289
 
329
290
  # :call-seq:
330
- # SequenceSet[*inputs] -> valid frozen sequence set
331
- #
332
- # Returns a frozen SequenceSet, constructed from +inputs+.
291
+ # SequenceSet[*values] -> valid frozen sequence set
333
292
  #
334
- # When only a single valid frozen SequenceSet is given, that same set is
335
- # returned.
293
+ # Returns a frozen SequenceSet, constructed from +values+.
336
294
  #
337
295
  # An empty SequenceSet is invalid and will raise a DataFormatError.
338
296
  #
@@ -360,7 +318,7 @@ module Net
360
318
  # raised.
361
319
  def try_convert(obj)
362
320
  return obj if obj.is_a?(SequenceSet)
363
- return nil unless obj.respond_to?(:to_sequence_set)
321
+ return nil unless respond_to?(:to_sequence_set)
364
322
  obj = obj.to_sequence_set
365
323
  return obj if obj.is_a?(SequenceSet)
366
324
  raise DataFormatError, "invalid object returned from to_sequence_set"
@@ -698,7 +656,7 @@ module Net
698
656
  alias complement :~
699
657
 
700
658
  # :call-seq:
701
- # add(element) -> self
659
+ # add(object) -> self
702
660
  # self << other -> self
703
661
  #
704
662
  # Adds a range or number to the set and returns +self+.
@@ -706,8 +664,8 @@ module Net
706
664
  # #string will be regenerated. Use #merge to add many elements at once.
707
665
  #
708
666
  # Related: #add?, #merge, #union
709
- def add(element)
710
- tuple_add input_to_tuple element
667
+ def add(object)
668
+ tuple_add input_to_tuple object
711
669
  normalize!
712
670
  end
713
671
  alias << add
@@ -716,29 +674,28 @@ module Net
716
674
  #
717
675
  # Unlike #add, #merge, or #union, the new value is appended to #string.
718
676
  # This may result in a #string which has duplicates or is out-of-order.
719
- def append(entry)
677
+ def append(object)
720
678
  modifying!
721
- tuple = input_to_tuple entry
679
+ tuple = input_to_tuple object
722
680
  entry = tuple_to_str tuple
723
- string unless empty? # write @string before tuple_add
724
681
  tuple_add tuple
725
- @string = -(@string ? "#{@string},#{entry}" : entry)
682
+ @string = -(string ? "#{@string},#{entry}" : entry)
726
683
  self
727
684
  end
728
685
 
729
- # :call-seq: add?(element) -> self or nil
686
+ # :call-seq: add?(object) -> self or nil
730
687
  #
731
688
  # Adds a range or number to the set and returns +self+. Returns +nil+
732
- # when the element is already included in the set.
689
+ # when the object is already included in the set.
733
690
  #
734
691
  # #string will be regenerated. Use #merge to add many elements at once.
735
692
  #
736
693
  # Related: #add, #merge, #union, #include?
737
- def add?(element)
738
- add element unless include? element
694
+ def add?(object)
695
+ add object unless include? object
739
696
  end
740
697
 
741
- # :call-seq: delete(element) -> self
698
+ # :call-seq: delete(object) -> self
742
699
  #
743
700
  # Deletes the given range or number from the set and returns +self+.
744
701
  #
@@ -746,8 +703,8 @@ module Net
746
703
  # many elements at once.
747
704
  #
748
705
  # Related: #delete?, #delete_at, #subtract, #difference
749
- def delete(element)
750
- tuple_subtract input_to_tuple element
706
+ def delete(object)
707
+ tuple_subtract input_to_tuple object
751
708
  normalize!
752
709
  end
753
710
 
@@ -783,8 +740,8 @@ module Net
783
740
  # #string will be regenerated after deletion.
784
741
  #
785
742
  # Related: #delete, #delete_at, #subtract, #difference, #disjoint?
786
- def delete?(element)
787
- tuple = input_to_tuple element
743
+ def delete?(object)
744
+ tuple = input_to_tuple object
788
745
  if tuple.first == tuple.last
789
746
  return unless include_tuple? tuple
790
747
  tuple_subtract tuple
@@ -828,31 +785,33 @@ module Net
828
785
  deleted
829
786
  end
830
787
 
831
- # Merges all of the elements that appear in any of the +sets+ into the
788
+ # Merges all of the elements that appear in any of the +inputs+ into the
832
789
  # set, and returns +self+.
833
790
  #
834
- # The +sets+ may be any objects that would be accepted by ::new: non-zero
835
- # 32 bit unsigned integers, ranges, <tt>sequence-set</tt> formatted
836
- # strings, other sequence sets, or enumerables containing any of these.
791
+ # The +inputs+ may be any objects that would be accepted by ::new:
792
+ # non-zero 32 bit unsigned integers, ranges, <tt>sequence-set</tt>
793
+ # formatted strings, other sequence sets, or enumerables containing any of
794
+ # these.
837
795
  #
838
- # #string will be regenerated after all sets have been merged.
796
+ # #string will be regenerated after all inputs have been merged.
839
797
  #
840
798
  # Related: #add, #add?, #union
841
- def merge(*sets)
842
- tuples_add input_to_tuples sets
799
+ def merge(*inputs)
800
+ tuples_add input_to_tuples inputs
843
801
  normalize!
844
802
  end
845
803
 
846
- # Removes all of the elements that appear in any of the given +sets+ from
847
- # the set, and returns +self+.
804
+ # Removes all of the elements that appear in any of the given +objects+
805
+ # from the set, and returns +self+.
848
806
  #
849
- # The +sets+ may be any objects that would be accepted by ::new: non-zero
850
- # 32 bit unsigned integers, ranges, <tt>sequence-set</tt> formatted
851
- # strings, other sequence sets, or enumerables containing any of these.
807
+ # The +objects+ may be any objects that would be accepted by ::new:
808
+ # non-zero 32 bit unsigned integers, ranges, <tt>sequence-set</tt>
809
+ # formatted strings, other sequence sets, or enumerables containing any of
810
+ # these.
852
811
  #
853
812
  # Related: #difference
854
- def subtract(*sets)
855
- tuples_subtract input_to_tuples sets
813
+ def subtract(*objects)
814
+ tuples_subtract input_to_tuples objects
856
815
  normalize!
857
816
  end
858
817
 
@@ -876,8 +835,8 @@ module Net
876
835
  # <tt>*</tt> translates to an endless range. Use #limit to translate both
877
836
  # cases to a maximum value.
878
837
  #
879
- # The returned elements will be sorted and coalesced, even when the input
880
- # #string is not. <tt>*</tt> will sort last. See #normalize.
838
+ # If the original input was unordered or contains overlapping ranges, the
839
+ # returned ranges will be ordered and coalesced.
881
840
  #
882
841
  # Net::IMAP::SequenceSet["2,5:9,6,*,12:11"].elements
883
842
  # #=> [2, 5..9, 11..12, :*]
@@ -895,7 +854,7 @@ module Net
895
854
  # translates to <tt>:*..</tt>. Use #limit to set <tt>*</tt> to a maximum
896
855
  # value.
897
856
  #
898
- # The returned ranges will be sorted and coalesced, even when the input
857
+ # The returned ranges will be ordered and coalesced, even when the input
899
858
  # #string is not. <tt>*</tt> will sort last. See #normalize.
900
859
  #
901
860
  # Net::IMAP::SequenceSet["2,5:9,6,*,12:11"].ranges
@@ -944,7 +903,9 @@ module Net
944
903
  # Related: #entries, #each_element
945
904
  def each_entry(&block) # :yields: integer or range or :*
946
905
  return to_enum(__method__) unless block_given?
947
- each_entry_tuple do yield tuple_to_entry _1 end
906
+ return each_element(&block) unless @string
907
+ @string.split(",").each do yield tuple_to_entry str_to_tuple _1 end
908
+ self
948
909
  end
949
910
 
950
911
  # Yields each number or range (or <tt>:*</tt>) in #elements to the block
@@ -962,16 +923,6 @@ module Net
962
923
 
963
924
  private
964
925
 
965
- def each_entry_tuple(&block)
966
- return to_enum(__method__) unless block_given?
967
- if @string
968
- @string.split(",") do block.call str_to_tuple _1 end
969
- else
970
- @tuples.each(&block)
971
- end
972
- self
973
- end
974
-
975
926
  def tuple_to_entry((min, max))
976
927
  if min == STAR_INT then :*
977
928
  elsif max == STAR_INT then min..
@@ -1003,34 +954,17 @@ module Net
1003
954
  # Returns an enumerator when called without a block (even if the set
1004
955
  # contains <tt>*</tt>).
1005
956
  #
1006
- # Related: #numbers, #each_ordered_number
957
+ # Related: #numbers
1007
958
  def each_number(&block) # :yields: integer
1008
959
  return to_enum(__method__) unless block_given?
1009
960
  raise RangeError, '%s contains "*"' % [self.class] if include_star?
1010
- @tuples.each do each_number_in_tuple _1, _2, &block end
1011
- self
1012
- end
1013
-
1014
- # Yields each number in #entries to the block and returns self.
1015
- # If the set contains a <tt>*</tt>, RangeError will be raised.
1016
- #
1017
- # Returns an enumerator when called without a block (even if the set
1018
- # contains <tt>*</tt>).
1019
- #
1020
- # Related: #entries, #each_number
1021
- def each_ordered_number(&block)
1022
- return to_enum(__method__) unless block_given?
1023
- raise RangeError, '%s contains "*"' % [self.class] if include_star?
1024
- each_entry_tuple do each_number_in_tuple _1, _2, &block end
1025
- end
1026
-
1027
- private def each_number_in_tuple(min, max, &block)
1028
- if min == STAR_INT then yield :*
1029
- elsif min == max then yield min
1030
- elsif max != STAR_INT then (min..max).each(&block)
1031
- else
1032
- raise RangeError, "#{SequenceSet} cannot enumerate range with '*'"
961
+ each_element do |elem|
962
+ case elem
963
+ when Range then elem.each(&block)
964
+ when Integer then block.(elem)
965
+ end
1033
966
  end
967
+ self
1034
968
  end
1035
969
 
1036
970
  # Returns a Set with all of the #numbers in the sequence set.
@@ -1044,10 +978,8 @@ module Net
1044
978
 
1045
979
  # Returns the count of #numbers in the set.
1046
980
  #
1047
- # <tt>*</tt> will be counted as <tt>2**32 - 1</tt> (the maximum 32-bit
1048
- # unsigned integer value).
1049
- #
1050
- # Related: #count_with_duplicates
981
+ # If <tt>*</tt> and <tt>2**32 - 1</tt> (the maximum 32-bit unsigned
982
+ # integer value) are both in the set, they will only be counted once.
1051
983
  def count
1052
984
  @tuples.sum(@tuples.count) { _2 - _1 } +
1053
985
  (include_star? && include?(UINT32_MAX) ? -1 : 0)
@@ -1055,87 +987,33 @@ module Net
1055
987
 
1056
988
  alias size count
1057
989
 
1058
- # Returns the count of numbers in the ordered #entries, including any
1059
- # repeated numbers.
1060
- #
1061
- # <tt>*</tt> will be counted as <tt>2**32 - 1</tt> (the maximum 32-bit
1062
- # unsigned integer value).
1063
- #
1064
- # When #string is normalized, this behaves the same as #count.
1065
- #
1066
- # Related: #entries, #count_duplicates, #has_duplicates?
1067
- def count_with_duplicates
1068
- return count unless @string
1069
- each_entry_tuple.sum {|min, max|
1070
- max - min + ((max == STAR_INT && min != STAR_INT) ? 0 : 1)
1071
- }
1072
- end
1073
-
1074
- # Returns the count of repeated numbers in the ordered #entries, the
1075
- # difference between #count_with_duplicates and #count.
1076
- #
1077
- # When #string is normalized, this is zero.
1078
- #
1079
- # Related: #entries, #count_with_duplicates, #has_duplicates?
1080
- def count_duplicates
1081
- return 0 unless @string
1082
- count_with_duplicates - count
1083
- end
1084
-
1085
- # :call-seq: has_duplicates? -> true | false
1086
- #
1087
- # Returns whether or not the ordered #entries repeat any numbers.
1088
- #
1089
- # Always returns +false+ when #string is normalized.
1090
- #
1091
- # Related: #entries, #count_with_duplicates, #count_duplicates?
1092
- def has_duplicates?
1093
- return false unless @string
1094
- count_with_duplicates != count
1095
- end
1096
-
1097
- # Returns the (sorted and deduplicated) index of +number+ in the set, or
1098
- # +nil+ if +number+ isn't in the set.
990
+ # Returns the index of +number+ in the set, or +nil+ if +number+ isn't in
991
+ # the set.
1099
992
  #
1100
- # Related: #[], #at, #find_ordered_index
993
+ # Related: #[]
1101
994
  def find_index(number)
1102
995
  number = to_tuple_int number
1103
- each_tuple_with_index(@tuples) do |min, max, idx_min|
996
+ each_tuple_with_index do |min, max, idx_min|
1104
997
  number < min and return nil
1105
998
  number <= max and return from_tuple_int(idx_min + (number - min))
1106
999
  end
1107
1000
  nil
1108
1001
  end
1109
1002
 
1110
- # Returns the first index of +number+ in the ordered #entries, or
1111
- # +nil+ if +number+ isn't in the set.
1112
- #
1113
- # Related: #find_index
1114
- def find_ordered_index(number)
1115
- number = to_tuple_int number
1116
- each_tuple_with_index(each_entry_tuple) do |min, max, idx_min|
1117
- if min <= number && number <= max
1118
- return from_tuple_int(idx_min + (number - min))
1119
- end
1120
- end
1121
- nil
1122
- end
1123
-
1124
1003
  private
1125
1004
 
1126
- def each_tuple_with_index(tuples)
1005
+ def each_tuple_with_index
1127
1006
  idx_min = 0
1128
- tuples.each do |min, max|
1129
- idx_max = idx_min + (max - min)
1130
- yield min, max, idx_min, idx_max
1007
+ @tuples.each do |min, max|
1008
+ yield min, max, idx_min, (idx_max = idx_min + (max - min))
1131
1009
  idx_min = idx_max + 1
1132
1010
  end
1133
1011
  idx_min
1134
1012
  end
1135
1013
 
1136
- def reverse_each_tuple_with_index(tuples)
1014
+ def reverse_each_tuple_with_index
1137
1015
  idx_max = -1
1138
- tuples.reverse_each do |min, max|
1016
+ @tuples.reverse_each do |min, max|
1139
1017
  yield min, max, (idx_min = idx_max - (max - min)), idx_max
1140
1018
  idx_max = idx_min - 1
1141
1019
  end
@@ -1146,38 +1024,18 @@ module Net
1146
1024
 
1147
1025
  # :call-seq: at(index) -> integer or nil
1148
1026
  #
1149
- # Returns the number at the given +index+ in the sorted set, without
1150
- # modifying the set.
1151
- #
1152
- # +index+ is interpreted the same as in #[], except that #at only allows a
1153
- # single integer argument.
1027
+ # Returns a number from +self+, without modifying the set. Behaves the
1028
+ # same as #[], except that #at only allows a single integer argument.
1154
1029
  #
1155
- # Related: #[], #slice, #ordered_at
1030
+ # Related: #[], #slice
1156
1031
  def at(index)
1157
- lookup_number_by_tuple_index(tuples, index)
1158
- end
1159
-
1160
- # :call-seq: ordered_at(index) -> integer or nil
1161
- #
1162
- # Returns the number at the given +index+ in the ordered #entries, without
1163
- # modifying the set.
1164
- #
1165
- # +index+ is interpreted the same as in #at (and #[]), except that
1166
- # #ordered_at applies to the ordered #entries, not the sorted set.
1167
- #
1168
- # Related: #[], #slice, #ordered_at
1169
- def ordered_at(index)
1170
- lookup_number_by_tuple_index(each_entry_tuple, index)
1171
- end
1172
-
1173
- private def lookup_number_by_tuple_index(tuples, index)
1174
1032
  index = Integer(index.to_int)
1175
1033
  if index.negative?
1176
- reverse_each_tuple_with_index(tuples) do |min, max, idx_min, idx_max|
1034
+ reverse_each_tuple_with_index do |min, max, idx_min, idx_max|
1177
1035
  idx_min <= index and return from_tuple_int(min + (index - idx_min))
1178
1036
  end
1179
1037
  else
1180
- each_tuple_with_index(tuples) do |min, _, idx_min, idx_max|
1038
+ each_tuple_with_index do |min, _, idx_min, idx_max|
1181
1039
  index <= idx_max and return from_tuple_int(min + (index - idx_min))
1182
1040
  end
1183
1041
  end
@@ -1192,18 +1050,17 @@ module Net
1192
1050
  # seqset[range] -> sequence set or nil
1193
1051
  # slice(range) -> sequence set or nil
1194
1052
  #
1195
- # Returns a number or a subset from the _sorted_ set, without modifying
1196
- # the set.
1053
+ # Returns a number or a subset from +self+, without modifying the set.
1197
1054
  #
1198
1055
  # When an Integer argument +index+ is given, the number at offset +index+
1199
- # in the sorted set is returned:
1056
+ # is returned:
1200
1057
  #
1201
1058
  # set = Net::IMAP::SequenceSet["10:15,20:23,26"]
1202
1059
  # set[0] #=> 10
1203
1060
  # set[5] #=> 15
1204
1061
  # set[10] #=> 26
1205
1062
  #
1206
- # If +index+ is negative, it counts relative to the end of the sorted set:
1063
+ # If +index+ is negative, it counts relative to the end of +self+:
1207
1064
  # set = Net::IMAP::SequenceSet["10:15,20:23,26"]
1208
1065
  # set[-1] #=> 26
1209
1066
  # set[-3] #=> 22
@@ -1215,14 +1072,13 @@ module Net
1215
1072
  # set[11] #=> nil
1216
1073
  # set[-12] #=> nil
1217
1074
  #
1218
- # The result is based on the sorted and de-duplicated set, not on the
1219
- # ordered #entries in #string.
1075
+ # The result is based on the normalized set—sorted and de-duplicatednot
1076
+ # on the assigned value of #string.
1220
1077
  #
1221
1078
  # set = Net::IMAP::SequenceSet["12,20:23,11:16,21"]
1222
1079
  # set[0] #=> 11
1223
1080
  # set[-1] #=> 23
1224
1081
  #
1225
- # Related: #at
1226
1082
  def [](index, length = nil)
1227
1083
  if length then slice_length(index, length)
1228
1084
  elsif index.is_a?(Range) then slice_range(index)
@@ -1392,29 +1248,30 @@ module Net
1392
1248
  super
1393
1249
  end
1394
1250
 
1395
- def input_to_tuple(entry)
1396
- entry = input_try_convert entry
1397
- case entry
1398
- when *STARS, Integer then [int = to_tuple_int(entry), int]
1399
- when Range then range_to_tuple(entry)
1400
- when String then str_to_tuple(entry)
1251
+ def input_to_tuple(obj)
1252
+ obj = input_try_convert obj
1253
+ case obj
1254
+ when *STARS, Integer then [int = to_tuple_int(obj), int]
1255
+ when Range then range_to_tuple(obj)
1256
+ when String then str_to_tuple(obj)
1401
1257
  else
1402
- raise DataFormatError, "expected number or range, got %p" % [entry]
1258
+ raise DataFormatError, "expected number or range, got %p" % [obj]
1403
1259
  end
1404
1260
  end
1405
1261
 
1406
- def input_to_tuples(set)
1407
- set = input_try_convert set
1408
- case set
1409
- when *STARS, Integer, Range then [input_to_tuple(set)]
1410
- when String then str_to_tuples set
1411
- when SequenceSet then set.tuples
1412
- when ENUMABLE then set.flat_map { input_to_tuples _1 }
1262
+ def input_to_tuples(obj)
1263
+ obj = input_try_convert obj
1264
+ case obj
1265
+ when *STARS, Integer, Range then [input_to_tuple(obj)]
1266
+ when String then str_to_tuples obj
1267
+ when SequenceSet then obj.tuples
1268
+ when Set then obj.map { [to_tuple_int(_1)] * 2 }
1269
+ when Array then obj.flat_map { input_to_tuples _1 }
1413
1270
  when nil then []
1414
1271
  else
1415
1272
  raise DataFormatError,
1416
1273
  "expected nz-number, range, string, or enumerable; " \
1417
- "got %p" % [set]
1274
+ "got %p" % [obj]
1418
1275
  end
1419
1276
  end
1420
1277
 
@@ -1422,8 +1279,7 @@ module Net
1422
1279
  # String, Set, Array, or... any type of object.
1423
1280
  def input_try_convert(input)
1424
1281
  SequenceSet.try_convert(input) ||
1425
- # Integer.try_convert(input) || # ruby 3.1+
1426
- input.respond_to?(:to_int) && Integer(input.to_int) ||
1282
+ Integer.try_convert(input) ||
1427
1283
  String.try_convert(input) ||
1428
1284
  input
1429
1285
  end
@@ -1478,8 +1334,8 @@ module Net
1478
1334
  modifying!
1479
1335
  min, max = tuple
1480
1336
  lower, lower_idx = tuple_gte_with_index(min - 1)
1481
- if lower.nil? then tuples << [min, max]
1482
- elsif (max + 1) < lower.first then tuples.insert(lower_idx, [min, max])
1337
+ if lower.nil? then tuples << tuple
1338
+ elsif (max + 1) < lower.first then tuples.insert(lower_idx, tuple)
1483
1339
  else tuple_coalesce(lower, lower_idx, min, max)
1484
1340
  end
1485
1341
  end
@@ -1553,12 +1409,11 @@ module Net
1553
1409
  end
1554
1410
 
1555
1411
  def nz_number(num)
1556
- case num
1557
- when Integer, /\A[1-9]\d*\z/ then num = Integer(num)
1558
- else raise DataFormatError, "%p is not a valid nz-number" % [num]
1559
- end
1560
- NumValidator.ensure_nz_number(num)
1561
- num
1412
+ String === num && !/\A[1-9]\d*\z/.match?(num) and
1413
+ raise DataFormatError, "%p is not a valid nz-number" % [num]
1414
+ NumValidator.ensure_nz_number Integer num
1415
+ rescue TypeError # To catch errors from Integer()
1416
+ raise DataFormatError, $!.message
1562
1417
  end
1563
1418
 
1564
1419
  # intentionally defined after the class implementation