Files
provider_imap/lib/Client/Protocol/Command/Argument/SequenceSet.php
Sebastian Krupinski 7446edced3 feat: speed improvements
Signed-off-by: Sebastian Krupinski <root@LAPTOP-7DVOR6NC>
2026-02-20 23:34:30 -05:00

86 lines
2.0 KiB
PHP

<?php
declare(strict_types=1);
namespace Gricob\IMAP\Protocol\Command\Argument;
final class SequenceSet implements Argument
{
/**
* @var array<int>
*/
private array $numbers;
private ?string $range;
public function __construct(int ...$numbers)
{
$this->numbers = $numbers;
$this->range = null;
}
public static function range(int $from, int $to): self
{
$set = new self();
$set->range = $from . ':' . $to;
return $set;
}
/**
* Build a SequenceSet that matches every message in the mailbox (1:*).
*/
public static function all(): self
{
$set = new self();
$set->range = '1:*';
return $set;
}
/**
* Build a SequenceSet from a flat array of UIDs, collapsing consecutive
* values into n:m ranges.
*
* Examples:
* [1, 2, 3, 5, 6, 10] → "1:3,5:6,10"
* [42] → "42"
* [7, 3, 4, 5] → "3:5,7"
*
* @param int[] $uids
*/
public static function list(array $uids): self
{
if (empty($uids)) {
return new self();
}
$uids = array_unique($uids);
sort($uids);
$ranges = [];
$start = $end = $uids[0];
for ($i = 1, $count = count($uids); $i <= $count; $i++) {
$current = $uids[$i] ?? null;
if ($current !== null && $current === $end + 1) {
$end = $current;
} else {
$ranges[] = $start === $end ? (string) $start : $start . ':' . $end;
if ($current !== null) {
$start = $end = $current;
}
}
}
$set = new self();
$set->range = implode(',', $ranges);
return $set;
}
public function __toString(): string
{
if ($this->range !== null) {
return $this->range;
}
return implode(',', $this->numbers);
}
}