class Net::IMAP::SequenceSet

IMAP 序列集是一组消息序列号或唯一标识符(“UID”)。它包含数字和数字范围。这些数字都是非零的无符号 32 位整数和一个特殊值("*"),表示邮箱中的最大值。

某些类型的 IMAP 响应将包含一个 SequenceSet,例如 "MODIFIED" ResponseCode 的数据。某些 IMAP 命令可能会接收一个 SequenceSet 作为参数,例如 IMAP#searchIMAP#fetchIMAP#store

创建序列集

不带任何参数的 SequenceSet.new 创建一个空的序列集。请注意,空的序列集在 IMAP 语法中是无效的。

set = Net::IMAP::SequenceSet.new
set.empty?        #=> true
set.valid?        #=> false
set.valid_string  #!> raises DataFormatError
set << 1..10
set.empty?        #=> false
set.valid?        #=> true
set.valid_string  #=> "1:10"

SequenceSet.new 可以接收一个可选的参数:一个非零的 32 位无符号整数、一个范围、一个 sequence-set 格式的字符串、另一个序列集、一个 Set(仅包含数字或 *)或一个包含其中任何一个的数组(数组输入可以嵌套)。

set = Net::IMAP::SequenceSet.new(1)
set.valid_string  #=> "1"
set = Net::IMAP::SequenceSet.new(1..100)
set.valid_string  #=> "1:100"
set = Net::IMAP::SequenceSet.new(1...100)
set.valid_string  #=> "1:99"
set = Net::IMAP::SequenceSet.new([1, 2, 5..])
set.valid_string  #=> "1:2,5:*"
set = Net::IMAP::SequenceSet.new("1,2,3:7,5,6:10,2048,1024")
set.valid_string  #=> "1,2,3:7,5,6:10,2048,1024"
set = Net::IMAP::SequenceSet.new(1, 2, 3..7, 5, 6..10, 2048, 1024)
set.valid_string  #=> "1:10,55,1024:2048"

使用带有一个或多个参数的 ::[] 创建一个冻结的 SequenceSet。使用 ::[] 无法创建无效的(空)集合。

set = Net::IMAP::SequenceSet["1,2,3:7,5,6:10,2048,1024"]
set.valid_string  #=> "1,2,3:7,5,6:10,2048,1024"
set = Net::IMAP::SequenceSet[1, 2, [3..7, 5], 6..10, 2048, 1024]
set.valid_string  #=> "1:10,55,1024:2048"

规范化形式

当使用单个 String 值创建序列集时,将保留该 string 表示形式。SequenceSet 的内部表示形式会隐式地对所有条目进行排序、删除重复的数字并合并相邻或重叠的范围。大多数枚举方法和基于偏移量的方法都使用这种规范化表示形式。大多数修改方法会将 string 转换为其规范化形式。

在某些情况下,字符串表示形式的顺序很重要,例如 ESORTCONTEXT=SORTUIDPLUS 扩展。使用 entrieseach_entry 按其原始顺序枚举集合。要在修改集合时保留 string 顺序,请使用 appendstring=replace

使用 *

IMAP 序列集可以包含一个特殊值 "*",它表示正在使用的最大数字。来自 RFC9051 §9 中的 seq-number

在消息序列号的情况下,它是非空邮箱中消息的数量。在唯一标识符的情况下,它是邮箱中最后一条消息的唯一标识符;如果邮箱为空,则为邮箱当前的 UIDNEXT 值。

创建 SequenceSet 时,* 可以作为 -1"*":*、无限范围或以 -1 结尾的范围输入。当转换为 elementsrangesnumbers 时,它将输出为 :* 或无限范围。例如

Net::IMAP::SequenceSet["1,3,*"].to_a      #=> [1, 3, :*]
Net::IMAP::SequenceSet["1,234:*"].to_a    #=> [1, 234..]
Net::IMAP::SequenceSet[1234..-1].to_a     #=> [1234..]
Net::IMAP::SequenceSet[1234..].to_a       #=> [1234..]

Net::IMAP::SequenceSet[1234..].to_s       #=> "1234:*"
Net::IMAP::SequenceSet[1234..-1].to_s     #=> "1234:*"

使用 limit"*" 转换为最大值。当范围包含 "*" 时,始终会匹配最大值

Net::IMAP::SequenceSet["9999:*"].limit(max: 25)
#=> Net::IMAP::SequenceSet["25"]

令人惊讶的 * 行为

当集合包含 * 时,某些方法可能会有令人惊讶的行为。

例如,complement* 视为其自身的数字。这样,集合及其 complementintersection 将始终为空。这与 IMAP 服务器解释集合的方式不同:它会将 * 转换为邮箱中的消息数或 UIDNEXT,具体取决于情况。并且在将 limit 应用于每个集合后,集合及其补集之间存在重叠

~Net::IMAP::SequenceSet["*"]  == Net::IMAP::SequenceSet[1..(2**32-1)]
~Net::IMAP::SequenceSet[1..5] == Net::IMAP::SequenceSet["6:*"]

set = Net::IMAP::SequenceSet[1..5]
(set & ~set).empty? => true

(set.limit(max: 4) & (~set).limit(max: 4)).to_a => [4]

在计算集合中的数字数量时,除了当集合中也存在 UINT32_MAX 时,会计算 *

UINT32_MAX = 2**32 - 1
Net::IMAP::SequenceSet["*"].count                   => 1
Net::IMAP::SequenceSet[1..UINT32_MAX - 1, :*].count => UINT32_MAX

Net::IMAP::SequenceSet["1:*"].count                 => UINT32_MAX
Net::IMAP::SequenceSet[UINT32_MAX, :*].count        => 1
Net::IMAP::SequenceSet[UINT32_MAX..].count          => 1

这里有什么?

SequenceSet 提供以下方法:

创建 SequenceSet 的方法

  • ::[]:从一个或多个输入创建经过验证的冻结序列集。

  • ::new:创建一个新的可变序列集,该序列集可能为空(无效)。

  • ::try_convert:对对象调用 to_sequence_set 并验证结果是否为 SequenceSet

  • ::empty:返回冻结的空(无效)SequenceSet

  • ::full:返回包含每个可能数字的冻结 SequenceSet

