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 3, 2024
1 parent 0c2295c commit 49ccb53
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 86 deletions.
32 changes: 0 additions & 32 deletions src/DataType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
25 changes: 15 additions & 10 deletions src/Dictionary.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,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 +124,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 +147,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 @@ -193,7 +198,7 @@ public static function fromRfc8941(Stringable|string $httpValue): 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 Down
2 changes: 1 addition & 1 deletion src/InnerList.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private function filterMember(mixed $member): Item
*/
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 Down
33 changes: 18 additions & 15 deletions src/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ public static function fromRfc8941(Stringable|string $httpValue): self
*
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.3
*
* @throws SyntaxError If the HTTP value can not be parsed
* @throws SyntaxError|Exception If the HTTP value can not be parsed
*/
public static function fromHttpValue(Stringable|string $httpValue, Ietf $rfc = Ietf::Rfc9651): self
{
return self::fromPair(Parser::new($rfc)->parseItem($httpValue));
return self::fromPair((new Parser($rfc))->parseItem($httpValue));
}

/**
Expand All @@ -81,13 +81,15 @@ public static function fromAssociative(
): self {
if ($parameters instanceof StructuredFieldProvider) {
$parameters = $parameters->toStructuredField();
if (!$parameters instanceof Parameters) {
throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Parameters::class.'; '.$parameters::class.' given.');
if ($parameters instanceof Parameters) {
return new self($value, $parameters);
}

throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Parameters::class.'; '.$parameters::class.' given.');
}

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

return new self($value, $parameters);
Expand Down Expand Up @@ -122,13 +124,15 @@ public static function fromPair(array $pair): self

if ($pair[1] instanceof StructuredFieldProvider) {
$pair[1] = $pair[1]->toStructuredField();
if (!$pair[1] instanceof Parameters) {
throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Parameters::class.'; '.$pair[1]::class.' given.');
if ($pair[1] instanceof Parameters) {
return new self($pair[0], Parameters::fromPairs($pair[1]));
}

throw new InvalidArgument('The '.StructuredFieldProvider::class.' must provide a '.Parameters::class.'; '.$pair[1]::class.' given.');
}

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 Down Expand Up @@ -251,10 +255,11 @@ public static function fromDateFormat(string $format, string $datetime): self
throw new SyntaxError('The date notation `'.$datetime.'` is incompatible with the date format `'.$format.'`.', 0, $exception);
}

return match (false) {
$value => throw new SyntaxError('The date notation `'.$datetime.'` is incompatible with the date format `'.$format.'`.'),
default => new self($value),
};
if (!$value instanceof DateTimeImmutable) {
throw new SyntaxError('The date notation `'.$datetime.'` is incompatible with the date format `'.$format.'`.');
}

return new self($value);
}

/**
Expand All @@ -274,12 +279,10 @@ public static function fromDateString(string $datetime, DateTimeZone|string|null
}

try {
$value = new DateTimeImmutable($datetime, $timezone);
return new self(new DateTimeImmutable($datetime, $timezone));
} catch (Throwable $exception) {
throw new SyntaxError('Unable to create a '.DateTimeImmutable::class.' instance with the date notation `'.$datetime.'.`', 0, $exception);
}

return new self($value);
}

/**
Expand Down
37 changes: 21 additions & 16 deletions src/OuterList.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ final class OuterList implements ArrayAccess, Countable, IteratorAggregate
* @param SfMemberInput ...$members
*/
private function __construct(
iterable|StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
iterable|StructuredFieldProvider|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
) {
$this->members = array_map($this->filterMember(...), array_values([...$members]));
}
Expand All @@ -57,14 +57,16 @@ private 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 Parameters,
$member instanceof Dictionary => 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 All @@ -77,7 +79,7 @@ private function filterMember(mixed $member): InnerList|Item
*/
public static function fromHttpValue(Stringable|string $httpValue, Ietf $rfc = Ietf::Rfc9651): self
{
return self::fromPairs(Parser::new($rfc)->parseList($httpValue)); /* @phpstan-ignore-line */
return self::fromPairs((new Parser($rfc))->parseList($httpValue)); /* @phpstan-ignore-line */
}

