1414use function count ;
1515use function implode ;
1616use function is_array ;
17+ use function is_int ;
1718use function is_iterable ;
1819use function is_string ;
1920
@@ -90,15 +91,14 @@ public static function fromAssociative(iterable $members): self
9091 */
9192 public static function fromPairs (iterable $ pairs ): self
9293 {
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+ };
102102 }
103103
104104 /**
@@ -110,18 +110,15 @@ public static function fromPairs(iterable $pairs): self
110110 */
111111 public static function fromHttpValue (Stringable |string $ httpValue ): self
112112 {
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+ };
120120
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 )));
125122 }
126123
127124 public function toHttpValue (): string
@@ -163,7 +160,7 @@ public function getIterator(): Iterator
163160 }
164161
165162 /**
166- * @return Iterator<array{0:string, 1:SfMember}>
163+ * @return Iterator<int, array{0:string, 1:SfMember}>
167164 */
168165 public function toPairs (): Iterator
169166 {
@@ -199,17 +196,14 @@ public function has(string|int ...$keys): bool
199196 */
200197 public function get (string |int $ key ): StructuredField
201198 {
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 );
207200 }
208201
209202 public function hasPair (int ...$ indexes ): bool
210203 {
204+ $ max = count ($ this ->members );
211205 foreach ($ indexes as $ index ) {
212- if (null === $ this ->filterIndex ($ index )) {
206+ if (null === $ this ->filterIndex ($ index, $ max )) {
213207 return false ;
214208 }
215209 }
@@ -220,12 +214,14 @@ public function hasPair(int ...$indexes): bool
220214 /**
221215 * Filters and format instance index.
222216 */
223- private function filterIndex (int $ index ): int |null
217+ private function filterIndex (int $ index, int | null $ max = null ): int |null
224218 {
225- $ max = count ($ this ->members );
219+ $ max ?? = count ($ this ->members );
226220
227221 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 ,
229225 0 > $ index => $ max + $ index ,
230226 default => $ index ,
231227 };
@@ -238,10 +234,7 @@ private function filterIndex(int $index): int|null
238234 */
239235 public function pair (int $ index ): array
240236 {
241- $ offset = $ this ->filterIndex ($ index );
242- if (null === $ offset ) {
243- throw InvalidOffset::dueToIndexNotFound ($ index );
244- }
237+ $ offset = $ this ->filterIndex ($ index ) ?? throw InvalidOffset::dueToIndexNotFound ($ index );
245238
246239 return [...$ this ->toPairs ()][$ offset ];
247240 }
@@ -262,29 +255,39 @@ public function add(string $key, iterable|StructuredField|Token|ByteSequence|Dat
262255 */
263256 private function newInstance (array $ members ): self
264257 {
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+ };
270262 }
271263
272264 public function remove (string |int ...$ keys ): static
273265 {
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 ) {
284267 return $ this ;
285268 }
286269
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+ };
288291 }
289292
290293 /**
@@ -294,9 +297,8 @@ public function append(string $key, iterable|StructuredField|Token|ByteSequence|
294297 {
295298 $ members = $ this ->members ;
296299 unset($ members [$ key ]);
297- $ members [MapKey::from ($ key )->value ] = self ::filterMember ($ member );
298300
299- return $ this ->newInstance ($ members );
301+ return $ this ->newInstance ([... $ members, MapKey:: from ( $ key )-> value => self :: filterMember ( $ member )] );
300302 }
301303
302304 /**
@@ -306,53 +308,46 @@ public function prepend(string $key, iterable|StructuredField|Token|ByteSequence
306308 {
307309 $ members = $ this ->members ;
308310 unset($ members [$ key ]);
309- $ members = [MapKey::from ($ key )->value => self ::filterMember ($ member ), ...$ members ];
310311
311- return $ this ->newInstance ($ members );
312+ return $ this ->newInstance ([MapKey:: from ( $ key )-> value => self :: filterMember ( $ member ), ... $ members] );
312313 }
313314
314315 /**
315316 * @param array{0:string, 1:SfMember|SfMemberInput} ...$pairs
316317 */
317318 public function push (array ...$ pairs ): self
318319 {
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+ };
329327 }
330328
331329 /**
332330 * @param array{0:string, 1:SfMember|SfMemberInput} ...$pairs
333331 */
334332 public function unshift (array ...$ pairs ): self
335333 {
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+ };
345341 }
346342
347343 /**
348344 * @param array{0:string, 1:SfMember|SfMemberInput} ...$members
349345 */
350346 public function insert (int $ index , array ...$ members ): static
351347 {
352- $ offset = $ this ->filterIndex ($ index );
348+ $ offset = $ this ->filterIndex ($ index ) ?? throw InvalidOffset:: dueToIndexNotFound ( $ index ) ;
353349
354350 return match (true ) {
355- null === $ offset => throw InvalidOffset::dueToIndexNotFound ($ index ),
356351 [] === $ members => $ this ,
357352 0 === $ offset => $ this ->unshift (...$ members ),
358353 count ($ this ->members ) === $ offset => $ this ->push (...$ members ),
@@ -370,18 +365,14 @@ public function insert(int $index, array ...$members): static
370365 */
371366 public function replace (int $ index , array $ member ): static
372367 {
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 );
378369 $ member [1 ] = self ::filterMember ($ member [1 ]);
379370 $ pairs = iterator_to_array ($ this ->toPairs ());
380- if ($ pairs [$ offset ] == $ member ) {
381- return $ this ;
382- }
383371
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+ };
385376 }
386377
387378 /**
0 commit comments