用于比较的方法

与另一个 SequenceSet 进行比较

  • ==:返回给定集合是否包含与 self 相同的数字。

  • eql?:返回给定集合是否使用与 self 相同的 string

与可转换为 SequenceSet 的对象进行比较

  • ===:返回给定对象是否完全包含在 self 中;如果该对象无法转换为兼容类型,则返回 nil

  • cover?(别名为 ===):返回给定对象是否完全包含在 self 中。

  • intersect?(别名为 overlap?):返回 self 和给定对象是否具有任何公共元素。

  • disjoint?:返回 self 和给定对象是否没有公共元素。

用于查询的方法

这些方法不会修改 self

集合成员资格

  • include?(别名为 member?):返回给定对象(nz-number、范围或 *)是否包含在该集合中。

  • include_star?:返回集合是否包含 *

最小值和最大值元素

  • min:返回集合中的最小数字。

  • max:返回集合中的最大数字。

  • minmax:返回集合中的最小和最大数字。

按偏移量访问值

  • [](别名为 slice):返回给定偏移量或偏移量范围处的数字或连续子集。

  • at:返回给定偏移量处的数字。

  • find_index:返回给定数字在集合中的偏移量

集合基数

  • count(别名为 size):返回集合中数字的计数。

  • empty?:返回集合是否没有成员。IMAP 语法不允许空序列集。

  • valid?:返回集合是否具有任何成员。

  • full?:返回集合是否包含每个可能的值,包括 *

用于迭代的方法

  • each_element:生成集合中排序和合并的每个数字和范围,并返回 self

  • elements(别名为 to_a):返回集合中每个排序和合并的数字和范围的数组。

  • each_entry:生成集合中未排序且不删除重复数字或合并范围的每个数字和范围,并返回 self

  • entries:返回集合中每个未排序且不删除重复数字或合并范围的数字和范围的数组。

  • each_range:将集合中的每个元素作为 Range 生成并返回 self

  • ranges:返回集合中每个元素的数组,将数字转换为单个值的范围。

  • each_number:生成集合中的每个数字并返回 self

  • numbers: 返回一个数组,其中包含集合中的每个数字,并将范围扩展为所有包含的数字。

  • to_set: 返回一个包含集合中所有numbers的 Set。

集合运算方法

这些方法不会修改 self

  • #|(别名为union+):返回一个新的集合,其中包含self中的所有成员以及另一个对象中的所有成员。

  • #&(别名为intersection):返回一个新的集合,其中包含self和另一个对象共有的所有成员。

  • -(别名为difference):返回self的一个副本,其中删除了另一个对象中的所有成员。

  • #^(别名为xor):返回一个新的集合,其中包含self和另一个对象的所有成员,但排除两者共有的成员。

  • #~(别名为complement):返回一个新集合,其中包含所有不在self中的成员

  • limit: 返回 self 的一个副本,其中将 * 替换为给定的最大值,并删除所有超出该最大值的成员。

赋值方法

这些方法在 self 中添加或替换元素。

  • add(别名为<<):将给定对象添加到集合中;返回self

  • add?:如果给定对象不是集合中的元素,则将其添加并返回self;否则,返回nil

  • merge:将多个元素合并到集合中;返回self

  • append:将给定对象添加到集合中,将其附加到现有字符串中,并返回 self

  • string=:赋值新的 string 值并替换 elements 以匹配。

  • replace:使用给定对象的内容替换集合的内容。

  • complement!: 使用其自身的 complement 替换集合的内容。

删除方法

这些方法从 self 中删除元素。

  • clear:删除集合中的所有元素;返回self

  • delete:从集合中删除给定对象;返回self

  • delete?:如果给定对象是集合中的元素,则将其删除并返回;否则,返回nil

  • delete_at:删除给定偏移量处的数字。

  • slice!:删除给定偏移量或偏移量范围处的数字或连续数字。

  • subtract:从集合中删除每个给定对象;返回self

  • limit!: 将 * 替换为给定的最大值,并删除所有超出该最大值的成员;返回 self

IMAP 字符串格式化方法

  • to_s: 返回 sequence-set 字符串,当集合为空时,返回空字符串。

  • string: 返回 sequence-set 字符串,当集合为空时,返回 nil。

  • valid_string: 返回 sequence-set 字符串,当集合为空时,引发 DataFormatError

  • normalized_string: 返回一个 sequence-set 字符串,其元素已排序和合并,当集合为空时,返回 nil。

  • normalize: 返回一个新集合,其中包含此集合的规范化 sequence-set 表示形式。

  • normalize!: 将 string 更新为其规范化的 sequence-set 表示形式,并返回 self

常量

EMPTY

有意在类实现之后定义

FULL
STARS

“*”的有效输入

STAR_INT

在内部表示“*”,以简化排序(等)

UINT32_MAX

最大的可能的非零无符号 32 位整数

公共类方法

SequenceSet[*values] → 有效的冻结序列集 点击切换源

返回一个冻结的 SequenceSet,由 values 构建。

一个空的 SequenceSet 是无效的,将引发一个 DataFormatError

使用 ::new 创建一个可变或空的 SequenceSet

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 297
def [](first, *rest)
  if rest.empty?
    if first.is_a?(SequenceSet) && first.frozen? && first.valid?
      first
    else
      new(first).validate.freeze
    end
  else
    new(first).merge(*rest).validate.freeze
  end
end
empty() 点击切换源

返回一个冻结的空集合单例。请注意,有效的 IMAP 序列集不能为空,因此该集合是无效的。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 328
def empty; EMPTY end
full() 点击切换源

返回一个冻结的完整集合单例: "1:*"

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 331
def full;  FULL end
new(input = nil) 点击切换源

input 创建一个新的 SequenceSet 对象,它可以是另一个 SequenceSet、一个 IMAP 格式化的 sequence-set 字符串、一个数字、一个范围、:* 或这些的可枚举对象。

使用 ::[] 创建一个冻结的(非空)SequenceSet

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 340
def initialize(input = nil) input ? replace(input) : clear end
try_convert(obj) → 序列集或 nil 点击切换源

