@@ -28,9 +28,9 @@ final class Iterator implements Countable, SeekableIterator
28
28
private array $ entries = [];
29
29
30
30
/**
31
- * Whether or not the current value/key pair has been added to the local entries.
31
+ * Whether or not the current value/key pair has been added to the local entries.
32
32
*/
33
- private bool $ saved = false ;
33
+ private bool $ saved = true ;
34
34
35
35
/**
36
36
* Current cursor position for the local entries.
@@ -79,7 +79,7 @@ public static function create(iterable $iterable): Iterator
79
79
/**
80
80
* @var (callable(): Generator<Tsk, Tsv, mixed, void>) $factory
81
81
*/
82
- $ factory = static fn (): Generator => yield from $ iterable ;
82
+ $ factory = static fn (): Generator => yield from $ iterable ;
83
83
84
84
return new self ($ factory ());
85
85
}
@@ -94,34 +94,34 @@ public static function create(iterable $iterable): Iterator
94
94
public function current (): mixed
95
95
{
96
96
Psl \invariant ($ this ->valid (), 'The Iterator is invalid. ' );
97
- if (!contains_key ($ this ->entries , $ this ->position )) {
98
- $ this ->progress ();
99
- }
97
+ $ this ->save ();
100
98
101
99
return $ this ->entries [$ this ->position ][1 ];
102
100
}
103
101
104
102
/**
105
- * Move forward to the next element .
103
+ * Checks if current position is valid .
106
104
*/
107
- public function next (): void
105
+ public function valid (): bool
108
106
{
109
- $ this ->position ++;
110
- if (null === $ this ->generator || !$ this ->generator ->valid ()) {
111
- return ;
107
+ if (isset ($ this ->entries [$ this ->position ])) {
108
+ return true ;
112
109
}
113
110
114
- if (contains_key ( $ this ->entries , $ this ->position + 1 )) {
115
- return ;
111
+ if (null !== $ this ->generator && $ this ->generator -> valid ( )) {
112
+ return true ;
116
113
}
117
114
118
- if (!$ this ->saved ) {
119
- $ this ->progress ();
120
- }
121
- $ this ->saved = false ;
122
- $ this ->generator ?->next();
115
+ $ this ->generator = null ;
116
+ return false ;
117
+ }
123
118
124
- $ this ->progress ();
119
+ private function save (): void
120
+ {
121
+ if (!$ this ->saved && $ this ->generator !== null ) {
122
+ $ this ->saved = true ;
123
+ $ this ->entries [] = [$ this ->generator ->key (), $ this ->generator ->current ()];
124
+ }
125
125
}
126
126
127
127
/**
@@ -134,34 +134,11 @@ public function next(): void
134
134
public function key (): mixed
135
135
{
136
136
Psl \invariant ($ this ->valid (), 'The Iterator is invalid. ' );
137
- if (!contains_key ($ this ->entries , $ this ->position )) {
138
- $ this ->progress ();
139
- }
137
+ $ this ->save ();
140
138
141
139
return $ this ->entries [$ this ->position ][0 ];
142
140
}
143
141
144
- /**
145
- * Checks if current position is valid.
146
- */
147
- public function valid (): bool
148
- {
149
- if (contains_key ($ this ->entries , $ this ->position )) {
150
- return true ;
151
- }
152
-
153
- if (null === $ this ->generator ) {
154
- return false ;
155
- }
156
-
157
- if ($ this ->generator ->valid ()) {
158
- return true ;
159
- }
160
-
161
- $ this ->generator = null ;
162
- return false ;
163
- }
164
-
165
142
/**
166
143
* Rewind the Iterator to the first element.
167
144
*/
@@ -179,16 +156,18 @@ public function rewind(): void
179
156
*/
180
157
public function seek (int $ position ): void
181
158
{
182
- if (0 === $ position || $ position <= $ this ->position ) {
159
+ if ($ position <= $ this ->position ) {
183
160
$ this ->position = $ position ;
184
161
return ;
185
162
}
186
163
187
164
if ($ this ->generator ) {
188
- while ($ this ->position !== $ position ) {
165
+ do {
166
+ $ this ->save ();
189
167
$ this ->next ();
190
- Psl \invariant ($ this ->valid (), 'Position is out-of-bounds. ' );
191
- }
168
+ /** @psalm-suppress PossiblyNullReference - ->next() and ->save() don't mutate ->generator. */
169
+ Psl \invariant ($ this ->generator ->valid (), 'Position is out-of-bounds. ' );
170
+ } while ($ this ->position < $ position );
192
171
193
172
return ;
194
173
}
@@ -199,43 +178,39 @@ public function seek(int $position): void
199
178
}
200
179
201
180
/**
202
- * @return 0|positive-int
203
- *
204
- * @psalm-suppress MoreSpecificReturnType
181
+ * Move forward to the next element.
205
182
*/
206
- public function count (): int
183
+ public function next (): void
207
184
{
208
- if ($ this ->generator ) {
209
- $ this ->exhaust ();
185
+ $ this ->position ++;
186
+
187
+ if (isset ($ this ->entries [$ this ->position ]) || null === $ this ->generator || !$ this ->generator ->valid ()) {
188
+ return ;
210
189
}
211
190
212
- /**
213
- * @psalm-suppress LessSpecificReturnStatement
214
- */
215
- return count ($ this ->entries );
191
+ $ this ->generator ->next ();
192
+ $ this ->saved = false ;
216
193
}
217
194
218
- private function exhaust (): void
195
+ /**
196
+ * @return int<0, max>
197
+ *
198
+ * @psalm-suppress PossiblyNullReference
199
+ */
200
+ public function count (): int
219
201
{
220
202
if ($ this ->generator ) {
221
- if ($ this ->generator ->valid ()) {
222
- foreach ($ this ->generator as $ key => $ value ) {
223
- $ this ->entries [] = [$ key , $ value ];
224
- }
225
- }
203
+ $ previous = $ this ->position ;
204
+ do {
205
+ $ this ->save ();
206
+ $ this ->next ();
207
+ } while ($ this ->generator ->valid ());
208
+ $ this ->position = $ previous ;
226
209
227
210
$ this ->generator = null ;
228
211
}
229
- }
230
212
231
- /**
232
- * Save the current key and value to the local entries if the generator is still valid.
233
- */
234
- private function progress (): void
235
- {
236
- if ($ this ->generator && $ this ->generator ->valid () && !$ this ->saved ) {
237
- $ this ->entries [] = [$ this ->generator ->key (), $ this ->generator ->current ()];
238
- $ this ->saved = true ;
239
- }
213
+ /** @var int<0, max> */
214
+ return count ($ this ->entries );
240
215
}
241
216
}
0 commit comments