Skip to content

✨ Add SequenceSet#ordered_at #397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions lib/net/imap/sequence_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class IMAP
# - #find_index: Returns the given number's offset in the sorted set.
#
# <i>Accessing value by offset in ordered entries</i>
# - #ordered_at: Returns the number at a given offset in the ordered entries.
# - #find_ordered_index: Returns the index of the given number's first
# occurrence in entries.
#
Expand Down Expand Up @@ -1145,15 +1146,32 @@ def reverse_each_tuple_with_index(tuples)
# +index+ is interpreted the same as in #[], except that #at only allows a
# single integer argument.
#
# Related: #[], #slice
# Related: #[], #slice, #ordered_at
def at(index)
lookup_number_by_tuple_index(tuples, index)
end

# :call-seq: ordered_at(index) -> integer or nil
#
# Returns the number at the given +index+ in the ordered #entries, without
# modifying the set.
#
# +index+ is interpreted the same as in #at (and #[]), except that
# #ordered_at applies to the ordered #entries, not the sorted set.
#
# Related: #[], #slice, #ordered_at
def ordered_at(index)
lookup_number_by_tuple_index(each_entry_tuple, index)
end

private def lookup_number_by_tuple_index(tuples, index)
index = Integer(index.to_int)
if index.negative?
reverse_each_tuple_with_index(@tuples) do |min, max, idx_min, idx_max|
reverse_each_tuple_with_index(tuples) do |min, max, idx_min, idx_max|
idx_min <= index and return from_tuple_int(min + (index - idx_min))
end
else
each_tuple_with_index(@tuples) do |min, _, idx_min, idx_max|
each_tuple_with_index(tuples) do |min, _, idx_min, idx_max|
index <= idx_max and return from_tuple_int(min + (index - idx_min))
end
end
Expand Down
77 changes: 69 additions & 8 deletions test/net/imap/test_sequence_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,21 @@ def obj.to_sequence_set; 192_168.001_255 end
assert_raise DataFormatError do SequenceSet.try_convert(obj) end
end

test "#at(non-negative index)" do
assert_nil SequenceSet.empty.at(0)
assert_equal 1, SequenceSet[1..].at(0)
assert_equal 1, SequenceSet.full.at(0)
assert_equal 111, SequenceSet.full.at(110)
assert_equal 4, SequenceSet[2,4,6,8].at(1)
assert_equal 8, SequenceSet[2,4,6,8].at(3)
assert_equal 6, SequenceSet[4..6].at(2)
assert_nil SequenceSet[4..6].at(3)
assert_equal 205, SequenceSet["101:110,201:210,301:310"].at(14)
assert_equal 310, SequenceSet["101:110,201:210,301:310"].at(29)
assert_nil SequenceSet["101:110,201:210,301:310"].at(44)
assert_equal :*, SequenceSet["1:10,*"].at(10)
end

test "#[non-negative index]" do
assert_nil SequenceSet.empty[0]
assert_equal 1, SequenceSet[1..][0]
Expand All @@ -182,18 +197,64 @@ def obj.to_sequence_set; 192_168.001_255 end
assert_equal :*, SequenceSet["1:10,*"][10]
end

test "#at(negative index)" do
assert_nil SequenceSet.empty.at(-1)
assert_equal :*, SequenceSet[1..].at(-1)
assert_equal 1, SequenceSet.full.at(-(2**32))
assert_equal 111, SequenceSet[1..111].at(-1)
assert_equal 6, SequenceSet[2,4,6,8].at(-2)
assert_equal 2, SequenceSet[2,4,6,8].at(-4)
assert_equal 4, SequenceSet[4..6].at(-3)
assert_nil SequenceSet[4..6].at(-4)
assert_equal 207, SequenceSet["101:110,201:210,301:310"].at(-14)
assert_equal 102, SequenceSet["101:110,201:210,301:310"].at(-29)
assert_nil SequenceSet["101:110,201:210,301:310"].at(-44)
end

test "#[negative index]" do
assert_nil SequenceSet.empty[0]
assert_nil SequenceSet.empty[-1]
assert_equal :*, SequenceSet[1..][-1]
assert_equal 1, SequenceSet.full[-(2**32)]
assert_equal 111, SequenceSet[1..111][-1]
assert_equal 4, SequenceSet[2,4,6,8][1]
assert_equal 8, SequenceSet[2,4,6,8][3]
assert_equal 6, SequenceSet[4..6][2]
assert_nil SequenceSet[4..6][3]
assert_equal 205, SequenceSet["101:110,201:210,301:310"][14]
assert_equal 310, SequenceSet["101:110,201:210,301:310"][29]
assert_nil SequenceSet["101:110,201:210,301:310"][44]
assert_equal 6, SequenceSet[2,4,6,8][-2]
assert_equal 2, SequenceSet[2,4,6,8][-4]
assert_equal 4, SequenceSet[4..6][-3]
assert_nil SequenceSet[4..6][-4]
assert_equal 207, SequenceSet["101:110,201:210,301:310"][-14]
assert_equal 102, SequenceSet["101:110,201:210,301:310"][-29]
assert_nil SequenceSet["101:110,201:210,301:310"][-44]
end

test "#ordered_at(non-negative index)" do
assert_nil SequenceSet.empty.ordered_at(0)
assert_equal 1, SequenceSet.full.ordered_at(0)
assert_equal 111, SequenceSet.full.ordered_at(110)
assert_equal 1, SequenceSet["1:*"].ordered_at(0)
assert_equal :*, SequenceSet["*,1"].ordered_at(0)
assert_equal 4, SequenceSet["6,4,8,2"].ordered_at(1)
assert_equal 2, SequenceSet["6,4,8,2"].ordered_at(3)
assert_equal 6, SequenceSet["9:11,4:6,1:3"].ordered_at(5)
assert_nil SequenceSet["9:11,4:6,1:3"].ordered_at(9)
assert_equal 105, SequenceSet["201:210,101:110,301:310"].ordered_at(14)
assert_equal 310, SequenceSet["201:210,101:110,301:310"].ordered_at(29)
assert_nil SequenceSet["201:210,101:110,301:310"].ordered_at(30)
assert_equal :*, SequenceSet["1:10,*"].ordered_at(10)
end

test "#ordered_at(negative index)" do
assert_nil SequenceSet.empty.ordered_at(-1)
assert_equal :*, SequenceSet["1:*"].ordered_at(-1)
assert_equal 1, SequenceSet.full.ordered_at(-(2**32))
assert_equal :*, SequenceSet["*,1"].ordered_at(0)
assert_equal 8, SequenceSet["6,4,8,2"].ordered_at(-2)
assert_equal 6, SequenceSet["6,4,8,2"].ordered_at(-4)
assert_equal 4, SequenceSet["9:11,4:6,1:3"].ordered_at(-6)
assert_equal 10, SequenceSet["9:11,4:6,1:3"].ordered_at(-8)
assert_nil SequenceSet["9:11,4:6,1:3"].ordered_at(-12)
assert_equal 107, SequenceSet["201:210,101:110,301:310"].ordered_at(-14)
assert_equal 201, SequenceSet["201:210,101:110,301:310"].ordered_at(-30)
assert_nil SequenceSet["201:210,101:110,301:310"].ordered_at(-31)
assert_equal :*, SequenceSet["1:10,*"].ordered_at(10)
end

test "#[start, length]" do
Expand Down