如果 obj 是一个 SequenceSet,则返回 obj。如果 obj 响应 to_sequence_set,则调用 obj.to_sequence_set 并返回结果。否则返回 nil

如果 obj.to_sequence_set 没有返回 SequenceSet,则会引发异常。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 318
def try_convert(obj)
  return obj if obj.is_a?(SequenceSet)
  return nil unless obj.respond_to?(:to_sequence_set)
  obj = obj.to_sequence_set
  return obj if obj.is_a?(SequenceSet)
  raise DataFormatError, "invalid object returned from to_sequence_set"
end

公共实例方法

self & other → 序列集 点击切换源

返回一个新的序列集,其中仅包含此集合和 other 共有的数字。

other 可以是任何会被 ::new 接受的对象:非零 32 位无符号整数、范围、sequence-set 格式的字符串、另一个序列集或包含这些的可枚举对象。

Net::IMAP::SequenceSet[1..5] & [2, 4, 6]
#=> Net::IMAP::SequenceSet["2,4"]

(seqset & other) 等效于 (seqset - ~other)

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 619
def &(other)
  remain_frozen dup.subtract SequenceSet.new(other).complement!
end
也别名为:intersection
self + other → 序列集
别名为: |
self - other → 序列集 点击切换源

返回通过复制此集合并删除 other 中出现的每个数字而构建的新序列集。

other 可以是任何会被 ::new 接受的对象:非零 32 位无符号整数、范围、sequence-set 格式的字符串、另一个序列集或包含这些的可枚举对象。

Net::IMAP::SequenceSet[1..5] - 2 - 4 - 6
#=> Net::IMAP::SequenceSet["1,3,5"]

相关:subtract

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 601
def -(other) remain_frozen dup.subtract other end
也别名为: difference
self << other → self
别名为:add
self == other → true 或 false 点击切换源

当另一个 SequenceSet 表示相同的消息标识符时,返回 true。编码差异(如顺序、重叠或重复)将被忽略。

Net::IMAP::SequenceSet["1:3"]   == Net::IMAP::SequenceSet["1:3"]
#=> true
Net::IMAP::SequenceSet["1,2,3"] == Net::IMAP::SequenceSet["1:3"]
#=> true
Net::IMAP::SequenceSet["1,3"]   == Net::IMAP::SequenceSet["3,1"]
#=> true
Net::IMAP::SequenceSet["9,1:*"] == Net::IMAP::SequenceSet["1:*"]
#=> true

相关:eql?normalize

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 437
def ==(other)
  self.class == other.class &&
    (to_s == other.to_s || tuples == other.tuples)
end
self === other → true | false | nil 点击切换源

返回 other 是否包含在集合中。如果在将 other 转换为可比较类型时引发 StandardError,则返回 nil

相关:cover?include?include_star?

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 467
def ===(other)
  cover?(other)
rescue
  nil
end
seqset[index] → 整数或 :* 或 nil 点击切换源
seqset[start, length] → 序列集或 nil
seqset[range] → 序列集或 nil

self 返回一个数字或一个子集,而不修改该集合。

当给定整数参数 index 时,返回偏移量 index 处的数字

set = Net::IMAP::SequenceSet["10:15,20:23,26"]
set[0]   #=> 10
set[5]   #=> 15
set[10]  #=> 26

如果 index 为负数,则相对于 self 的末尾计数

set = Net::IMAP::SequenceSet["10:15,20:23,26"]
set[-1]  #=> 26
set[-3]  #=> 22
set[-6]  #=> 15

如果 index 超出范围,则返回 nil

set = Net::IMAP::SequenceSet["10:15,20:23,26"]
set[11]  #=> nil
set[-12] #=> nil

结果基于规范化的集合(已排序且已删除重复项),而不是 string 的分配值。

set = Net::IMAP::SequenceSet["12,20:23,11:16,21"]
set[0]   #=> 11
set[-1]  #=> 23
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1085
def [](index, length = nil)
  if    length              then slice_length(index, length)
  elsif index.is_a?(Range)  then slice_range(index)
  else                           at(index)
  end
end
也别名为: slice
self ^ other → 序列集 点击切换源

返回一个新的序列集,其中包含此集合和 other 之间的唯一数字。

other 可以是任何会被 ::new 接受的对象:非零 32 位无符号整数、范围、sequence-set 格式的字符串、另一个序列集或包含这些的可枚举对象。

Net::IMAP::SequenceSet[1..5] ^ [2, 4, 6]
#=> Net::IMAP::SequenceSet["1,3,5:6"]

(seqset ^ other) 等效于 ((seqset | other) - (seqset & other))

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 640
def ^(other) remain_frozen (self | other).subtract(self & other) end
也别名为: xor
add(object) → self 点击切换源

将一个范围或数字添加到集合并返回 self

string 将被重新生成。使用 merge 一次添加多个元素。

相关:add?, merge, union

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 670
def add(object)
  tuple_add input_to_tuple object
  normalize!
end
也别名为: <<
add?(object) → self 或 nil 点击切换源

将一个范围或数字添加到集合并返回 self。当该对象已包含在集合中时,返回 nil

string 将被重新生成。使用 merge 一次添加多个元素。

相关:addmergeunioninclude?

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 697
def add?(object)
  add object unless include? object
end
append(object) 点击切换源

将一个范围或数字添加到集合并返回 self

add, mergeunion 不同,新值将附加到 string。这可能会导致 string 出现重复或顺序错误。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 680
def append(object)
  modifying!
  tuple = input_to_tuple object
  entry = tuple_to_str tuple
  tuple_add tuple
  @string = -(string ? "#{@string},#{entry}" : entry)
  self
end
at(index) → 整数或 nil 点击切换源

self 返回一个数字,而不修改集合。行为与 [] 相同,只是 at 只允许一个整数参数。

相关:[]slice

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1034
def at(index)
  index = Integer(index.to_int)
  if index.negative?
    reverse_each_tuple_with_index 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 do |min, _, idx_min, idx_max|
      index <= idx_max and return from_tuple_int(min + (index - idx_min))
    end
  end
  nil
end
clear() 点击切换源

