forked from voku/Arrayy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathArrayyRewindableGenerator.php
More file actions
131 lines (117 loc) · 2.82 KB
/
ArrayyRewindableGenerator.php
File metadata and controls
131 lines (117 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<?php
declare(strict_types=1);
namespace Arrayy;
/**
* @template XKey of array-key
* @template X
* @implements \Iterator<XKey,X>
*
* @internal
*/
final class ArrayyRewindableGenerator implements \Iterator
{
/**
* @var callable
*/
private $generatorFunction;
/**
* @var \Generator
*
* @psalm-var \Generator<XKey,X>
*/
private $generator;
/**
* @var callable|null
*/
private $onRewind;
/**
* @param callable $generatorConstructionFunction A callable that should return a Generator
* @param callable $onRewind callable that gets invoked with 0 arguments after the iterator
* was rewinded
*
* @throws \InvalidArgumentException
*/
public function __construct(callable $generatorConstructionFunction, callable $onRewind = null)
{
$this->generatorFunction = $generatorConstructionFunction;
$this->onRewind = $onRewind;
$this->generateGenerator();
}
/**
* Return the current element.
*
* @return mixed
*
* @see http://php.net/manual/en/iterator.current.php
* @see Iterator::current
*
* @psalm-return X
*/
public function current()
{
return $this->generator->current();
}
/**
* Return the key of the current element.
*
* @return mixed scalar on success, or null on failure
*
* @see http://php.net/manual/en/iterator.key.php
* @see Iterator::key
*
* @psalm-return XKey
*/
public function key()
{
return $this->generator->key();
}
/**
* Move forward to next element.
*
* @return void
*
* @see http://php.net/manual/en/iterator.next.php
* @see Iterator::next
*/
public function next()
{
$this->generator->next();
}
/**
* Rewind the Iterator to the first element.
*
* @return void
*
* @see http://php.net/manual/en/iterator.rewind.php
* @see Iterator::rewind
*/
public function rewind()
{
$this->generateGenerator();
if (\is_callable($this->onRewind)) {
\call_user_func($this->onRewind);
}
}
/**
* Checks if current position is valid.
*
* @return bool
*
* @see http://php.net/manual/en/iterator.valid.php
* @see Iterator::rewind
*/
public function valid(): bool
{
return $this->generator->valid();
}
/**
* @return void
*/
private function generateGenerator()
{
$this->generator = \call_user_func($this->generatorFunction);
if (!($this->generator instanceof \Generator)) {
throw new \InvalidArgumentException('The callable needs to return a Generator');
}
}
}