Skip to content

Commit a27c5a0

Browse files
committed
dirty generator
1 parent 78beb83 commit a27c5a0

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

src/Helper/WindowIterator.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class WindowIterator implements Iterator
5050

5151
/**
5252
* @param Iterator<TKey, TValue> $inner
53-
* @param int|null $maxSize Maximum buffer size (null = unlimited)
53+
* @param int<1, max>|null $maxSize Maximum buffer size (null = unlimited)
5454
*/
5555
public function __construct(
5656
private readonly Iterator $inner,
@@ -123,6 +123,13 @@ private function initialize(): void
123123
}
124124
$this->initialized = true;
125125

126+
// If inner is already pointing at data (e.g. a started generator), capture it
127+
if ($this->inner->valid()) {
128+
$this->pushFromInner();
129+
130+
return;
131+
}
132+
126133
$this->fetch(rewind: true);
127134
}
128135

@@ -139,6 +146,11 @@ private function fetch(bool $rewind = false): void
139146
return;
140147
}
141148

149+
$this->pushFromInner();
150+
}
151+
152+
private function pushFromInner(): void
153+
{
142154
$this->buffer->push([$this->inner->key(), $this->inner->current()]);
143155
}
144156
}

src/Standard.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ public function cursor(): Iterator
691691
*
692692
* With a size limit, oldest elements are dropped (sliding window).
693693
*
694-
* @param int|null $size Maximum buffer size (null = unlimited)
694+
* @param int<1, max>|null $size Maximum buffer size (null = unlimited)
695695
* @return Iterator<TKey, TValue>
696696
*/
697697
public function window(?int $size = null): Iterator

tests/WindowTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,32 @@ public function valid(): bool
408408
$window->next();
409409
$this->assertSame(0, $nextCalls);
410410
}
411+
412+
public function testWindowWithStartedGenerator(): void
413+
{
414+
$generator = (function () {
415+
yield 1;
416+
yield 2;
417+
yield 3;
418+
})();
419+
420+
// Advance the generator - it's now "dirty"
421+
$generator->next();
422+
$this->assertSame(2, $generator->current());
423+
424+
// Wrapping in WindowIterator should not throw "Cannot rewind a generator"
425+
$window = new WindowIterator($generator);
426+
427+
// Should capture current element (2) and continue
428+
$collected = [];
429+
foreach ($window as $value) {
430+
$collected[] = $value;
431+
}
432+
433+
$this->assertSame([2, 3], $collected);
434+
435+
// Can rewind and replay
436+
$window->rewind();
437+
$this->assertSame([2, 3], take($window)->toList());
438+
}
411439
}

0 commit comments

Comments
 (0)