删除所有元素并返回 self。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 343
def clear; @tuples, @string = [], nil; self end
complement → 序列集
别名为:~
complement! → self 点击切换源

SequenceSet 转换为其自身的 complement。它将包含所有可能的值,除了当前在集合中的值。

相关:complement

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1165
def complement!
  return replace(self.class.full) if empty?
  return clear                    if full?
  flat = @tuples.flat_map { [_1 - 1, _2 + 1] }
  if flat.first < 1         then flat.shift else flat.unshift 1        end
  if STAR_INT   < flat.last then flat.pop   else flat.push    STAR_INT end
  @tuples = flat.each_slice(2).to_a
  normalize!
end
count() 点击切换源

返回集合中 numbers 的计数。

如果集合中同时存在 *2**32 - 1 (最大 32 位无符号整数值),它们将只被计数一次。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 986
def count
  @tuples.sum(@tuples.count) { _2 - _1 } +
    (include_star? && include?(UINT32_MAX) ? -1 : 0)
end
别名:size
cover?(other) → true | false | nil 点击以切换源

返回 other 是否包含在该集合中。other 可以是任何能被 ::new 接受的对象。

相关:===, include?, include_star?

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 479
def cover?(other) input_to_tuples(other).none? { !include_tuple?(_1) } end
deconstruct() 点击以切换源

当有效时返回一个包含 normalized_string 的数组,否则返回一个空数组。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 386
def deconstruct; valid? ? [normalized_string] : [] end
delete(object) → self 点击以切换源

从集合中删除给定的范围或数字,并返回 self

删除后,string 将被重新生成。使用 subtract 可以一次删除多个元素。

相关:delete?, delete_at, subtract, difference

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 709
def delete(object)
  tuple_subtract input_to_tuple object
  normalize!
end
delete?(number) → integer or nil 点击以切换源
delete?(star) → :* or nil
delete?(range) → sequence set or nil

从集合中删除指定的值,并返回删除的值。如果未删除任何内容,则返回 nil

当删除指定的 number 参数时,返回一个整数。

set = Net::IMAP::SequenceSet.new [5..10, 20]
set.delete?(7)      #=> 7
set                 #=> #<Net::IMAP::SequenceSet "5:6,8:10,20">
set.delete?("20")   #=> 20
set                 #=> #<Net::IMAP::SequenceSet "5:6,8:10">
set.delete?(30)     #=> nil

当指定并删除 *-1 时,返回 :*

set = Net::IMAP::SequenceSet.new "5:9,20,35,*"
set.delete?(-1)  #=> :*
set              #=> #<Net::IMAP::SequenceSet "5:9,20,35">

当指定范围时,返回一个新的 SequenceSet

set = Net::IMAP::SequenceSet.new [5..10, 20]
set.delete?(9..)  #=> #<Net::IMAP::SequenceSet "9:10,20">
set               #=> #<Net::IMAP::SequenceSet "5:8">
set.delete?(21..) #=> nil

删除后,string 将被重新生成。

相关:delete, delete_at, subtract, difference, disjoint?

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 746
def delete?(object)
  tuple = input_to_tuple object
  if tuple.first == tuple.last
    return unless include_tuple? tuple
    tuple_subtract tuple
    normalize!
    from_tuple_int tuple.first
  else
    copy = dup
    tuple_subtract tuple
    normalize!
    copy if copy.subtract(self).valid?
  end
end
delete_at(index) → number or :* or nil 点击以切换源

删除集合中由给定 index 指示的数字。返回被删除的数字,如果未删除任何内容,则返回 nil

删除后,string 将被重新生成。

相关:delete, delete?, slice!, subtract, difference

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 769
def delete_at(index)
  slice! Integer(index.to_int)
end
difference(other) → sequence set
别名:-
disjoint?(other) 点击以切换源

如果集合和给定对象没有公共元素,则返回 true,否则返回 false

Net::IMAP::SequenceSet["5:10"].disjoint? "7,9,11" #=> false
Net::IMAP::SequenceSet["5:10"].disjoint? "11:33"  #=> true

相关:intersection, intersect?

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 531
def disjoint?(other)
  empty? || input_to_tuples(other).none? { intersect_tuple? _1 }
end
each_element() { |integer or range or :*| ... } 点击以切换源

elements 中的每个数字或范围(或 :*)传递给代码块,并返回 self。当不带代码块调用时,返回一个枚举器。

返回的数字是排序和去重的,即使输入 string 不是。参见 normalize

相关:elements, each_entry

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 921
def each_element # :yields: integer or range or :*
  return to_enum(__method__) unless block_given?
  @tuples.each do yield tuple_to_entry _1 end
  self
end
each_entry() { |integer or range or :*| ... } 点击以切换源

string 中的每个数字或范围传递给代码块,并返回 self。当不带代码块调用时,返回一个枚举器。

条目按照它们在 string 中出现的相同顺序产生,没有排序、去重或合并。当 string 处于其规范化形式时,这将产生与 each_element 相同的值。

相关:entries, each_element

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 907
def each_entry(&block) # :yields: integer or range or :*
  return to_enum(__method__) unless block_given?
  return each_element(&block) unless @string
  @string.split(",").each do yield tuple_to_entry str_to_tuple _1 end
  self
end
each_number() { |integer| ... } 点击以切换源

numbers 中的每个数字传递给代码块,并返回 self。如果集合包含 *,将引发 RangeError。

当不带代码块调用时,返回一个枚举器(即使集合包含 *)。

相关:numbers

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 961
def each_number(&block) # :yields: integer
  return to_enum(__method__) unless block_given?
  raise RangeError, '%s contains "*"' % [self.class] if include_star?
  each_element do |elem|
    case elem
    when Range   then elem.each(&block)
    when Integer then block.(elem)
    end
  end
  self
end
each_range() { |range| ... } 点击以切换源

ranges 中的每个范围传递给代码块,并返回 self。当不带代码块调用时,返回一个枚举器。

相关:ranges

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 943
def each_range # :yields: range
  return to_enum(__method__) unless block_given?
  @tuples.each do |min, max|
    if    min == STAR_INT then yield :*..
    elsif max == STAR_INT then yield min..
    else                       yield min..max
    end
  end
  self
end
elements() 点击以切换源

返回一个范围、整数和 :* 的数组。

返回的元素是排序和合并的,即使输入 string 不是。* 将最后排序。参见 normalize

单独来说,* 转换为 :*。包含 * 的范围转换为无限范围。使用 limit 可以将这两种情况都转换为最大值。

如果原始输入是无序的或包含重叠的范围,则返回的范围将被排序和合并。

Net::IMAP::SequenceSet["2,5:9,6,*,12:11"].elements
#=> [2, 5..9, 11..12, :*]

相关:each_element, ranges, numbers

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 848
def elements; each_element.to_a end
别名:to_a
empty?() 点击以切换源

如果集合不包含任何元素,则返回 true。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 561
def empty?; @tuples.empty? end
entries() 点击以切换源

返回一个范围、整数和 :* 的数组。

条目按照它们在 string 中出现的相同顺序排列,没有排序、去重或合并。当 string 处于其规范化形式时,这将返回与 elements 相同的结果。当给定顺序很重要时,这很有用,例如在 ESEARCH 响应中用于 IMAP#sort

相关:each_entry, elements

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 830
def entries; each_entry.to_a end
eql?(other) → true or false 点击以切换源

哈希相等性需要相同的编码 string 表示形式。

Net::IMAP::SequenceSet["1:3"]  .eql? Net::IMAP::SequenceSet["1:3"]
#=> true
Net::IMAP::SequenceSet["1,2,3"].eql? Net::IMAP::SequenceSet["1:3"]
#=> false
Net::IMAP::SequenceSet["1,3"]  .eql? Net::IMAP::SequenceSet["3,1"]
#=> false
Net::IMAP::SequenceSet["9,1:*"].eql? Net::IMAP::SequenceSet["1:*"]
#=> false

相关:==, normalize

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 456
def eql?(other) self.class == other.class && string == other.string end
find_index(number) 点击以切换源

返回 number 在集合中的索引,如果 number 不在集合中,则返回 nil

相关:[]

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 997
def find_index(number)
  number = to_tuple_int number
  each_tuple_with_index do |min, max, idx_min|
    number <  min and return nil
    number <= max and return from_tuple_int(idx_min + (number - min))
  end
  nil
end
freeze() 点击以切换源

冻结并返回集合。冻结的 SequenceSet 是 Ractor 安全的。

调用超类方法
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 414
def freeze
  return self if frozen?
  string
  @tuples.each(&:freeze).freeze
  super
end
full?() 点击以切换源

如果集合包含每个可能的元素,则返回 true。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 564
def full?; @tuples == [[1, STAR_INT]] end
hash() 点击以切换源

参见 eql?

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 459
def hash; [self.class, string].hash end
include?(element) 点击以切换源

当给定数字或范围在 self 中时,返回 true,否则返回 false。除非 number 是整数、范围或 *,否则返回 false

set = Net::IMAP::SequenceSet["5:10,100,111:115"]
set.include? 1      #=> false
set.include? 5..10  #=> true
set.include? 11..20 #=> false
set.include? 100    #=> true
set.include? 6      #=> true, covered by "5:10"
set.include? 4..9   #=> true, covered by "5:10"
set.include? "4:9"  #=> true, strings are parsed
set.include? 4..9   #=> false, intersection is not sufficient
set.include? "*"    #=> false, use #limit to re-interpret "*"
set.include? -1     #=> false, -1 is interpreted as "*"

set = Net::IMAP::SequenceSet["5:10,100,111:*"]
set.include? :*     #=> true
set.include? "*"    #=> true
set.include? -1     #=> true
set.include? 200..  #=> true
set.include? 100..  #=> false

相关:include_star?, cover?, ===

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 505
def include?(element) include_tuple? input_to_tuple element end
别名:member?
include_star?() 点击以切换源

当集合包含 * 时,返回 true

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 510
def include_star?; @tuples.last&.last == STAR_INT end
inspect() 点击以切换源
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1211
def inspect
  if empty?
    (frozen? ?  "%s.empty" : "#<%s empty>") % [self.class]
  elsif frozen?
    "%s[%p]"   % [self.class, to_s]
  else
    "#<%s %p>" % [self.class, to_s]
  end
end
intersect?(other) 点击以切换源

如果集合和给定对象有任何公共元素,则返回 true,否则返回 false

Net::IMAP::SequenceSet["5:10"].intersect? "7,9,11" #=> true
Net::IMAP::SequenceSet["5:10"].intersect? "11:33"  #=> false

相关:intersection, disjoint?

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 519
def intersect?(other)
  valid? && input_to_tuples(other).any? { intersect_tuple? _1 }
end
别名:overlap?
intersection(other) → sequence set
别名:&
limit(max:) 点击以切换源

返回一个冻结的 SequenceSet,其中 * 转换为 max,删除了大于 max 的数字和范围,并且将包含 max 的范围转换为以 max 结束。

Net::IMAP::SequenceSet["5,10:22,50"].limit(max: 20).to_s
#=> "5,10:20"

* 始终被解释为最大值。当集合包含 * 时,它将被设置为等于该限制。

Net::IMAP::SequenceSet["*"].limit(max: 37)
#=> Net::IMAP::SequenceSet["37"]
Net::IMAP::SequenceSet["5:*"].limit(max: 37)
#=> Net::IMAP::SequenceSet["5:37"]
Net::IMAP::SequenceSet["500:*"].limit(max: 37)
#=> Net::IMAP::SequenceSet["37"]
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1138
def limit(max:)
  max = to_tuple_int(max)
  if    empty?                      then self.class.empty
  elsif !include_star? && max < min then self.class.empty
  elsif max(star: STAR_INT) <= max  then frozen? ? self : dup.freeze
  else                                   dup.limit!(max: max).freeze
  end
end
limit!(max:) 点击以切换源

删除所有大于 max 的成员,并返回 self。如果 * 是一个成员,它将被转换为 max

相关:limit

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1151
def limit!(max:)
  star = include_star?
  max  = to_tuple_int(max)
  tuple_subtract [max + 1, STAR_INT]
  tuple_add      [max,     max     ] if star
  normalize!
