Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
SlidingWindowIteratorIterator
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
6 / 6
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 next
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 current
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 key
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 valid
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rewind
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5/**
6 * This file is part of php-fast-forward/iterators.
7 *
8 * This source file is subject to the license that is bundled
9 * with this source code in the file LICENSE.
10 *
11 * @copyright Copyright (c) 2025-2026 Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
12 * @license   https://opensource.org/licenses/MIT MIT License
13 *
14 * @see       https://github.com/php-fast-forward/iterators
15 * @see       https://github.com/php-fast-forward
16 * @see       https://datatracker.ietf.org/doc/html/rfc2119
17 */
18
19namespace FastForward\Iterator;
20
21use InvalidArgumentException;
22
23/**
24 * Provides a sliding window over an iterator with sequential keys.
25 *
26 * This iterator returns overlapping windows of elements with keys
27 * starting from `0` and incrementing sequentially.
28 *
29 * @since 1.0.0
30 */
31class SlidingWindowIteratorIterator extends CountableIteratorIterator
32{
33    /**
34     * @var int the fixed size of each sliding window
35     */
36    private  int $windowSize;
37
38    /**
39     * @var array<int, mixed> the buffer holding the current window of elements
40     */
41    private array $window = [];
42
43    /**
44     * @var int the current sequential key for the iterator
45     */
46    private int $key = 0;
47
48    /**
49     * Initializes the SlidingWindowIteratorIterator.
50     *
51     * @param iterable $iterator the iterator containing values
52     * @param int $windowSize the number of elements per window (must be >= 1)
53     *
54     * @throws InvalidArgumentException if $windowSize is less than 1
55     */
56    public function __construct(iterable $iterator, int $windowSize)
57    {
58        if ($windowSize < 1) {
59            throw new InvalidArgumentException('Window size must be at least 1.');
60        }
61
62        parent::__construct(new IterableIterator($iterator));
63        $this->windowSize = $windowSize;
64    }
65
66    /**
67     * Advances to the next element, maintaining the sliding window.
68     *
69     * @return void
70     */
71    public function next(): void
72    {
73        array_shift($this->window);
74
75        if (parent::valid()) {
76            $this->window[] = parent::current();
77            parent::next();
78        }
79
80        ++$this->key;
81    }
82
83    /**
84     * Retrieves the current sliding window of elements.
85     *
86     * @return array<int, mixed> the current window of elements
87     */
88    public function current(): array
89    {
90        return $this->window;
91    }
92
93    /**
94     * Returns the current sequential key.
95     *
96     * @return int the current key, starting from 0
97     */
98    public function key(): int
99    {
100        return $this->key;
101    }
102
103    /**
104     * Determines whether the current window is valid.
105     *
106     * The iterator continues filling the window until the required size is met.
107     * If fewer elements than the window size exist, iteration stops.
108     *
109     * @return bool true if a valid window exists, false otherwise
110     */
111    public function valid(): bool
112    {
113        return \count($this->window) === $this->windowSize;
114    }
115
116    /**
117     * Resets the iterator, allowing re-iteration.
118     *
119     * @return void
120     */
121    public function rewind(): void
122    {
123        parent::rewind();
124
125        $this->window = [];
126        $this->key    = 0;
127
128        while (parent::valid() && \count($this->window) < $this->windowSize) {
129            $this->window[] = parent::current();
130            parent::next();
131        }
132    }
133}