✨ Improve SequenceSet with Set, Range, Enumerable methods #239
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The version of SequenceSet in net-imap prior to this PR is merely a placeholder, needed in order to complete
tagged-ext
for #225.This updates it with a full API, inspired by Set, Range, and Array. This allows it to be more broadly useful, e.g. for storing and working with mailbox state. A better API for working with
sequence-set
is also a prerequisite for properly supportingESEARCH
(#115, #121). NOTE: The API added here is documented as experimental, but I'd like to remove that label when v0.5.0 is released.In addition to Integer, Range, and enumerables, any object with
#to_sequence_set
can now be used to create a sequence set. For compatibility with MessageSet,ThreadMember#to_sequence_set
collects all child seqno into a SequenceSet.Because mailbox state can be very large, inputs are stored in an internal sorted array of ranges. These are stored as
[start, stop]
tuples, not Range objects, for simpler manipulation. A future optimization could convert all tuples to a flat one-dimensional Array (to reduce object allocations). Storing the data in sorted range tuples allows many of the important operations to beO(lg n)
.Although updates do use
Array#insert
andArray#slice!
—which are technicallyO(n)
—they tend to be fast until the number of elements is very large. Count and index-based methods are alsoO(n)
. A future optimization could cache the count and compose larger sets from a balanced tree of smaller sets, to preserveO(lg n)
for most operations.SequenceSet will be used to replace MessageSet (which is used internally to validate, format, and send certain command args). Some notable differences between the two:
sequence-set
bug has been fixed.TODO list:
For now, everything except for
::[]
and#valid_string
is marked as "experimental". I don't expect any big changes though.::[]
to create a validated immutable sequence set::try_convert
to safely coerce other objects into SequenceSetSequenceSet#to_sequence_set
-- itselfMessageSet
#validate
#send_data
ThreadMember#to_sequence_set
#==
#eql?
and#hash
#===
#cover?
#include?
,#member?
#include_star?
#intersect?
#disjoint?
#empty?
#valid?
-- i.e: not empty#full?
Set
API#replace
#complement!
#add
and#<<
#add?
#merge
#clear
#delete
#delete?
#subtract
#limit!
Set
API#freeze
lhs + rhs
,lhs | rhs
(#union
)lhs - rhs
(#difference
)lhs & rhs
(#intersection
)lhs ^ rhs
(#xor
)~set
(#complement
)#limit
#elements
,#to_a
#each_element
#ranges
#each_range
#numbers
#each_number
#to_set
min
,max
,minmax
#count
#at
#[]
,#slice
#slice!
: remove a number or numbers at a given index or indices#find_index
: get the index of a number in the set#delete_at
: remove a number or numbers at a given index or indices#valid_string
- raises an exception when the set is empty#string
- isnil
when the set is empty#string=
- can be set tonil
to clear the set#to_s
- is empty string when empty#normalize
,normalize!
#inspect
- special cases for frozen and emptyO(lg n)
performance.TODO (later):
#pretty_print
#find_index_lte
,#find_index_gte
MessageSet
.