Skip to content

Commit cfb93b9

Browse files
authored
🔀 Merge pull request #397 from ruby/sequence_set-ordered_at
✨ Add `SequenceSet#ordered_at`
2 parents 257ede0 + 54de657 commit cfb93b9

File tree

2 files changed

+90
-11
lines changed

2 files changed

+90
-11
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: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,21 @@ def obj.to_sequence_set; 192_168.001_255 end
167167
assert_raise DataFormatError do SequenceSet.try_convert(obj) end
168168
end
169169

170+
test "#at(non-negative index)" do
171+
assert_nil SequenceSet.empty.at(0)
172+
assert_equal 1, SequenceSet[1..].at(0)
173+
assert_equal 1, SequenceSet.full.at(0)
174+
assert_equal 111, SequenceSet.full.at(110)
175+
assert_equal 4, SequenceSet[2,4,6,8].at(1)
176+
assert_equal 8, SequenceSet[2,4,6,8].at(3)
177+
assert_equal 6, SequenceSet[4..6].at(2)
178+
assert_nil SequenceSet[4..6].at(3)
179+
assert_equal 205, SequenceSet["101:110,201:210,301:310"].at(14)
180+
assert_equal 310, SequenceSet["101:110,201:210,301:310"].at(29)
181+
assert_nil SequenceSet["101:110,201:210,301:310"].at(44)
182+
assert_equal :*, SequenceSet["1:10,*"].at(10)
183+
end
184+
170185
test "#[non-negative index]" do
171186
assert_nil SequenceSet.empty[0]
172187
assert_equal 1, SequenceSet[1..][0]
@@ -182,18 +197,64 @@ def obj.to_sequence_set; 192_168.001_255 end
182197
assert_equal :*, SequenceSet["1:10,*"][10]
183198
end
184199

200+
test "#at(negative index)" do
201+
assert_nil SequenceSet.empty.at(-1)
202+
assert_equal :*, SequenceSet[1..].at(-1)
203+
assert_equal 1, SequenceSet.full.at(-(2**32))
204+
assert_equal 111, SequenceSet[1..111].at(-1)
205+
assert_equal 6, SequenceSet[2,4,6,8].at(-2)
206+
assert_equal 2, SequenceSet[2,4,6,8].at(-4)
207+
assert_equal 4, SequenceSet[4..6].at(-3)
208+
assert_nil SequenceSet[4..6].at(-4)
209+
assert_equal 207, SequenceSet["101:110,201:210,301:310"].at(-14)
210+
assert_equal 102, SequenceSet["101:110,201:210,301:310"].at(-29)
211+
assert_nil SequenceSet["101:110,201:210,301:310"].at(-44)
212+
end
213+
185214
test "#[negative index]" do
186-
assert_nil SequenceSet.empty[0]
215+
assert_nil SequenceSet.empty[-1]
187216
assert_equal :*, SequenceSet[1..][-1]
188217
assert_equal 1, SequenceSet.full[-(2**32)]
189218
assert_equal 111, SequenceSet[1..111][-1]
190-
assert_equal 4, SequenceSet[2,4,6,8][1]
191-
assert_equal 8, SequenceSet[2,4,6,8][3]
192-
assert_equal 6, SequenceSet[4..6][2]
193-
assert_nil SequenceSet[4..6][3]
194-
assert_equal 205, SequenceSet["101:110,201:210,301:310"][14]
195-
assert_equal 310, SequenceSet["101:110,201:210,301:310"][29]
196-
assert_nil SequenceSet["101:110,201:210,301:310"][44]
219+
assert_equal 6, SequenceSet[2,4,6,8][-2]
220+
assert_equal 2, SequenceSet[2,4,6,8][-4]
221+
assert_equal 4, SequenceSet[4..6][-3]
222+
assert_nil SequenceSet[4..6][-4]
223+
assert_equal 207, SequenceSet["101:110,201:210,301:310"][-14]
224+
assert_equal 102, SequenceSet["101:110,201:210,301:310"][-29]
225+
assert_nil SequenceSet["101:110,201:210,301:310"][-44]
226+
end
227+
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)
197258
end
198259

199260
test "#[start, length]" do

0 commit comments

Comments
 (0)