Skip to content

Commit c4a0076

Browse files
committed
Improve internal codebase
1 parent 16d0497 commit c4a0076

File tree

8 files changed

+198
-243
lines changed

8 files changed

+198
-243
lines changed

src/Dictionary.php

Lines changed: 23 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,17 @@
99
use CallbackFilterIterator;
1010
use Countable;
1111
use DateTimeInterface;
12+
use Exception;
1213
use Iterator;
1314
use IteratorAggregate;
1415
use Stringable;
1516
use Throwable;
1617

17-
use function array_is_list;
1818
use function array_key_exists;
1919
use function array_keys;
2020
use function array_map;
2121
use function count;
2222
use function implode;
23-
use function is_array;
2423
use function is_bool;
2524
use function is_int;
2625
use function is_iterable;
@@ -47,34 +46,12 @@ private function __construct(iterable $members = [])
4746
{
4847
$filteredMembers = [];
4948
foreach ($members as $key => $member) {
50-
$filteredMembers[MapKey::from($key)->value] = self::filterMember($member);
49+
$filteredMembers[Key::from($key)->value] = Member::innerListOrItem($member);
5150
}
5251

5352
$this->members = $filteredMembers;
5453
}
5554

56-
/**
57-
* @param SfMemberInput $member
58-
*/
59-
private static function filterMember(mixed $member): InnerList|Item
60-
{
61-
if ($member instanceof StructuredFieldProvider) {
62-
$member = $member->toStructuredField();
63-
if ($member instanceof Item || $member instanceof InnerList) {
64-
return $member;
65-
}
66-
67-
throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Item::class.' or an '.InnerList::class.'; '.$member::class.' given.');
68-
}
69-
70-
return match (true) {
71-
$member instanceof InnerList,
72-
$member instanceof Item => $member,
73-
is_iterable($member) => InnerList::new(...$member),
74-
default => Item::new($member),
75-
};
76-
}
77-
7855
/**
7956
* Returns a new instance.
8057
*/
@@ -125,45 +102,12 @@ public static function fromPairs(StructuredFieldProvider|Dictionary|Parameters|i
125102
throw new InvalidArgument('The "'.$pairs::class.'" instance can not be used for creating a .'.self::class.' structured field.');
126103
}
127104

