Skip to content

Commit 54de657

Browse files
committed
✨ Add SequenceSet#ordered_at
This is the ordered entries variation of `#at`.
1 parent 608a983 commit 54de657

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

lib/net/imap/sequence_set.rb

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ class IMAP
190190
# - #find_index: Returns the given number's offset in the sorted set.
191191
#
192192
# <i>Accessing value by offset in ordered entries</i>
193+
# - #ordered_at: Returns the number at a given offset in the ordered entries.
193194
# - #find_ordered_index: Returns the index of the given number's first
194195
# occurrence in entries.
195196
#
@@ -1145,15 +1146,32 @@ def reverse_each_tuple_with_index(tuples)
11451146
# +index+ is interpreted the same as in #[], except that #at only allows a
11461147
# single integer argument.
11471148
#
1148-
# Related: #[], #slice
1149+
# Related: #[], #slice, #ordered_at
11491150
def at(index)
1151+
lookup_number_by_tuple_index(tuples, index)
1152+
end
1153+
1154+
# :call-seq: ordered_at(index) -> integer or nil
1155+
#
1156+
# Returns the number at the given +index+ in the ordered #entries, without
1157+
# modifying the set.
1158+
#
1159+
# +index+ is interpreted the same as in #at (and #[]), except that
1160+
# #ordered_at applies to the ordered #entries, not the sorted set.
1161+
#
1162+
# Related: #[], #slice, #ordered_at
1163+
def ordered_at(index)
1164+
lookup_number_by_tuple_index(each_entry_tuple, index)
1165+
end
1166+
1167+
private def lookup_number_by_tuple_index(tuples, index)
11501168
index = Integer(index.to_int)
11511169
if index.negative?
1152-
reverse_each_tuple_with_index(@tuples) do |min, max, idx_min, idx_max|
1170+
reverse_each_tuple_with_index(tuples) do |min, max, idx_min, idx_max|
11531171
idx_min <= index and return from_tuple_int(min + (index - idx_min))
11541172
end
11551173
else
1156-
each_tuple_with_index(@tuples) do |min, _, idx_min, idx_max|
1174+
each_tuple_with_index(tuples) do |min, _, idx_min, idx_max|
11571175
index <= idx_max and return from_tuple_int(min + (index - idx_min))
11581176
end
11591177
end

test/net/imap/test_sequence_set.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,38 @@ def obj.to_sequence_set; 192_168.001_255 end
225225
assert_nil SequenceSet["101:110,201:210,301:310"][-44]
226226
end
227227

228+
test "#ordered_at(non-negative index)" do
229+
assert_nil SequenceSet.empty.ordered_at(0)
230+
assert_equal 1, SequenceSet.full.ordered_at(0)
231+
assert_equal 111, SequenceSet.full.ordered_at(110)
232+
assert_equal 1, SequenceSet["1:*"].ordered_at(0)
233+
assert_equal :*, SequenceSet["*,1"].ordered_at(0)
234+
assert_equal 4, SequenceSet["6,4,8,2"].ordered_at(1)
235+
assert_equal 2, SequenceSet["6,4,8,2"].ordered_at(3)
236+
assert_equal 6, SequenceSet["9:11,4:6,1:3"].ordered_at(5)
237+
assert_nil SequenceSet["9:11,4:6,1:3"].ordered_at(9)
238+
assert_equal 105, SequenceSet["201:210,101:110,301:310"].ordered_at(14)
239+
assert_equal 310, SequenceSet["201:210,101:110,301:310"].ordered_at(29)
240+
assert_nil SequenceSet["201:210,101:110,301:310"].ordered_at(30)
241+
assert_equal :*, SequenceSet["1:10,*"].ordered_at(10)
242+
end
243+
244+
test "#ordered_at(negative index)" do
245+
assert_nil SequenceSet.empty.ordered_at(-1)
246+
assert_equal :*, SequenceSet["1:*"].ordered_at(-1)
247+
assert_equal 1, SequenceSet.full.ordered_at(-(2**32))
248+
assert_equal :*, SequenceSet["*,1"].ordered_at(0)
249+
assert_equal 8, SequenceSet["6,4,8,2"].ordered_at(-2)
250+
assert_equal 6, SequenceSet["6,4,8,2"].ordered_at(-4)
251+
assert_equal 4, SequenceSet["9:11,4:6,1:3"].ordered_at(-6)
252+
assert_equal 10, SequenceSet["9:11,4:6,1:3"].ordered_at(-8)
253+
assert_nil SequenceSet["9:11,4:6,1:3"].ordered_at(-12)
254+
assert_equal 107, SequenceSet["201:210,101:110,301:310"].ordered_at(-14)
255+
assert_equal 201, SequenceSet["201:210,101:110,301:310"].ordered_at(-30)
256+
assert_nil SequenceSet["201:210,101:110,301:310"].ordered_at(-31)
257+
assert_equal :*, SequenceSet["1:10,*"].ordered_at(10)
258+
end
259+
228260
test "#[start, length]" do
229261
assert_equal SequenceSet[10..99], SequenceSet.full[9, 90]
230262
assert_equal 90, SequenceSet.full[9, 90].count

0 commit comments

Comments
 (0)