end
max(star: :*) → integer or star or nil 点击以切换源

返回 self 中的最大值,当集合包含 * 时返回 star,当集合为空时返回 nil

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 539
def max(star: :*)
  (val = @tuples.last&.last) && val == STAR_INT ? star : val
end
member?(element)
别名:include?
merge(*inputs) 点击以切换源

将任何 inputs 中出现的所有元素合并到集合中,并返回 self

inputs 可以是任何被 ::new 接受的对象:非零 32 位无符号整数、范围、sequence-set 格式的字符串、其他序列集或包含任何这些内容的可枚举对象。

所有输入合并后,string 将会被重新生成。

相关方法: add, add?, union

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 802
def merge(*inputs)
  tuples_add input_to_tuples inputs
  normalize!
end
min(star: :*) → integer or star or nil 点击切换源代码

返回 self 中的最小值,当集合中唯一的值是 * 时返回 star,当集合为空时返回 nil

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 547
def min(star: :*)
  (val = @tuples.first&.first) && val == STAR_INT ? star : val
end
minmax(star: :*) → nil or [integer, integer or star] 点击切换源代码

返回一个包含 self 中最小值和最大值的 2 元素数组,当集合为空时返回 nil

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 555
def minmax(star: :*); [min(star: star), max(star: star)] unless empty? end
normalize() 点击切换源代码

返回一个新的 SequenceSet,其中包含标准化的字符串表示形式。

返回的集合的 string 是排序和去重的。相邻或重叠的元素将被合并为一个更大的范围。

Net::IMAP::SequenceSet["1:5,3:7,10:9,10:11"].normalize
#=> Net::IMAP::SequenceSet["1:7,9:11"]

相关方法: normalize!, normalized_string

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1184
def normalize
  str = normalized_string
  return self if frozen? && str == string
  remain_frozen dup.instance_exec { @string = str&.-@; self }
end
normalize!() 点击切换源代码

重置 string 为排序、去重和合并后的形式。返回 self

相关方法: normalize, normalized_string

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1194
def normalize!
  @string = nil
  self
end
normalized_string() 点击切换源代码

返回标准化的 sequence-set 字符串表示形式,排序并去重。相邻或重叠的元素将被合并为一个更大的范围。当集合为空时返回 nil

Net::IMAP::SequenceSet["1:5,3:7,10:9,10:11"].normalized_string
#=> "1:7,9:11"

相关方法: normalize!, normalize

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1207
def normalized_string
  @tuples.empty? ? nil : -@tuples.map { tuple_to_str _1 }.join(",")
end
numbers() 点击切换源代码

返回序列集中所有数字值的排序数组。

返回的数字是排序和去重的,即使输入 string 不是。参见 normalize

Net::IMAP::SequenceSet["2,5:9,6,12:11"].numbers
#=> [2, 5, 6, 7, 8, 9, 11, 12]

如果集合包含 *,则会引发 RangeError。请参阅 limit

Net::IMAP::SequenceSet["10000:*"].numbers
#!> RangeError

警告:即使排除包含 * 的集合,也可能很容易创建巨大的结果。可能会返回一个包含超过 40 亿个整数的数组,在 64 位架构上需要高达 32GiB 的内存。

Net::IMAP::SequenceSet[10000..2**32-1].numbers
# ...probably freezes the process for a while...
#!> NoMemoryError (probably)

为了安全起见,请考虑使用 limitintersection 来设置上限。或者,使用 each_elementeach_range,甚至 each_number 来避免分配结果数组。

相关方法: elements, ranges, to_set

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 897
def numbers; each_number.to_a end
overlap?(other)
别名: intersect?
ranges() 点击切换源代码

返回范围数组

返回的元素是排序和合并的,即使输入 string 不是。* 将最后排序。参见 normalize

* 转换为无限范围。单独使用时,* 转换为 :*..。使用 limit* 设置为最大值。

返回的范围将被排序和合并,即使输入 string 没有被排序和合并。* 将排在最后。请参阅 normalize

Net::IMAP::SequenceSet["2,5:9,6,*,12:11"].ranges
#=> [2..2, 5..9, 11..12, :*..]
Net::IMAP::SequenceSet["123,999:*,456:789"].ranges
#=> [123..123, 456..789, 999..]

相关方法: each_range, elements, numbers, to_set

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 869
def ranges; each_range.to_a end
replace(other) 点击切换源代码

other 的内容替换集合的内容,并返回 self

other 可以是另一个 SequenceSet,也可以是 IMAP sequence-set 字符串、数字、范围、* 或这些内容的可枚举对象。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 350
def replace(other)
  case other
  when SequenceSet then initialize_dup(other)
  when String      then self.string = other
  else                  clear; merge other
  end
  self
end
size()
别名: count
slice(index) → integer or :* or nil
slice(start, length) → sequence set or nil
slice(range) → sequence set or nil
别名: []
slice!(index) → integer or :* or nil 点击切换源代码
slice!(start, length) → sequence set or nil
slice!(range) → sequence set or nil

从集合中删除由给定 indexstartlength 或偏移量 range 指示的数字或连续数字。返回删除的数字或序列集,如果未删除任何内容,则返回 nil。参数的解释方式与 slice[] 相同。

删除后,string 将被重新生成。

相关方法: slice, delete_at, delete, delete?, subtract, difference

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 786
def slice!(index, length = nil)
  deleted = slice(index, length) and subtract deleted
  deleted
end
string() 点击切换源代码

返回 IMAP sequence-set 字符串表示形式,当集合为空时返回 nil。请注意,空集合在 IMAP 语法中是无效的。

当集合为空时,使用 valid_string 引发异常,或使用 to_s 返回空字符串。

如果集合是从单个字符串创建的,则不会标准化。如果更新集合,则字符串将标准化。

相关方法: valid_string, normalized_string, to_s

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 382
def string; @string ||= normalized_string if valid? end
string=(str) 点击切换源代码

string 分配一个新字符串,并重置 elements 以匹配。它不能设置为空字符串,请分配 nil 或使用 clear 代替。该字符串已验证但未标准化。

使用 addmerge 将字符串添加到现有集合。

