Skip to content

Commit

Permalink
feat: Add PausableIteratorAggregate.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Dec 20, 2021
1 parent b0eed19 commit a806dcc
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/Contract/PausableIteratorAggregateInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace loophp\iterators\Contract;

use IteratorAggregate;
use Traversable;

/**
* @template TKey
* @template T
*
* @extends IteratorAggregate<TKey, T>
*/
interface PausableIteratorAggregateInterface extends IteratorAggregate
{
/**
* @return Traversable<TKey, T>
*/
public function rest(): Traversable;
}
66 changes: 66 additions & 0 deletions src/PausableIteratorAggregate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/**
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace loophp\iterators;

use ArrayIterator;
use Iterator;
use IteratorAggregate;
use loophp\iterators\Contract\PausableIteratorAggregateInterface;
use Traversable;

/**
* @template TKey
* @template T
*
* @implements IteratorAggregate<TKey, T>
*/
final class PausableIteratorAggregate implements PausableIteratorAggregateInterface
{
/**
* @var Iterator<TKey, T>
*/
private Iterator $iterator;

/**
* @var IteratorAggregate<TKey, T>
*/
private IteratorAggregate $iteratorAggregate;

/**
* @param Iterator<TKey, T> $iterator
*/
public function __construct(Iterator $iterator)
{
$this->iteratorAggregate = new CachingIteratorAggregate($iterator);
$this->iterator = new ArrayIterator();
}

/**
* @return Traversable<TKey, T>
*/
public function getIterator(): Traversable
{
$this->iterator = $this->iteratorAggregate->getIterator();

yield from $this->iterator;
}

/**
* @return Traversable<TKey, T>
*/
public function rest(): Traversable
{
$this->iterator->next();

for (; $this->iterator->valid(); $this->iterator->next()) {
yield $this->iterator->key() => $this->iterator->current();
}
}
}
116 changes: 116 additions & 0 deletions tests/unit/PausableIteratorAggregateTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

/**
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace tests\loophp\iterators;

use Generator;
use loophp\iterators\PausableIteratorAggregate;
use PHPUnit\Framework\TestCase;

/**
* @internal
* @coversDefaultClass \loophp\iterators
*/
final class PausableIteratorAggregateTest extends TestCase
{
public function testGetRest(): void
{
$input = static function (): Generator {
yield from range('a', 'e');
};

$iterator = (new PausableIteratorAggregate($input()));

$a = $r = [];
$i = 0;

foreach ($iterator->rest() as $key => $value) {
$r[] = [$key, $value];
}

self::assertEmpty($r);

foreach ($iterator as $key => $value) {
$a[] = [$key, $value];

if (2 === $i++) {
break;
}
}

foreach ($iterator->rest() as $key => $value) {
$a[] = [$key, $value];
}

foreach ($iterator as $key => $value) {
$a[] = [$key, $value];
}

$expected = [
[0, 'a'],
[1, 'b'],
[2, 'c'],
[3, 'd'],
[4, 'e'],
[0, 'a'],
[1, 'b'],
[2, 'c'],
[3, 'd'],
[4, 'e'],
];

self::assertEquals($expected, $a);
}

public function testSimple(): void
{
$input = static function (): Generator {
yield from range('a', 'e');
};

$iterator = (new PausableIteratorAggregate($input()));

$a = $b = [];
$i = 0;

foreach ($iterator as $key => $value) {
$a[] = [$key, $value];

if (2 === $i++) {
break;
}
}

foreach ($iterator as $key => $value) {
$a[] = [$key, $value];
}

foreach ($iterator as $key => $value) {
$a[] = [$key, $value];
}

$expected = [
[0, 'a'],
[1, 'b'],
[2, 'c'],
[0, 'a'],
[1, 'b'],
[2, 'c'],
[3, 'd'],
[4, 'e'],
[0, 'a'],
[1, 'b'],
[2, 'c'],
[3, 'd'],
[4, 'e'],
];

self::assertEquals($expected, $a);
}
}

0 comments on commit a806dcc

Please sign in to comment.