Skip to content

Commit

Permalink
Improve internal codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Dec 4, 2024
1 parent a8b8df3 commit c17a734
Show file tree
Hide file tree
Showing 19 changed files with 248 additions and 412 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
- `Dictionary::toPairs` and `Parameters::toPairs`
- `ByteSequence` class replaced by `Bytes` class
- `DataType::create` method use a specific DataType class instead.
- `Value` internal class.

## [1.3.0](https://github.com/bakame-php/http-structured-fields/compare/1.2.2...1.3.0) - 2024-01-05

Expand Down
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ parameters:
ignoreErrors:
- message: '#it_fails_to_create_an_item_from_an_array_of_pairs\(\)#'
path: tests/ItemTest.php
- message: '#Method Bakame\\Http\\StructuredFields\\DataType::(serialize|build|create|toRfc9651|toRfc8941)\(\) has parameter \$data with no value type specified in iterable type iterable.#'
- message: '#Method Bakame\\Http\\StructuredFields\\DataType::(serialize|parse)\(\) has parameter \$data with no value type specified in iterable type iterable.#'
path: src/DataType.php
excludePaths:
- tests/Record.php
Expand Down
36 changes: 2 additions & 34 deletions src/DataType.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ enum DataType: string
/**
* @throws SyntaxError|Exception
*/
public function parse(Stringable|string $httpValue, ?Ietf $rfc = Ietf::Rfc9651): OuterList|InnerList|Parameters|Dictionary|Item
public function parse(Stringable|string $httpValue, Ietf $rfc = Ietf::Rfc9651): OuterList|InnerList|Parameters|Dictionary|Item
{
return match ($this) {
self::List => OuterList::fromHttpValue($httpValue, $rfc),
Expand All @@ -32,7 +32,7 @@ public function parse(Stringable|string $httpValue, ?Ietf $rfc = Ietf::Rfc9651):
/**
* @throws SyntaxError|Exception
*/
public function serialize(iterable $data, ?Ietf $rfc = Ietf::Rfc9651): string
public function serialize(iterable $data, Ietf $rfc = Ietf::Rfc9651): string
{
return (match ($this) {
self::List => OuterList::fromPairs($data),
Expand All @@ -42,36 +42,4 @@ public function serialize(iterable $data, ?Ietf $rfc = Ietf::Rfc9651): string
self::Parameters => Parameters::fromPairs($data),
})->toHttpValue($rfc);
}

/**
* @throws SyntaxError|Exception
*/
public function fromRfc9651(Stringable|string $httpValue): OuterList|InnerList|Parameters|Dictionary|Item
{
return $this->parse($httpValue, Ietf::Rfc9651);
}

/**
* @throws SyntaxError|Exception
*/
public function toRfc9651(iterable $data): string
{
return $this->serialize($data, Ietf::Rfc9651);
}

/**
* @throws SyntaxError|Exception
*/
public function fromRfc8941(Stringable|string $httpValue): OuterList|InnerList|Parameters|Dictionary|Item
{
return $this->parse($httpValue, Ietf::Rfc8941);
}

/**
* @throws SyntaxError|Exception
*/
public function toRfc8941(iterable $data): string
{
return $this->serialize($data, Ietf::Rfc8941);
}
}
55 changes: 30 additions & 25 deletions src/Dictionary.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@
use Stringable;
use Throwable;

use function array_is_list;
use function array_key_exists;
use function array_keys;
use function array_map;
use function count;
use function implode;
use function is_array;
use function is_bool;
use function is_int;
use function is_iterable;
use function is_string;
use function uasort;

/**
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.2
Expand Down Expand Up @@ -56,14 +60,16 @@ private static function filterMember(mixed $member): InnerList|Item
{
if ($member instanceof StructuredFieldProvider) {
$member = $member->toStructuredField();
if ($member instanceof Item || $member instanceof InnerList) {
return $member;
}

throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Item::class.' or an '.InnerList::class.'; '.$member::class.' given.');
}

return match (true) {
$member instanceof InnerList,
$member instanceof Item => $member,
$member instanceof OuterList,
$member instanceof Dictionary,
$member instanceof Parameters => throw new InvalidArgument('An instance of "'.$member::class.'" can not be a member of "'.self::class.'".'),
is_iterable($member) => InnerList::new(...$member),
default => Item::new($member),
};
Expand Down Expand Up @@ -122,6 +128,11 @@ public static function fromPairs(StructuredFieldProvider|Dictionary|Parameters|i
$converter = function (mixed $pair): InnerList|Item {
if ($pair instanceof StructuredFieldProvider) {
$pair = $pair->toStructuredField();
if ($pair instanceof Item || $pair instanceof InnerList) {
return $pair;
}

throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Item::class.' or an '.InnerList::class.'; '.$pair::class.' given.');
}

if ($pair instanceof InnerList || $pair instanceof Item) {
Expand All @@ -140,13 +151,11 @@ public static function fromPairs(StructuredFieldProvider|Dictionary|Parameters|i
return InnerList::new();
}

[$member, $parameters] = match (count($pair)) {
2 => $pair,
1 => [$pair[0], []],
default => throw new SyntaxError('The pair first member is the item value; its second member is the item parameters.'),
};
if (!in_array(count($pair), [1, 2], true)) {
throw new SyntaxError('The pair first member is the item value; its second member is the item parameters.');
}

return is_iterable($member) ? InnerList::fromPair([$member, $parameters]) : Item::fromPair([$member, $parameters]);
return is_iterable($pair[0]) ? InnerList::fromPair($pair) : Item::fromPair($pair);
};

return match (true) {
Expand Down Expand Up @@ -191,9 +200,9 @@ public static function fromRfc8941(Stringable|string $httpValue): self
*
* @throws StructuredFieldError|Throwable If the string is not a valid
*/
public static function fromHttpValue(Stringable|string $httpValue, ?Ietf $rfc = Ietf::Rfc9651): self
public static function fromHttpValue(Stringable|string $httpValue, Ietf $rfc = Ietf::Rfc9651): self
{
return self::fromPairs(Parser::new($rfc)->parseDictionary($httpValue)); /* @phpstan-ignore-line */
return self::fromPairs((new Parser($rfc))->parseDictionary($httpValue)); /* @phpstan-ignore-line */
}

public function toRfc9651(): string
Expand All @@ -206,18 +215,14 @@ public function toRfc8941(): string
return $this->toHttpValue(Ietf::Rfc8941);
}