/**
Expand All @@ -96,6 +98,11 @@ public static function fromPairs(StructuredFieldProvider|iterable $pairs): self
$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 @@ -114,13 +121,11 @@ public static function fromPairs(StructuredFieldProvider|iterable $pairs): self
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 All @@ -137,7 +142,7 @@ public static function fromPairs(StructuredFieldProvider|iterable $pairs): self
/**
* @param SfMemberInput ...$members
*/
public static function new(iterable|StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members): self
public static function new(iterable|StructuredFieldProvider|InnerList|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members): self
{
return new self(...$members);
}
Expand Down Expand Up @@ -289,7 +294,7 @@ public function last(): InnerList|Item|null
* @param SfMemberInput ...$members
*/
public function unshift(
StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|iterable|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
StructuredFieldProvider|InnerList|Item|iterable|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
): self {
$membersToAdd = array_reduce(
$members,
Expand All @@ -315,7 +320,7 @@ function (array $carry, $member) {
* @param SfMemberInput ...$members
*/
public function push(
iterable|StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
iterable|StructuredFieldProvider|InnerList|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
): self {
$membersToAdd = array_reduce(
$members,
Expand Down Expand Up @@ -344,7 +349,7 @@ function (array $carry, $member) {
*/
public function insert(
int $index,
iterable|StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
iterable|StructuredFieldProvider|InnerList|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool ...$members
): self {
$offset = $this->filterIndex($index) ?? throw InvalidOffset::dueToIndexNotFound($index);

Expand All @@ -365,7 +370,7 @@ public function insert(
*/
public function replace(
int $index,
iterable|StructuredFieldProvider|OuterList|Dictionary|InnerList|Parameters|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool $member
iterable|StructuredFieldProvider|InnerList|Item|Token|Bytes|DisplayString|DateTimeInterface|string|int|float|bool $member
): self {
$offset = $this->filterIndex($index) ?? throw InvalidOffset::dueToIndexNotFound($index);
$member = self::filterMember($member);
Expand Down
2 changes: 1 addition & 1 deletion src/Parameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public static function fromPairs(StructuredFieldProvider|iterable $pairs): self
*/
public static function fromHttpValue(Stringable|string $httpValue, Ietf $rfc = Ietf::Rfc9651): self
{
return self::fromPairs(Parser::new($rfc)->parseParameters($httpValue)); /* @phpstan-ignore-line */
return self::fromPairs((new Parser($rfc))->parseParameters($httpValue)); /* @phpstan-ignore-line */
}

public static function fromRfc9651(Stringable|string $httpValue): self
Expand Down
5 changes: 0 additions & 5 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ final class Parser
private const FIRST_CHARACTER_RANGE_NUMBER = '-1234567890';
private const FIRST_CHARACTER_RANGE_TOKEN = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*';

public static function new(Ietf $rfc = Ietf::Rfc9651): self
{
return new self($rfc);
}

public function __construct(private readonly Ietf $rfc)
{
}
Expand Down
4 changes: 2 additions & 2 deletions tests/DataTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public function it_will_fail_to_generate_rfc8941_structured_field_text_represena
{
$this->expectExceptionObject(MissingFeature::dueToLackOfSupport(Type::Date, Ietf::Rfc8941));

DataType::Dictionary->toRfc8941([['a', false], ['b', Item::fromDateString('+30 minutes')]]);
DataType::Dictionary->serialize([['a', false], ['b', Item::fromDateString('+30 minutes')]], Ietf::Rfc8941);
}

#[Test]
Expand All @@ -108,6 +108,6 @@ public function it_will_fail_to_parse_rfc9651_structured_field_text_represenatio

$string = DataType::Dictionary->serialize([['a', false], ['b', Item::fromDateString('+30 minutes')]]);

DataType::Dictionary->fromRfc8941($string);
DataType::Dictionary->parse($string, Ietf::Rfc8941);
}
}
3 changes: 2 additions & 1 deletion tests/DictionaryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use LogicException;
use PHPUnit\Framework\Attributes\Test;
use TypeError;

final class DictionaryTest extends StructuredFieldTestCase
{
Expand Down Expand Up @@ -125,7 +126,7 @@ public function it_fails_to_add_an_item_with_wrong_key(): void
#[Test]
public function it_fails_to_insert_something_other_than_a_inner_list_or_an_item(): void
{
$this->expectException(InvalidArgument::class);
$this->expectException(TypeError::class);

Dictionary::new()->add('foo', Parameters::fromAssociative(['foo' => 'bar']));
}
Expand Down
3 changes: 2 additions & 1 deletion tests/OuterListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use LogicException;
use PHPUnit\Framework\Attributes\Test;
use TypeError;

final class OuterListTest extends StructuredFieldTestCase
{
Expand Down Expand Up @@ -103,7 +104,7 @@ public function it_can_return_the_same_object_if_no_replace_is_needed(): void
#[Test]
public function it_fails_to_insert_something_other_than_a_inner_list_or_an_item(): void
{
$this->expectException(InvalidArgument::class);
$this->expectException(TypeError::class);

OuterList::new()->push(Dictionary::fromAssociative(['foo' => 'bar']));
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ParserBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ final class ParserBench

public function __construct()
{
$this->parser = Parser::new();
$this->parser = new Parser(Ietf::Rfc9651);
}

#[Bench\Iterations(4)]
Expand Down
3 changes: 2 additions & 1 deletion tests/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ final class ParserTest extends StructuredFieldTestCase
protected function setUp(): void
{
parent::setUp();
$this->parser = Parser::new();

$this->parser = new Parser(Ietf::Rfc9651);
}

#[Test]
Expand Down

0 comments on commit 49ccb53

Please sign in to comment.