Skip to content

Commit 1b3be85

Browse files
committed
Improve array and list type
1 parent 5eb4e51 commit 1b3be85

10 files changed

Lines changed: 64 additions & 91 deletions

src/Platform/StandardPlatform.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ public function getTypes(Direction $direction): iterable
6464
yield new Builder\TypeAliasBuilder(\Traversable::class, $array);
6565
yield new Builder\TypeAliasBuilder(\IteratorAggregate::class, $array);
6666

67+
// Adds support for the "iterable<T> -> list<T>" type
68+
yield new Builder\ListTypeBuilder('list', 'mixed');
69+
6770
// Adds support for the "?T" statement
6871
yield new Builder\NullableTypeBuilder();
6972

@@ -116,8 +119,6 @@ public function getTypes(Direction $direction): iterable
116119

117120
// Other
118121
if ($direction === Direction::Normalize) {
119-
// Adds support for the "iterable<T> -> list<T>" type
120-
yield new Builder\ListFromIterableTypeBuilder('list', 'mixed');
121122
// Adds support for the "object -> array{ ... }" type
122123
yield $object = new Builder\ObjectToArrayTypeBuilder('object');
123124
yield new Builder\TypeAliasBuilder(\stdClass::class, $object);
@@ -130,8 +131,6 @@ public function getTypes(Direction $direction): iterable
130131
// Adds support for the "object(ClassName) -> array{ ... }" type
131132
yield new Builder\ClassToArrayTypeBuilder($this->meta);
132133
} else {
133-
// Adds support for the "array<T> -> list<T>" type
134-
yield new Builder\ListFromArrayTypeBuilder('list', 'mixed');
135134
// Adds support for the "array{ ... } -> object" type
136135
yield $object = new Builder\ObjectFromArrayTypeBuilder('object');
137136
yield new Builder\TypeAliasBuilder(\stdClass::class, $object);
@@ -170,6 +169,12 @@ public function getTypeCoercers(Direction $direction): iterable
170169
// string
171170
yield Type\StringType::class => $string = new Coercer\StringTypeCoercer();
172171
yield Type\StringLiteralType::class => $string;
172+
173+
// array
174+
yield Type\ArrayType::class => $array = new Coercer\ArrayTypeCoercer();
175+
176+
// list
177+
yield Type\ListType::class => $list = new Coercer\ListTypeCoercer();
173178
}
174179

175180
#[\Override]

src/Type/ArrayType.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace TypeLang\Mapper\Type;
66

77
use TypeLang\Mapper\Context\Context;
8-
use TypeLang\Mapper\Context\Direction;
98
use TypeLang\Mapper\Context\Path\Entry\ArrayIndexEntry;
109
use TypeLang\Mapper\Exception\Runtime\InvalidIterableKeyException;
1110
use TypeLang\Mapper\Exception\Runtime\InvalidIterableValueException;
@@ -34,11 +33,7 @@ public function __construct(
3433
*/
3534
public function match(mixed $value, Context $context): bool
3635
{
37-
if ($context->direction === Direction::Denormalize) {
38-
return \is_array($value);
39-
}
40-
41-
return \is_iterable($value);
36+
return \is_array($value);
4237
}
4338

4439
public function cast(mixed $value, Context $context): array

src/Type/Builder/ListFromArrayTypeBuilder.php

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/Type/Builder/ListFromIterableTypeBuilder.php

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/Type/Builder/ListTypeBuilder.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use TypeLang\Mapper\Exception\Definition\Template\Hint\TemplateArgumentHintsNotSupportedException;
99
use TypeLang\Mapper\Exception\Definition\Template\TooManyTemplateArgumentsException;
1010
use TypeLang\Mapper\Exception\Definition\TypeNotFoundException;
11+
use TypeLang\Mapper\Type\ListType;
1112
use TypeLang\Mapper\Type\Parser\TypeParserInterface;
1213
use TypeLang\Mapper\Type\Repository\TypeRepositoryInterface;
1314
use TypeLang\Mapper\Type\TypeInterface;
@@ -18,7 +19,7 @@
1819
/**
1920
* @template-extends NamedTypeBuilder<TypeInterface>
2021
*/
21-
abstract class ListTypeBuilder extends NamedTypeBuilder
22+
class ListTypeBuilder extends NamedTypeBuilder
2223
{
2324
/**
2425
* @var non-empty-lowercase-string
@@ -72,8 +73,8 @@ public function build(
7273
*/
7374
private function buildWithNoValue(TypeRepositoryInterface $types, TypeParserInterface $parser): TypeInterface
7475
{
75-
return $this->create(
76-
type: $types->getTypeByStatement(
76+
return new ListType(
77+
value: $types->getTypeByStatement(
7778
statement: $parser->getStatementByDefinition(
7879
definition: $this->defaultValueType,
7980
),
@@ -97,12 +98,10 @@ private function buildWithValue(NamedTypeNode $statement, TypeRepositoryInterfac
9798

9899
$this->expectNoTemplateArgumentHint($statement, $value);
99100

100-
return $this->create(
101-
type: $types->getTypeByStatement(
101+
return new ListType(
102+
value: $types->getTypeByStatement(
102103
statement: $value->value,
103104
),
104105
);
105106
}
106-
107-
abstract protected function create(TypeInterface $type): TypeInterface;
108107
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\Mapper\Type\Coercer;
6+
7+
use TypeLang\Mapper\Context\Context;
8+
use TypeLang\Mapper\Exception\Runtime\InvalidValueException;
9+
10+
/**
11+
* @template-implements TypeCoercerInterface<array<array-key, mixed>>
12+
*/
13+
class ArrayTypeCoercer implements TypeCoercerInterface
14+
{
15+
public function coerce(mixed $value, Context $context): array
16+
{
17+
return match (true) {
18+
\is_array($value) => $value,
19+
$value instanceof \Traversable => \iterator_to_array($value, true),
20+
default => throw InvalidValueException::createFromContext($context),
21+
};
22+
}
23+
}

src/Type/Coercer/IntTypeCoercer.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ public function coerce(mixed $value, Context $context): int
1818
return $value->value;
1919
}
2020

21-
$original = $value;
22-
2321
if (\is_string($value) && \is_numeric($value)) {
2422
$value = (float) $value;
2523
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\Mapper\Type\Coercer;
6+
7+
use TypeLang\Mapper\Context\Context;
8+
use TypeLang\Mapper\Exception\Runtime\InvalidValueException;
9+
10+
/**
11+
* @template-implements TypeCoercerInterface<list<mixed>>
12+
*/
13+
class ListTypeCoercer implements TypeCoercerInterface
14+
{
15+
public function coerce(mixed $value, Context $context): array
16+
{
17+
return match (true) {
18+
\is_array($value) => \array_is_list($value) ? $value : \array_values($value),
19+
$value instanceof \Traversable => \iterator_to_array($value, false),
20+
default => throw InvalidValueException::createFromContext($context),
21+
};
22+
}
23+
}

src/Type/ListFromArrayType.php

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* @template-covariant TItem of mixed = mixed
1414
* @template-implements TypeInterface<list<TItem>>
1515
*/
16-
class ListFromIterableType implements TypeInterface
16+
class ListType implements TypeInterface
1717
{
1818
public function __construct(
1919
/**
@@ -27,7 +27,7 @@ public function __construct(
2727
*/
2828
public function match(mixed $value, Context $context): bool
2929
{
30-
return \is_iterable($value);
30+
return \is_array($value) && \array_is_list($value);
3131
}
3232

3333
public function cast(mixed $value, Context $context): array

0 commit comments

Comments
 (0)