Skip to content

Commit 6f356e1

Browse files
committed
Proposal for buffer operators
1 parent a6413e8 commit 6f356e1

File tree

16 files changed

+641
-407
lines changed

16 files changed

+641
-407
lines changed

src/RunOpenCode/Component/Dataset/src/Collector/IterableCollector.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ final class IterableCollector implements \IteratorAggregate, CollectorInterface
2828
return $this->getIterator();
2929
}
3030
}
31-
31+
3232
/**
3333
* {@inheritdoc}
3434
*/
@@ -45,7 +45,7 @@ final class IterableCollector implements \IteratorAggregate, CollectorInterface
4545

4646
/**
4747
* Provides you with total number of iterated elements.
48-
*
48+
*
4949
* @var non-negative-int
5050
*/
5151
public private(set) int $count = 0;
@@ -73,4 +73,4 @@ public function getIterator(): \Traversable
7373
$this->count++;
7474
}
7575
}
76-
}
76+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RunOpenCode\Component\Dataset\Model;
6+
7+
/**
8+
* Buffer of iterated items from collection.
9+
*
10+
* @template-covariant TKey
11+
* @template-covariant TValue
12+
*
13+
* @phpstan-type ItemTuple = array{TKey, TValue}
14+
*
15+
* @implements \IteratorAggregate<TKey, TValue>
16+
*/
17+
final class Buffer implements \IteratorAggregate, \Countable
18+
{
19+
/**
20+
* Create new buffer.
21+
*
22+
* @param non-empty-list<ItemTuple> $items Items within buffer.
23+
*
24+
* @internal
25+
*/
26+
public function __construct(private array &$items)
27+
{
28+
// noop.
29+
}
30+
31+
/**
32+
* Get first item in buffer.
33+
*
34+
* @return Item<TKey, TValue>
35+
*
36+
* @phpstan-ignore-next-line generics.variance
37+
*/
38+
public function first(): Item
39+
{
40+
return new Item($this->items[0][0], $this->items[0][1]);
41+
}
42+
43+
/**
44+
* Get last item in buffer.
45+
*
46+
* @return Item<TKey, TValue>
47+
*
48+
* @phpstan-ignore-next-line generics.variance
49+
*/
50+
public function last(): Item
51+
{
52+
$last = $this->items[\count($this->items) - 1];
53+
54+
return new Item($last[0], $last[1]);
55+
}
56+
57+
/**
58+
* Get all keys.
59+
*
60+
* @return list<TKey>
61+
*/
62+
public function keys(): array
63+
{
64+
return \array_map(static fn(array $item): mixed => $item[0], $this->items);
65+
}
66+
67+
/**
68+
* Get all values.
69+
*
70+
* @return list<TValue>
71+
*/
72+
public function values(): array
73+
{
74+
return \array_map(static fn(array $item): mixed => $item[1], $this->items);
75+
}
76+
77+
/**
78+
* {@inheritdoc}
79+
*/
80+
public function getIterator(): \Traversable
81+
{
82+
foreach ($this->items as [$key, $value]) {
83+
yield $key => $value;
84+
}
85+
}
86+
87+
/**
88+
* {@inheritdoc}
89+
*/
90+
public function count(): int
91+
{
92+
return \count($this->items);
93+
}
94+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RunOpenCode\Component\Dataset\Model;
6+
7+
use RunOpenCode\Component\Dataset\Exception\OutOfBoundsException;
8+
9+
/**
10+
* @template TKey
11+
* @template TValue
12+
*
13+
* @implements \ArrayAccess<int, TKey|TValue>
14+
*/
15+
final readonly class Item implements \ArrayAccess
16+
{
17+
/**
18+
* @param TKey $key
19+
* @param TValue $value
20+
*/
21+
public function __construct(
22+
private mixed $key,
23+
private mixed $value
24+
) {
25+
// noop.
26+
}
27+
28+
/**
29+
* Get key.
30+
*
31+
* @return TKey
32+
*/
33+
public function key(): mixed
34+
{
35+
return $this->key;
36+
}
37+
38+
/**
39+
* Get value.
40+
*
41+
* @return TValue
42+
*/
43+
public function value(): mixed
44+
{
45+
return $this->value;
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
*/
51+
public function offsetExists(mixed $offset): bool
52+
{
53+
return $offset === 0 || $offset === 1;
54+
}
55+
56+
/**
57+
* {@inheritdoc}
58+
*
59+
* @return ($offset is 0 ? TKey : TValue)
60+
*/
61+
public function offsetGet(mixed $offset): mixed
62+
{
63+
return match ($offset) {
64+
0 => $this->key,
65+
1 => $this->value,
66+
default => throw new OutOfBoundsException($offset, $this, \sprintf(
67+
'Item tuple does not have offset "%s".',
68+
$offset
69+
)),
70+
};
71+
}
72+
73+
/**
74+
* {@inheritdoc}
75+
*/
76+
public function offsetSet(mixed $offset, mixed $value): void
77+
{
78+
throw new \BadMethodCallException('Item is immutable.');
79+
}
80+
81+
/**
82+
* {@inheritdoc}
83+
*/
84+
public function offsetUnset(mixed $offset): void
85+
{
86+
throw new \BadMethodCallException('Item is immutable.');
87+
}
88+
}

src/RunOpenCode/Component/Dataset/src/Operator/Batch.php

Lines changed: 0 additions & 94 deletions
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RunOpenCode\Component\Dataset\Operator;
6+
7+
use RunOpenCode\Component\Dataset\AbstractStream;
8+
use RunOpenCode\Component\Dataset\Contract\OperatorInterface;
9+
use RunOpenCode\Component\Dataset\Model\Buffer;
10+
11+
/**
12+
* Buffer count operator.
13+
*
14+
* Iterates over given collection and creates a buffer of items with number of items
15+
* up to given capacity.
16+
*
17+
* Yields created instances of {@see Buffer} for batch processing.
18+
*
19+
* @template TKey
20+
* @template TValue
21+
*
22+
* @extends AbstractStream<int, Buffer<TKey, TValue>>
23+
* @implements OperatorInterface<int, Buffer<TKey, TValue>>
24+
*/
25+
final class BufferCount extends AbstractStream implements OperatorInterface
26+
{
27+
/**
28+
* @param iterable<TKey, TValue> $collection Collection to iterate over.
29+
* @param positive-int $count How many items to buffer.
30+
*/
31+
public function __construct(
32+
private readonly iterable $collection,
33+
private readonly int $count = 1000,
34+
) {
35+
parent::__construct($collection);
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
protected function iterate(): \Traversable
42+
{
43+
$items = [];
44+
45+
foreach ($this->collection as $key => $value) {
46+
$items[] = [$key, $value];
47+
48+
if (\count($items) === $this->count) {
49+
yield new Buffer($items);
50+
$items = [];
51+
}
52+
}
53+
54+
if (\count($items) !== 0) {
55+
yield new Buffer($items);
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)