相关方法: replace, clear

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 395
def string=(str)
  if str.nil?
    clear
  else
    str = String.try_convert(str) or raise ArgumentError, "not a string"
    tuples = str_to_tuples str
    @tuples, @string = [], -str
    tuples_add tuples
  end
end
subtract(*objects) 点击切换源代码

从集合中删除任何给定的 objects 中出现的所有元素,并返回 self

objects 可以是任何被 ::new 接受的对象:非零 32 位无符号整数、范围、sequence-set 格式的字符串、其他序列集或包含任何这些内容的可枚举对象。

相关方法: difference

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 816
def subtract(*objects)
  tuples_subtract input_to_tuples objects
  normalize!
end
to_a()
别名: elements
to_s() 点击切换源代码

返回 IMAP sequence-set 字符串表示形式,当集合为空时返回空字符串。请注意,空集合在 IMAP 语法中是无效的。

相关方法: valid_string, normalized_string, to_s

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 411
def to_s; string || "" end
to_set() 点击切换源代码

返回一个包含序列集中所有 numbers 的集合。

如果集合包含 *,则会引发 RangeError。

有关非常大的集合的警告,请参阅 numbers

相关方法: elements, ranges, numbers

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 980
def to_set; Set.new(numbers) end
union(other) → sequence set
别名为: |
valid?() 点击切换源代码

当集合为空时返回 false。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 558
def valid?; !empty? end
valid_string() 点击切换源代码

返回 IMAP sequence-set 字符串表示形式,当集合为空时引发 DataFormatError

使用 string 返回 nil 或使用 to_s 返回空字符串而不会出错。

相关方法: string, normalized_string, to_s

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 366
def valid_string
  raise DataFormatError, "empty sequence-set" if empty?
  string
end
xor(other) → sequence set
别名: ^
self | other → sequence set 点击切换源代码

返回一个新的序列集,其中添加了 other 对象中的每个数字。

other 可以是任何会被 ::new 接受的对象:非零 32 位无符号整数、范围、sequence-set 格式的字符串、另一个序列集或包含这些的可枚举对象。

Net::IMAP::SequenceSet["1:5"] | 2 | [4..6, 99]
#=> Net::IMAP::SequenceSet["1:6,99"]

相关方法: add, merge

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 582
def |(other) remain_frozen dup.merge other end
也别名为: +, union
~ self → sequence set 点击切换源代码

返回 self 的补集,即一个 SequenceSet,它包含除了此集合中那些之外的所有数字。

~Net::IMAP::SequenceSet.full  #=> Net::IMAP::SequenceSet.empty
~Net::IMAP::SequenceSet.empty #=> Net::IMAP::SequenceSet.full
~Net::IMAP::SequenceSet["1:5,100:222"]
#=> Net::IMAP::SequenceSet["6:99,223:*"]
~Net::IMAP::SequenceSet["6:99,223:*"]
#=> Net::IMAP::SequenceSet["1:5,100:222"]

相关方法: complement!

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 658
def ~; remain_frozen dup.complement! end
也别名为: complement

私有实例方法

each_tuple_with_index() { |min, max, idx_min, (idx_max = idx_min + (max - min))| ... } 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1008
def each_tuple_with_index
  idx_min = 0
  @tuples.each do |min, max|
    yield min, max, idx_min, (idx_max = idx_min + (max - min))
    idx_min = idx_max + 1
  end
  idx_min
end
from_tuple_int(num) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1301
def from_tuple_int(num) num == STAR_INT ? :* : num end
include_tuple?((min, max)) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1310
def include_tuple?((min, max)) range_gte_to(min)&.cover?(min..max) end
initialize_clone(other) 点击切换源代码

冻结的克隆是浅拷贝的

调用超类方法
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1244
def initialize_clone(other)
  other.frozen? ? super : initialize_dup(other)
end
initialize_dup(other) 点击切换源代码
调用超类方法
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1248
def initialize_dup(other)
  @tuples = other.tuples.map(&:dup)
  @string = other.string&.-@
  super
end
input_to_tuple(obj) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1254
def input_to_tuple(obj)
  obj = input_try_convert obj
  case obj
  when *STARS, Integer then [int = to_tuple_int(obj), int]
  when Range           then range_to_tuple(obj)
  when String          then str_to_tuple(obj)
  else
    raise DataFormatError, "expected number or range, got %p" % [obj]
  end
end
input_to_tuples(obj) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1265
def input_to_tuples(obj)
  obj = input_try_convert obj
  case obj
  when *STARS, Integer, Range then [input_to_tuple(obj)]
  when String      then str_to_tuples obj
  when SequenceSet then obj.tuples
  when Set         then obj.map      { [to_tuple_int(_1)] * 2 }
  when Array       then obj.flat_map { input_to_tuples _1 }
  when nil         then []
  else
    raise DataFormatError,
          "expected nz-number, range, string, or enumerable; " \
          "got %p" % [obj]
  end
end
input_try_convert(input) 点击切换源代码

与 SequenceSet#try_convert 不同,此方法返回 Integer、Range、String、Set、Array 或…任何类型的对象。

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1283
def input_try_convert(input)
  SequenceSet.try_convert(input) ||
    Integer.try_convert(input) ||
    String.try_convert(input) ||
    input
end
intersect_tuple?((min, max)) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1312
def intersect_tuple?((min, max))
  range = range_gte_to(min) and
    range.include?(min) || range.include?(max) || (min..max).cover?(range)
end
modifying!() 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1317
def modifying!
  if frozen?
    raise FrozenError, "can't modify frozen #{self.class}: %p" % [self]
  end
end
nz_number(num) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1414
def nz_number(num)
  String === num && !/\A[1-9]\d*\z/.match?(num) and
    raise DataFormatError, "%p is not a valid nz-number" % [num]
  NumValidator.ensure_nz_number Integer num
rescue TypeError # To catch errors from Integer()
  raise DataFormatError, $!.message
end
range_gte_to(num) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1409
def range_gte_to(num)
  first, last = tuples.bsearch { _2 >= num }
  first..last if first