128-
$converter = function (mixed $pair): InnerList|Item {
129-
if ($pair instanceof StructuredFieldProvider) {
130-
$pair = $pair->toStructuredField();
131-
if ($pair instanceof Item || $pair instanceof InnerList) {
132-
return $pair;
133-
}
134-
135-
throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Item::class.' or an '.InnerList::class.'; '.$pair::class.' given.');
136-
}
137-
138-
if ($pair instanceof InnerList || $pair instanceof Item) {
139-
return $pair;
140-
}
141-
142-
if (!is_array($pair)) {
143-
return Item::new($pair); /* @phpstan-ignore-line */
144-
}
145-
146-
if (!array_is_list($pair)) {
147-
throw new SyntaxError('The pair must be represented by an array as a list.');
148-
}
149-
150-
if ([] === $pair) {
151-
return InnerList::new();
152-
}
153-
154-
if (!in_array(count($pair), [1, 2], true)) {
155-
throw new SyntaxError('The pair first member represents its value; the second member is its associated parameters.');
156-
}
157-
158-
return is_iterable($pair[0]) ? InnerList::fromPair($pair) : Item::fromPair($pair);
159-
};
160-
161105
return match (true) {
162106
$pairs instanceof Dictionary,
163107
$pairs instanceof Parameters => new self($pairs->toAssociative()),
164-
default => new self((function (iterable $pairs) use ($converter) {
108+
default => new self((function (iterable $pairs) {
165109
foreach ($pairs as [$key, $member]) {
166-
yield $key => $converter($member);
110+
yield $key => Member::innerListOrItemFromPair($member);
167111
}
168112
})($pairs)),
169113
};
@@ -198,7 +142,7 @@ public static function fromRfc8941(Stringable|string $httpValue): self
198142
*
199143
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.2
200144
*
201-
* @throws StructuredFieldError|Throwable If the string is not a valid
145+
* @throws StructuredFieldError|Exception If the string is not a valid
202146
*/
203147
public static function fromHttpValue(Stringable|string $httpValue, Ietf $rfc = Ietf::Rfc9651): self
204148
{
@@ -352,11 +296,7 @@ public function allowedKeys(array $keys): bool
352296
public function getByKey(string $key, ?callable $validate = null): Item|InnerList
353297
{
354298
$value = $this->members[$key] ?? throw InvalidOffset::dueToKeyNotFound($key);
355-
if (null === $validate) {
356-
return $value;
357-
}
358-
359-
if (true === ($exceptionMessage = $validate($value))) {
299+
if (null === $validate || true === ($exceptionMessage = $validate($value))) {
360300
return $value;
361301
}
362302

@@ -411,29 +351,25 @@ private function filterIndex(int $index, ?int $max = null): ?int
411351
public function getByIndex(int $index, ?callable $validate = null): array
412352
{
413353
$foundOffset = $this->filterIndex($index) ?? throw InvalidOffset::dueToIndexNotFound($index);
414-
415-
$validator = function (Item|InnerList $value, string $key, int $index, callable $validate): array {
416-
if (true === ($exceptionMessage = $validate($value, $key))) {
417-
return [$key, $value];
354+
foreach ($this as $offset => $pair) {
355+
if ($offset === $foundOffset) {
356+
break;
418357
}
358+
}
419359

420-
if (!is_string($exceptionMessage) || '' === trim($exceptionMessage)) {
421-
$exceptionMessage = "The member at position '{index}' whose key is '{key}' with the value '{value}' failed validation.";
422-
}
360+
if (!isset($pair)) {
361+
throw InvalidOffset::dueToIndexNotFound($index);
362+
}
423363

424-
throw new Violation(strtr($exceptionMessage, ['{index}' => $index, '{key}' => $key, '{value}' => $value->toHttpValue()]));
425-
};
364+
if (null === $validate || true === ($exceptionMessage = $validate($pair[1], $pair[0]))) {
365+
return $pair;
366+
}
426367

427-
foreach ($this as $offset => $pair) {
428-
if ($offset === $foundOffset) {
429-
return match ($validate) {
430-
null => $pair,
431-
default => $validator($pair[1], $pair[0], $index, $validate),
432-
};
433-
}
368+
if (!is_string($exceptionMessage) || '' === trim($exceptionMessage)) {
369+
$exceptionMessage = "The member at position '{index}' whose key is '{key}' with the value '{value}' failed validation.";
434370
}
435371

436-
throw InvalidOffset::dueToIndexNotFound($index);
372+
throw new Violation(strtr($exceptionMessage, ['{index}' => $index, '{key}' => $pair[0], '{value}' => $pair[1]->toHttpValue()]));
437373
}
438374

439375
/**
@@ -514,7 +450,7 @@ public function add(
514450
iterable|StructuredFieldProvider|Dictionary|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool $member
515451
): self {
516452
$members = $this->members;
517-
$members[MapKey::from($key)->value] = self::filterMember($member);
453+
$members[Key::from($key)->value] = Member::innerListOrItem($member);
518454

519455
return $this->newInstance($members);
520456
}
@@ -606,7 +542,7 @@ public function append(
606542
$members = $this->members;
607543
unset($members[$key]);
608544

609-
return $this->newInstance([...$members, MapKey::from($key)->value => self::filterMember($member)]);
545+
return $this->newInstance([...$members, Key::from($key)->value => Member::innerListOrItem($member)]);
610546
}
611547

612548
/**
@@ -626,7 +562,7 @@ public function prepend(
626562
$members = $this->members;
627563
unset($members[$key]);
628564

629-
return $this->newInstance([MapKey::from($key)->value => self::filterMember($member), ...$members]);
565+
return $this->newInstance([Key::from($key)->value => Member::innerListOrItem($member), ...$members]);
630566
}
631567

632568
/**
@@ -703,7 +639,7 @@ public function insert(int $index, array ...$members): self
703639
public function replace(int $index, array $pair): self
704640
{
705641
$offset = $this->filterIndex($index) ?? throw InvalidOffset::dueToIndexNotFound($index);
706-
$pair[1] = self::filterMember($pair[1]);
642+
$pair[1] = Member::innerListOrItem($pair[1]);
707643
$pairs = iterator_to_array($this->getIterator());
708644

709645
return match (true) {

src/InnerList.php

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,31 +51,10 @@ final class InnerList implements ArrayAccess, Countable, IteratorAggregate
5151
*/
5252
private function __construct(iterable $members, ?Parameters $parameters = null)
5353
{
54-
$this->members = array_map($this->filterMember(...), array_values([...$members]));
54+
$this->members = array_map(Member::item(...), array_values([...$members]));
5555
$this->parameters = $parameters ?? Parameters::new();
5656
}
5757

58-
/**
59-
* @param SfItemInput|SfItemPair $member
60-
*/
61-
private function filterMember(mixed $member): Item
62-
{
63-
if ($member instanceof StructuredFieldProvider) {
64-
$member = $member->toStructuredField();
65-
if (!$member instanceof Item) {
66-
throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Item::class.'; '.$member::class.' given.');
67-
}
68-
69-
return $member;
70-
}
71-
72-
if ($member instanceof Item) {
73-
return $member;
74-
}
75-
76-
return Item::new($member);
77-
}
78-
7958
/**
8059
* Returns an instance from an HTTP textual representation.
8160
*
@@ -113,7 +92,7 @@ public static function fromAssociative(
11392
/**
11493
* @param array{0:iterable<SfItemInput>, 1?:Parameters|SfParameterInput}|array<mixed> $pair
11594
*/
116-
public static function fromPair(array $pair): self
95+
public static function fromPair(array $pair = []): self
11796
{
11897
if ([] === $pair) {
11998
return self::new();
@@ -389,7 +368,7 @@ public function replace(
389368
StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool $member
390369
): self {
391370
$offset = $this->filterIndex($index) ?? throw InvalidOffset::dueToIndexNotFound($index);
392-
$member = self::filterMember($member);
371+
$member = Member::item($member);
393372

394373
return match (true) {
395374
$member->equals($this->members[$offset]) => $this,

src/Item.php

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
use Exception;
1212
use Stringable;
1313
use Throwable;
14+
use TypeError;
1415

1516
use function array_is_list;
1617
use function count;
18+
use function in_array;
1719

1820
use const JSON_PRESERVE_ZERO_FRACTION;
1921
use const PHP_ROUND_HALF_EVEN;
@@ -114,12 +116,12 @@ public static function tryFromPair(array $pair): ?self
114116
*/
115117
public static function fromPair(array $pair): self
116118
{
117-
;
118-
if ([] === $pair || !array_is_list($pair) || 2 < count($pair)) {
119+
$nbElements = count($pair);
120+
if (!in_array($nbElements, [1, 2], true) || !array_is_list($pair)) {
119121
throw new SyntaxError('The pair must be represented by an non-empty array as a list containing exactly 1 or 2 members.');
120122
}
121123

122-
if (1 === count($pair)) {
124+
if (1 === $nbElements) {
123125
return new self($pair[0]);
124126
}
125127

@@ -142,16 +144,12 @@ public static function fromPair(array $pair): self
142144
/**
143145
* Returns a new bare instance from value.
144146
*
145-
* @param SfItemInput|SfItemPair $value
147+
* @param SfItemPair|SfItemInput $value
146148
*
147-
* @throws SyntaxError If the value is not valid.
149+
* @throws SyntaxError|TypeError If the value is not valid.
148150
*/
149151
public static function new(mixed $value): self
150152
{
151-
if ($value instanceof Item) {
152-
return new self($value->value(), $value->parameters());
153-
}
154-
155153
if (is_array($value)) {
156154
return self::fromPair($value);
157155
}
@@ -389,8 +387,8 @@ private function serialize(Ietf $rfc = Ietf::Rfc9651): string
389387
$this->value instanceof Token => $this->value->toString(),
390388
$this->value instanceof Bytes => ':'.$this->value->encoded().':',
391389
$this->value instanceof DisplayString => '%"'.$this->value->encoded().'"',
392-
is_int($this->value) => (string)$this->value,
393-
is_float($this->value) => (string)json_encode(round($this->value, 3, PHP_ROUND_HALF_EVEN), JSON_PRESERVE_ZERO_FRACTION),
390+
is_int($this->value) => (string) $this->value,
391+
is_float($this->value) => (string) json_encode(round($this->value, 3, PHP_ROUND_HALF_EVEN), JSON_PRESERVE_ZERO_FRACTION),
394392
$this->value,
395393
false === $this->value => '?'.($this->value ? '1' : '0'),
396394
default => '"'.preg_replace('/(["\\\])/', '\\\$1', $this->value).'"',

src/MapKey.php renamed to src/Key.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.1.2
1111
* @internal normalize HTTP field key
1212
*/
13-
final class MapKey
13+
final class Key
1414
{
1515
private function __construct(public readonly string $value)
1616
{

0 commit comments

Comments
 (0)