public function toHttpValue(?Ietf $rfc = Ietf::Rfc9651): string
public function toHttpValue(Ietf $rfc = Ietf::Rfc9651): string
{
$rfc ??= Ietf::Rfc9651;
$members = [];
foreach ($this->members as $key => $member) {
$members[] = match (true) {
$member instanceof Item && true === $member->value() => $key.$member->parameters()->toHttpValue($rfc),
default => $key.'='.$member->toHttpValue($rfc),
};
}
$formatter = static fn (Item|InnerList $member, string $offset): string => match (true) {
$member instanceof Item && true === $member->value() => $offset.$member->parameters()->toHttpValue($rfc),
default => $offset.'='.$member->toHttpValue($rfc),
};

return implode(', ', $members);
return implode(', ', array_map($formatter, $this->members, array_keys($this->members)));
}

public function __toString(): string
Expand Down Expand Up @@ -506,7 +511,7 @@ public function last(): array
*/
public function add(
string $key,
iterable|StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool|null $member
iterable|StructuredFieldProvider|Dictionary|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool|null $member
): self {
if (null === $member) {
return $this;
Expand Down Expand Up @@ -596,7 +601,7 @@ public function removeByKeys(string ...$keys): self
*/
public function append(
string $key,
iterable|StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool $member
iterable|StructuredFieldProvider|Dictionary|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool $member
): self {
$members = $this->members;
unset($members[$key]);
Expand All @@ -616,7 +621,7 @@ public function append(
*/
public function prepend(
string $key,
iterable|StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool $member
iterable|StructuredFieldProvider|Dictionary|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool $member
): self {
$members = $this->members;
unset($members[$key]);
Expand Down Expand Up @@ -840,7 +845,7 @@ public function filter(callable $callback): self
public function sort(callable $callback): self
{
$members = iterator_to_array($this);
usort($members, $callback);
uasort($members, $callback);

return self::fromPairs($members);
}
Expand Down
1 change: 1 addition & 0 deletions src/DisplayString.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use function preg_replace_callback;
use function rawurldecode;
use function rawurlencode;
use function str_contains;

/**
* @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-sfbis#section-4.2.10
Expand Down
37 changes: 21 additions & 16 deletions src/InnerList.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use function array_values;
use function count;
use function implode;
use function uasort;

use const ARRAY_FILTER_USE_BOTH;
use const ARRAY_FILTER_USE_KEY;
Expand All @@ -46,10 +47,10 @@ final class InnerList implements ArrayAccess, Countable, IteratorAggregate
/**
* @param iterable<SfItemInput> $members
*/
private function __construct(iterable $members, Parameters $parameters)
private function __construct(iterable $members, ?Parameters $parameters = null)
{
$this->members = array_map($this->filterMember(...), array_values([...$members]));
$this->parameters = $parameters;
$this->parameters = $parameters ?? Parameters::new();
}

/**
Expand All @@ -59,22 +60,28 @@ private function filterMember(mixed $member): Item
{
if ($member instanceof StructuredFieldProvider) {
$member = $member->toStructuredField();
if (!$member instanceof Item) {
throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Item::class.'; '.$member::class.' given.');
}

return $member;
}

return match (true) {
$member instanceof Item => $member,
default => Item::new($member),
};
if (!$member instanceof Item) {
return Item::new($member);
}

return $member;
}

/**
* Returns an instance from an HTTP textual representation.
*
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.1
*/
public static function fromHttpValue(Stringable|string $httpValue, ?Ietf $rfc = Ietf::Rfc9651): self
public static function fromHttpValue(Stringable|string $httpValue, Ietf $rfc = Ietf::Rfc9651): self
{
return self::fromPair(Parser::new($rfc)->parseInnerList($httpValue));
return self::fromPair((new Parser($rfc))->parseInnerList($httpValue));
}

/**
Expand All @@ -95,7 +102,7 @@ public static function fromAssociative(
}

if (!$parameters instanceof Parameters) {
$parameters = Parameters::fromAssociative($parameters);
return new self($value, Parameters::fromAssociative($parameters));
}

return new self($value, $parameters);
Expand All @@ -115,7 +122,7 @@ public static function fromPair(array $pair): self
}

if (1 === count($pair)) {
return new self($pair[0], Parameters::new());
return new self($pair[0]);
}

if ($pair[1] instanceof StructuredFieldProvider) {
Expand All @@ -126,7 +133,7 @@ public static function fromPair(array $pair): self
}

if (!$pair[1] instanceof Parameters) {
$pair[1] = Parameters::fromPairs($pair[1]);
return new self($pair[0], Parameters::fromPairs($pair[1]));
}

return new self($pair[0], $pair[1]);
Expand All @@ -138,7 +145,7 @@ public static function fromPair(array $pair): self
public static function new(
StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
): self {
return new self($members, Parameters::new());
return new self($members);
}

public static function fromRfc9651(Stringable|string $httpValue): self
Expand All @@ -151,10 +158,8 @@ public static function fromRfc8941(Stringable|string $httpValue): self
return self::fromHttpValue($httpValue, Ietf::Rfc8941);
}

public function toHttpValue(?Ietf $rfc = Ietf::Rfc9651): string
public function toHttpValue(Ietf $rfc = Ietf::Rfc9651): string
{
$rfc ??= Ietf::Rfc9651;

return '('.implode(' ', array_map(fn (Item $value): string => $value->toHttpValue($rfc), $this->members)).')'.$this->parameters->toHttpValue($rfc);
}

Expand Down Expand Up @@ -483,7 +488,7 @@ public function filter(callable $callback): self
public function sort(callable $callback): self
{
$members = $this->members;
usort($members, $callback);
uasort($members, $callback);

return new self($members, $this->parameters);
}
Expand Down
Loading

0 comments on commit c17a734

Please sign in to comment.