end
range_to_tuple(range) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1290
def range_to_tuple(range)
  first = to_tuple_int(range.begin || 1)
  last  = to_tuple_int(range.end   || :*)
  last -= 1 if range.exclude_end? && range.end && last != STAR_INT
  unless first <= last
    raise DataFormatError, "invalid range for sequence-set: %p" % [range]
  end
  [first, last]
end
remain_frozen(set) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1241
def remain_frozen(set) frozen? ? set.freeze : set end
reverse_each_tuple_with_index() { |min, max, (idx_min = idx_max - (max - min)), idx_max| ... } 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1017
def reverse_each_tuple_with_index
  idx_max = -1
  @tuples.reverse_each do |min, max|
    yield min, max, (idx_min = idx_max - (max - min)), idx_max
    idx_max = idx_min - 1
  end
  idx_max
end
slice_length(start, length) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1096
def slice_length(start, length)
  start  = Integer(start.to_int)
  length = Integer(length.to_int)
  raise ArgumentError, "length must be positive" unless length.positive?
  last = start + length - 1 unless start.negative? && start.abs <= length
  slice_range(start..last)
end
slice_range(range) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1104
def slice_range(range)
  first = range.begin ||  0
  last  = range.end   || -1
  last -= 1 if range.exclude_end? && range.end && last != STAR_INT
  if (first * last).positive? && last < first
    SequenceSet.empty
  elsif (min = at(first))
    max = at(last)
    if    max == :*  then self & (min..)
    elsif min <= max then self & (min..max)
    else                  SequenceSet.empty
    end
  end
end
str_to_tuple(str) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1305
def str_to_tuple(str)
  raise DataFormatError, "invalid sequence set string" if str.empty?
  str.split(":", 2).map! { to_tuple_int _1 }.minmax
end
str_to_tuples(str) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1304
def str_to_tuples(str) str.split(",", -1).map! { str_to_tuple _1 } end
to_tuple_int(obj) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1300
def to_tuple_int(obj) STARS.include?(obj) ? STAR_INT : nz_number(obj) end
tuple_add(tuple) 点击切换源代码

–|=====| |=====新元组=====| 追加 ?????????-|=====新元组=====|-|===较低===|– 插入

|=====new tuple=====|

———??=======较低=======??————— 无操作

———??===较低==|–|==| 连接剩余 ———??===较低==|–|==|—-|===较高===|– 连接直到较高 ———??===较低==|–|==|–|=====较高===|– 连接到较高

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1336
def tuple_add(tuple)
  modifying!
  min, max = tuple
  lower, lower_idx = tuple_gte_with_index(min - 1)
  if    lower.nil?              then tuples << tuple
  elsif (max + 1) < lower.first then tuples.insert(lower_idx, tuple)
  else  tuple_coalesce(lower, lower_idx, min, max)
  end
end
tuple_coalesce(较低, lower_idx, min, max) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1346
def tuple_coalesce(lower, lower_idx, min, max)
  return if lower.first <= min && max <= lower.last
  lower[0] = [min, lower.first].min
  lower[1] = [max, lower.last].max
  lower_idx += 1
  return if lower_idx == tuples.count
  tmax_adj = lower.last + 1
  upper, upper_idx = tuple_gte_with_index(tmax_adj)
  if upper
    tmax_adj < upper.first ? (upper_idx -= 1) : (lower[1] = upper.last)
  end
  tuples.slice!(lower_idx..upper_idx)
end
tuple_gte_with_index(num) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1405
def tuple_gte_with_index(num)
  idx = tuples.bsearch_index { _2 >= num } and [tuples[idx], idx]
end
tuple_subtract(tuple) 点击切换源代码
|====tuple================|

–|====| 不再有 1. 无操作 –|====|—————————|====较低====|– 2. 无操作 ——-|======较低================|—————- 3. 分割 ——–|=====较低================|—————- 4. 修剪开头

——-|======较低====????????????—————– 修剪较低 ——–|=====较低====????????????—————– 删除较低

——-??=====较低===============|—————– 5. 修剪/删除一个 ——-??=====较低====|–|====| 不再有 6. 删除其余 ——-??=====较低====|–|====|—|====较高====|– 7. 删除直到 ——-??=====较低====|–|====|–|=====较高====|– 8. 删除并修剪

# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1373
def tuple_subtract(tuple)
  modifying!
  min, max = tuple
  lower, idx = tuple_gte_with_index(min)
  if    lower.nil?        then nil # case 1.
  elsif max < lower.first then nil # case 2.
  elsif max < lower.last  then tuple_trim_or_split   lower, idx, min, max
  else                         tuples_trim_or_delete lower, idx, min, max
  end
end
tuple_to_entry((min, max)) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 929
def tuple_to_entry((min, max))
  if    min == STAR_INT then :*
  elsif max == STAR_INT then min..
  elsif min == max      then min
  else                       min..max
  end
end
tuple_to_str(tuple) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1303
def tuple_to_str(tuple) tuple.uniq.map{ from_tuple_int _1 }.join(":") end
tuple_trim_or_split(较低, idx, tmin, tmax) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1384
def tuple_trim_or_split(lower, idx, tmin, tmax)
  if lower.first < tmin # split
    tuples.insert(idx, [lower.first, tmin - 1])
  end
  lower[0] = tmax + 1
end
tuples_add(tuples) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1323
def tuples_add(tuples)      tuples.each do tuple_add _1      end; self end
tuples_subtract(tuples) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1324
def tuples_subtract(tuples) tuples.each do tuple_subtract _1 end; self end
tuples_trim_or_delete(较低, lower_idx, tmin, tmax) 点击切换源代码
# File net-imap-0.5.4/lib/net/imap/sequence_set.rb, line 1391
def tuples_trim_or_delete(lower, lower_idx, tmin, tmax)
  if lower.first < tmin # trim lower
    lower[1] = tmin - 1
    lower_idx += 1
  end
  if tmax == lower.last                           # case 5
    upper_idx = lower_idx
  elsif (upper, upper_idx = tuple_gte_with_index(tmax + 1))
    upper_idx -= 1                                # cases 7 and 8
    upper[0] = tmax + 1 if upper.first <= tmax    # case 8 (else case 7)
  end
  tuples.slice!(lower_idx..upper_idx)
end