Skip to content

Instantly share code, notes, and snippets.

@drupol
Last active December 9, 2020 13:01
Show Gist options
  • Select an option

  • Save drupol/520071fcfe971b48a78f8ce53ca58bf1 to your computer and use it in GitHub Desktop.

Select an option

Save drupol/520071fcfe971b48a78f8ce53ca58bf1 to your computer and use it in GitHub Desktop.
Stream Iterator oddity
<?php
declare(strict_types=1);
namespace App;
use Generator;
use Iterator;
class ClosureIterator implements \Iterator
{
/**
* @var array<int, mixed>
*/
private array $arguments;
/**
* @var callable
*/
private $callable;
public function __construct(callable $callable, ...$arguments)
{
$this->callable = $callable;
$this->arguments = $arguments;
$this->iterator = $this->getGenerator();
}
protected \Iterator $iterator;
public function current()
{
return $this->iterator->current();
}
public function key()
{
return $this->iterator->key();
}
public function next(): void
{
$this->iterator->next();
}
public function valid(): bool
{
return $this->iterator->valid();
}
public function rewind(): void
{
$this->iterator = $this->getGenerator();
}
private function getGenerator(): Generator
{
$generator = static fn (callable $callable, array $arguments): \Generator => yield from ($callable)(...$arguments);
return ($generator)($this->callable, $this->arguments);
}
}
$string = 'Lorem ipsum dolor sit amet';
$stream = fopen('data://text/plain,' . $string, 'rb');
$callable = static function ($resource): \Generator {
while (false !== $chunk = fgetc($resource)) {
yield $chunk;
}
};
// Test 1
$closureIterator = new ClosureIterator($callable, $stream);
$string1 = implode('', iterator_to_array($closureIterator)); // 'Lorem ipsum dolor sit amet'
// Test 2
$closureIterator = new ClosureIterator($callable, $stream);
$closureIterator->valid();
$string2 = implode('', iterator_to_array($closureIterator)); // 'orem ipsum dolor sit amet' <- Missing first letter! Why ?
var_dump($string1 === $string2); // false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment