Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.56% covered (success)
97.56%
40 / 41
90.00% covered (success)
90.00%
9 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Vector
97.56% covered (success)
97.56%
40 / 41
90.00% covered (success)
90.00%
9 / 10
21
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 create
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
2.02
 empty
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 throwIfInvalidOffset
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 add
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 addRange
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 offsetExists
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 offsetGet
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 offsetSet
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 offsetUnset
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace PeServer\Core\Collection;
6
7use TypeError;
8use PeServer\Core\Collection\Arr;
9use PeServer\Core\Throws\ArgumentException;
10use PeServer\Core\Throws\IndexOutOfRangeException;
11use PeServer\Core\TypeUtility;
12
13/**
14 * 一次元配列。
15 *
16 * @template TValue
17 * @phpstan-extends TypeArrayBase<non-negative-int,TValue>
18 */
19class Vector extends TypeArrayBase
20{
21    /**
22     * 生成。
23     *
24     * @param string $type
25     * @phpstan-param class-string|TypeUtility::TYPE_* $type
26     * @param array $items
27     * @phpstan-param array<array-key,TValue> $items
28     * @param bool $useValues
29     */
30    public function __construct(string $type, ?array $items, bool $useValues)
31    {
32        parent::__construct($type);
33
34        if (!Arr::isNullOrEmpty($items)) {
35            $this->addRange($items, $useValues);
36        }
37    }
38
39    #region function
40
41    /**
42     * 配列から生成。
43     *
44     * @template TTValue
45     * @param array $items 配列。
46     * @phpstan-param non-empty-array<TTValue> $items
47     * @param bool $useValues
48     * @return self
49     * @phpstan-return self<TTValue>
50     */
51    public static function create(array $items, bool $useValues = true): self
52    {
53        if (Arr::isNullOrEmpty($items)) { //@phpstan-ignore-line [DOCTYPE]
54            throw new ArgumentException('$items');
55        }
56
57        $firstKey = Arr::getFirstKey($items);
58        $firstValue = $items[$firstKey];
59
60        $type = TypeUtility::getType($firstValue);
61        return new self($type, $items, $useValues);
62    }
63
64    /**
65     * 空データの生成。
66     *
67     * @template TTValue
68     * @param string $type
69     * @phpstan-param class-string|TypeUtility::TYPE_* $type
70     * @return self
71     * @phpstan-return self<TTValue>
72     */
73    public static function empty(string $type): self //@phpstan-ignore-line わかんね
74    {
75        return new self($type, [], false);
76    }
77
78    protected function throwIfInvalidOffset(mixed $offset): void
79    {
80        if ($offset === null) {
81            throw new TypeError('$offset: null');
82        }
83
84        if (!is_int($offset)) {
85            throw new TypeError('$offset: ' . gettype($offset));
86        }
87    }
88
89    /**
90     * 追加。
91     *
92     * @param mixed $value
93     * @phpstan-param TValue $value
94     * @return self
95     * @phpstan-return self<TValue>
96     */
97    public function add(mixed $value): self
98    {
99        $this->isValidType($value);
100
101        $this->items[] = $value;
102
103        return $this;
104    }
105
106    /**
107     * 追加。
108     *
109     * @param array $items
110     * @phpstan-param array<array-key,TValue> $items
111     * @param bool $useValues
112     * @phpstan-return self<TValue>
113     */
114    public function addRange(array $items, bool $useValues = true): self
115    {
116        if ($useValues) {
117            $items = Arr::getValues($items);
118        } elseif (!Arr::isList($items)) {
119            throw new ArgumentException('$items');
120        }
121
122        foreach ($items as $key => $value) {
123            $this->isValidType($value);
124        }
125
126        /** @phpstan-var array<non-negative-int,TValue> $items */
127        $this->items = array_merge($this->items, $items);
128
129        return $this;
130    }
131
132    #endregion
133
134    #region TypeArrayBase
135
136    /**
137     * @param int $offset
138     * @phpstan-param non-negative-int $offset
139     */
140    public function offsetExists(mixed $offset): bool
141    {
142        $this->throwIfInvalidOffset($offset);
143
144        return isset($this->items[$offset]);
145    }
146    /**
147     * @param int $offset
148     * @phpstan-param non-negative-int $offset
149     * @phpstan-return TValue $value
150     */
151    public function offsetGet(mixed $offset): mixed
152    {
153        $this->throwIfInvalidOffset($offset);
154
155        if (!isset($this->items[$offset])) {
156            throw new IndexOutOfRangeException('$offset: ' . $offset);
157        }
158
159        return $this->items[$offset];
160    }
161    /**
162     * @param int|null $offset
163     * @phpstan-param non-negative-int|null $offset
164     * @phpstan-param TValue $value
165     * @throws IndexOutOfRangeException
166     */
167    public function offsetSet(mixed $offset, mixed $value): void
168    {
169        if ($offset === null) {
170            $this->add($value);
171            return;
172        }
173
174        if (!isset($this->items[$offset])) {
175            throw new IndexOutOfRangeException('$offset: ' . $offset);
176        }
177
178        $this->items[$offset] = $value;
179    }
180    /**
181     * @param int $offset
182     * @phpstan-param non-negative-int $offset
183     */
184    public function offsetUnset(mixed $offset): void
185    {
186        $this->throwIfInvalidOffset($offset);
187
188        if ($offset !== $this->count() - 1) {
189            throw new IndexOutOfRangeException('$offset: ' . $offset);
190        }
191
192        unset($this->items[$offset]);
193    }
194
195    #endregion
196}