14
14
use function count ;
15
15
use function implode ;
16
16
use function is_array ;
17
+ use function is_int ;
17
18
use function is_iterable ;
18
19
use function is_string ;
19
20
@@ -90,15 +91,14 @@ public static function fromAssociative(iterable $members): self
90
91
*/
91
92
public static function fromPairs (iterable $ pairs ): self
92
93
{
93
- if ($ pairs instanceof MemberOrderedMap) {
94
- return new self ($ pairs );
95
- }
96
-
97
- return new self ((function (iterable $ pairs ) {
98
- foreach ($ pairs as [$ key , $ member ]) {
99
- yield $ key => $ member ;
100
- }
101
- })($ pairs ));
94
+ return match (true ) {
95
+ $ pairs instanceof MemberOrderedMap => new self ($ pairs ),
96
+ default => new self ((function (iterable $ pairs ) {
97
+ foreach ($ pairs as [$ key , $ member ]) {
98
+ yield $ key => $ member ;
99
+ }
100
+ })($ pairs )),
101
+ };
102
102
}
103
103
104
104
/**
@@ -110,18 +110,15 @@ public static function fromPairs(iterable $pairs): self
110
110
*/
111
111
public static function fromHttpValue (Stringable |string $ httpValue ): self
112
112
{
113
- return new self (( function ( iterable $ members ) {
114
- foreach ( $ members as $ key => $ member ) {
115
- if (! is_array ( $ member [0 ])) {
116
- yield $ key => Item:: fromAssociative (... $ member);
117
-
118
- continue ;
119
- }
113
+ $ converter = fn ( array $ member ): InnerList | Item => match ( true ) {
114
+ is_array ( $ member [ 0 ]) => InnerList:: fromAssociative (
115
+ array_map ( fn ( array $ item ) => Item:: fromAssociative (... $ item ), $ member [0 ]),
116
+ $ member[ 1 ]
117
+ ),
118
+ default => Item:: fromAssociative ( $ member [ 0 ], $ member [ 1 ]),
119
+ };
120
120
121
- $ member [0 ] = array_map (fn (array $ item ) => Item::fromAssociative (...$ item ), $ member [0 ]);
122
- yield $ key => InnerList::fromAssociative (...$ member );
123
- }
124
- })(Parser::parseDictionary ($ httpValue )));
121
+ return new self (array_map ($ converter , Parser::parseDictionary ($ httpValue )));
125
122
}
126
123
127
124
public function toHttpValue (): string
@@ -163,7 +160,7 @@ public function getIterator(): Iterator
163
160
}
164
161
165
162
/**
166
- * @return Iterator<array{0:string, 1:SfMember}>
163
+ * @return Iterator<int, array{0:string, 1:SfMember}>
167
164
*/
168
165
public function toPairs (): Iterator
169
166
{
@@ -199,17 +196,14 @@ public function has(string|int ...$keys): bool
199
196
*/
200
197
public function get (string |int $ key ): StructuredField
201
198
{
202
- if (!$ this ->has ($ key )) {
203
- throw InvalidOffset::dueToKeyNotFound ($ key );
204
- }
205
-
206
- return $ this ->members [$ key ];
199
+ return $ this ->members [$ key ] ?? throw InvalidOffset::dueToKeyNotFound ($ key );
207
200
}
208
201
209
202
public function hasPair (int ...$ indexes ): bool
210
203
{
204
+ $ max = count ($ this ->members );
211
205
foreach ($ indexes as $ index ) {
212
- if (null === $ this ->filterIndex ($ index )) {
206
+ if (null === $ this ->filterIndex ($ index, $ max )) {
213
207
return false ;
214
208
}
215
209
}
@@ -220,12 +214,14 @@ public function hasPair(int ...$indexes): bool
220
214
/**
221
215
* Filters and format instance index.
222
216
*/
223
- private function filterIndex (int $ index ): int |null
217
+ private function filterIndex (int $ index, int | null $ max = null ): int |null
224
218
{
225
- $ max = count ($ this ->members );
219
+ $ max ?? = count ($ this ->members );
226
220
227
221
return match (true ) {
228
- [] === $ this ->members , 0 > $ max + $ index , 0 > $ max - $ index - 1 => null ,
222
+ [] === $ this ->members ,
223
+ 0 > $ max + $ index ,
224
+ 0 > $ max - $ index - 1 => null ,
229
225
0 > $ index => $ max + $ index ,
230
226
default => $ index ,
231
227
};
@@ -238,10 +234,7 @@ private function filterIndex(int $index): int|null
238
234
*/
239
235
public function pair (int $ index ): array
240
236
{
241
- $ offset = $ this ->filterIndex ($ index );
242
- if (null === $ offset ) {
243
- throw InvalidOffset::dueToIndexNotFound ($ index );
244
- }
237
+ $ offset = $ this ->filterIndex ($ index ) ?? throw InvalidOffset::dueToIndexNotFound ($ index );
245
238
246
239
return [...$ this ->toPairs ()][$ offset ];
247
240
}
@@ -262,29 +255,39 @@ public function add(string $key, iterable|StructuredField|Token|ByteSequence|Dat
262
255
*/
263
256
private function newInstance (array $ members ): self
264
257
{
265
- if ($ members == $ this ->members ) {
266
- return $ this ;
267
- }
268
-
269
- return new self ($ members );
258
+ return match (true ) {
259
+ $ members == $ this ->members => $ this ,
260
+ default => new self ($ members ),
261
+ };
270
262
}
271
263
272
264
public function remove (string |int ...$ keys ): static
273
265
{
274
- /** @var array<array-key, true> $indexes */
275
- $ indexes = array_fill_keys ($ keys , true );
276
- $ pairs = [];
277
- foreach ($ this ->toPairs () as $ index => $ pair ) {
278
- if (!isset ($ indexes [$ index ]) && !isset ($ indexes [$ pair [0 ]])) {
279
- $ pairs [] = $ pair ;
280
- }
281
- }
282
-
283
- if (count ($ this ->members ) === count ($ pairs )) {
266
+ if ([] === $ this ->members || [] === $ keys ) {
284
267
return $ this ;
285
268
}
286
269
287
- return self ::fromPairs ($ pairs );
270
+ $ offsets = array_keys ($ this ->members );
271
+ $ max = count ($ offsets );
272
+ $ reducer = fn (array $ carry , string |int $ key ): array => match (true ) {
273
+ is_string ($ key ) && (false !== ($ position = array_search ($ key , $ offsets , true ))),
274
+ is_int ($ key ) && (null !== ($ position = $ this ->filterIndex ($ key , $ max ))) => [$ position => true ] + $ carry ,
275
+ default => $ carry ,
276
+ };
277
+
278
+ $ indices = array_reduce ($ keys , $ reducer , []);
279
+
280
+ return match (true ) {
281
+ [] === $ indices => $ this ,
282
+ $ max === count ($ indices ) => self ::new (),
283
+ default => self ::fromPairs ((function (array $ offsets ) {
284
+ foreach ($ this ->toPairs () as $ offset => $ pair ) {
285
+ if (!array_key_exists ($ offset , $ offsets )) {
286
+ yield $ pair ;
287
+ }
288
+ }
289
+ })($ indices )),
290
+ };
288
291
}
289
292
290
293
/**
@@ -294,9 +297,8 @@ public function append(string $key, iterable|StructuredField|Token|ByteSequence|
294
297
{
295
298
$ members = $ this ->members ;
296
299
unset($ members [$ key ]);
297
- $ members [MapKey::from ($ key )->value ] = self ::filterMember ($ member );
298
300
299
- return $ this ->newInstance ($ members );
301
+ return $ this ->newInstance ([... $ members, MapKey:: from ( $ key )-> value => self :: filterMember ( $ member )] );
300
302
}
301
303
302
304
/**
@@ -306,53 +308,46 @@ public function prepend(string $key, iterable|StructuredField|Token|ByteSequence
306
308
{
307
309
$ members = $ this ->members ;
308
310
unset($ members [$ key ]);
309
- $ members = [MapKey::from ($ key )->value => self ::filterMember ($ member ), ...$ members ];
310
311
311
- return $ this ->newInstance ($ members );
312
+ return $ this ->newInstance ([MapKey:: from ( $ key )-> value => self :: filterMember ( $ member ), ... $ members] );
312
313
}
313
314
314
315
/**
315
316
* @param array{0:string, 1:SfMember|SfMemberInput} ...$pairs
316
317
*/
317
318
public function push (array ...$ pairs ): self
318
319
{
319
- if ([] === $ pairs ) {
320
- return $ this ;
321
- }
322
-
323
- $ newPairs = iterator_to_array ($ this ->toPairs ());
324
- foreach ($ pairs as $ pair ) {
325
- $ newPairs [] = $ pair ;
326
- }
327
-
328
- return self ::fromPairs ($ newPairs );
320
+ return match (true ) {
321
+ [] === $ pairs => $ this ,
322
+ default => self ::fromPairs ((function (iterable $ pairs ) {
323
+ yield from $ this ->toPairs ();
324
+ yield from $ pairs ;
325
+ })($ pairs )),
326
+ };
329
327
}
330
328
331
329
/**
332
330
* @param array{0:string, 1:SfMember|SfMemberInput} ...$pairs
333
331
*/
334
332
public function unshift (array ...$ pairs ): self
335
333
{
336
- if ([] === $ pairs ) {
337
- return $ this ;
338
- }
339
-
340
- foreach ($ this ->members as $ key => $ member ) {
341
- $ pairs [] = [$ key , $ member ];
342
- }
343
-
344
- return self ::fromPairs ($ pairs );
334
+ return match (true ) {
335
+ [] === $ pairs => $ this ,
336
+ default => self ::fromPairs ((function (iterable $ pairs ) {
337
+ yield from $ pairs ;
338
+ yield from $ this ->toPairs ();
339
+ })($ pairs )),
340
+ };
345
341
}
346
342
347
343
/**
348
344
* @param array{0:string, 1:SfMember|SfMemberInput} ...$members
349
345
*/
350
346
public function insert (int $ index , array ...$ members ): static
351
347
{
352
- $ offset = $ this ->filterIndex ($ index );
348
+ $ offset = $ this ->filterIndex ($ index ) ?? throw InvalidOffset:: dueToIndexNotFound ( $ index ) ;
353
349
354
350
return match (true ) {
355
- null === $ offset => throw InvalidOffset::dueToIndexNotFound ($ index ),
356
351
[] === $ members => $ this ,
357
352
0 === $ offset => $ this ->unshift (...$ members ),
358
353
count ($ this ->members ) === $ offset => $ this ->push (...$ members ),
@@ -370,18 +365,14 @@ public function insert(int $index, array ...$members): static
370
365
*/
371
366
public function replace (int $ index , array $ member ): static
372
367
{
373
- $ offset = $ this ->filterIndex ($ index );
374
- if (null === $ offset ) {
375
- throw InvalidOffset::dueToIndexNotFound ($ index );
376
- }
377
-
368
+ $ offset = $ this ->filterIndex ($ index ) ?? throw InvalidOffset::dueToIndexNotFound ($ index );
378
369
$ member [1 ] = self ::filterMember ($ member [1 ]);
379
370
$ pairs = iterator_to_array ($ this ->toPairs ());
380
- if ($ pairs [$ offset ] == $ member ) {
381
- return $ this ;
382
- }
383
371
384
- return self ::fromPairs (array_replace ($ pairs , [$ offset => $ member ]));
372
+ return match (true ) {
373
+ $ pairs [$ offset ] == $ member => $ this ,
374
+ default => self ::fromPairs (array_replace ($ pairs , [$ offset => $ member ])),
375
+ };
385
376
}
386
377
387
378
/**
0 commit comments