Skip to content

Commit 9ad0522

Browse files
committed
EnumMap: implement IteratorAggregate (instead of SeekableIterator) using Generator
1 parent 976d40c commit 9ad0522

File tree

3 files changed

+113
-186
lines changed

3 files changed

+113
-186
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ $enumSet = $enumSet->withSymDiff($other); // Enumerators in either this and ot
304304

305305
An `EnumMap` maps enumerators of the same type to data assigned to.
306306

307-
It implements `ArrayAccess`, `Countable` and `SeekableIterator`
307+
It implements `ArrayAccess`, `Countable` and `IteratorAggregate`
308308
so elements can be accessed, iterated and counted like a normal array
309309
using `$enumMap[$key]`, `foreach` and `count()`.
310310

src/EnumMap.php

Lines changed: 15 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
use ArrayAccess;
88
use Countable;
99
use InvalidArgumentException;
10-
use OutOfBoundsException;
11-
use SeekableIterator;
12-
use TypeError;
10+
use Iterator;
11+
use IteratorAggregate;
1312
use UnexpectedValueException;
1413

1514
/**
@@ -19,7 +18,7 @@
1918
* @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
2019
* @link http://github.com/marc-mabe/php-enum for the canonical source repository
2120
*/
22-
class EnumMap implements ArrayAccess, Countable, SeekableIterator
21+
class EnumMap implements ArrayAccess, Countable, IteratorAggregate
2322
{
2423
/**
2524
* The classname of the enumeration type
@@ -33,18 +32,6 @@ class EnumMap implements ArrayAccess, Countable, SeekableIterator
3332
*/
3433
private $map = [];
3534

36-
/**
37-
* List of ordinal numbers
38-
* @var int[]
39-
*/
40-
private $ordinals = [];
41-
42-
/**
43-
* Current iterator position
44-
* @var int
45-
*/
46-
private $pos = 0;
47-
4835
/**
4936
* Constructor
5037
* @param string $enumeration The classname of the enumeration type
@@ -77,7 +64,7 @@ public function getEnumeration(): string
7764
*/
7865
public function getKeys(): array
7966
{
80-
return \array_map([$this->enumeration, 'byOrdinal'], $this->ordinals);
67+
return \array_map([$this->enumeration, 'byOrdinal'], \array_keys($this->map));
8168
}
8269

8370
/**
@@ -115,7 +102,7 @@ public function contains($enumerator): bool
115102
{
116103
try {
117104
$ord = ($this->enumeration)::get($enumerator)->getOrdinal();
118-
return array_key_exists($ord, $this->map);
105+
return \array_key_exists($ord, $this->map);
119106
} catch (InvalidArgumentException $e) {
120107
// An invalid enumerator can't be contained in this map
121108
return false;
@@ -149,7 +136,7 @@ public function offsetGet($enumerator)
149136
{
150137
$enumerator = ($this->enumeration)::get($enumerator);
151138
$ord = $enumerator->getOrdinal();
152-
if (!isset($this->map[$ord]) && !array_key_exists($ord, $this->map)) {
139+
if (!isset($this->map[$ord]) && !\array_key_exists($ord, $this->map)) {
153140
throw new UnexpectedValueException(sprintf(
154141
'Enumerator %s could not be found',
155142
\var_export($enumerator->getValue(), true)
@@ -170,10 +157,6 @@ public function offsetGet($enumerator)
170157
public function offsetSet($enumerator, $value = null): void
171158
{
172159
$ord = ($this->enumeration)::get($enumerator)->getOrdinal();
173-
174-
if (!array_key_exists($ord, $this->map)) {
175-
$this->ordinals[] = $ord;
176-
}
177160
$this->map[$ord] = $value;
178161
}
179162

@@ -187,86 +170,20 @@ public function offsetSet($enumerator, $value = null): void
187170
public function offsetUnset($enumerator): void
188171
{
189172
$ord = ($this->enumeration)::get($enumerator)->getOrdinal();
190-
191-
if (($idx = \array_search($ord, $this->ordinals, true)) !== false) {
192-
unset($this->map[$ord], $this->ordinals[$idx]);
193-
$this->ordinals = \array_values($this->ordinals);
194-
}
195-
}
196-
197-
/**
198-
* Seeks to the given iterator position.
199-
* @param int $pos
200-
* @throws OutOfBoundsException On an invalid position
201-
*/
202-
public function seek($pos): void
203-
{
204-
if (!is_int($pos)) {
205-
throw new TypeError(\sprintf(
206-
'Argument 1 passed to %s() must be of the type int, %s given',
207-
__METHOD__,
208-
gettype($pos)
209-
));
210-
}
211-
212-
if (!isset($this->ordinals[$pos])) {
213-
throw new OutOfBoundsException("Position {$pos} not found");
214-
}
215-
216-
$this->pos = $pos;
217-
}
218-
219-
/**
220-
* Get the current value
221-
* @return mixed
222-
*/
223-
public function current()
224-
{
225-
if (!isset($this->ordinals[$this->pos])) {
226-
return null;
227-
}
228-
229-
return $this->map[$this->ordinals[$this->pos]];
173+
unset($this->map[$ord]);
230174
}
231175

232176
/**
233-
* Get the current key
234-
* @return Enum|null
177+
* Get a new Iterator.
178+
*
179+
* @return Iterator
235180
*/
236-
public function key(): ?Enum
181+
public function getIterator(): Iterator
237182
{
238-
if (!isset($this->ordinals[$this->pos])) {
239-
return null;
183+
$map = $this->map;
184+
foreach ($map as $ordinal => $value) {
185+
yield ($this->enumeration)::byOrdinal($ordinal) => $value;
240186
}
241-
242-
return ($this->enumeration)::byOrdinal($this->ordinals[$this->pos]);
243-
}
244-
245-
/**
246-
* Reset the iterator position to zero.
247-
* @return void
248-
*/
249-
public function rewind(): void
250-
{
251-
$this->pos = 0;
252-
}
253-
254-
/**
255-
* Increment the iterator position by one.
256-
* @return void
257-
*/
258-
public function next(): void
259-
{
260-
++$this->pos;
261-
}
262-
263-
/**
264-
* Test if the iterator is in a valid state
265-
* @return bool
266-
*/
267-
public function valid(): bool
268-
{
269-
return isset($this->ordinals[$this->pos]);
270187
}
271188

272189
/**
@@ -276,6 +193,6 @@ public function valid(): bool
276193
*/
277194
public function count(): int
278195
{
279-
return \count($this->ordinals);
196+
return \count($this->map);
280197
}
281198
}

0 commit comments

Comments
 (0)