Skip to content

Commit

Permalink
Merge ea8c6e2 into e1b45c2
Browse files Browse the repository at this point in the history
  • Loading branch information
azjezz committed Nov 8, 2020
2 parents e1b45c2 + ea8c6e2 commit 9bd00a7
Show file tree
Hide file tree
Showing 16 changed files with 941 additions and 95 deletions.
10 changes: 8 additions & 2 deletions src/Psl/Internal/Loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,10 @@ final class Loader
'Psl\invariant',
'Psl\invariant_violation',
'Psl\sequence',
'Psl\Type\arr',
'Psl\Type\map',
'Psl\Type\mutable_map',
'Psl\Type\vector',
'Psl\Type\mutable_vector',
'Psl\Type\array_key',
'Psl\Type\bool',
'Psl\Type\float',
Expand Down Expand Up @@ -386,7 +389,10 @@ final class Loader
'Psl\Result\Failure',
'Psl\Result\Success',
'Psl\Type\Internal\ArrayKeyType',
'Psl\Type\Internal\ArrayType',
'Psl\Type\Internal\MapType',
'Psl\Type\Internal\MutableMapType',
'Psl\Type\Internal\VectorType',
'Psl\Type\Internal\MutableVectorType',
'Psl\Type\Internal\BoolType',
'Psl\Type\Internal\FloatType',
'Psl\Type\Internal\IntersectionType',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Psl\Type\Internal;

use Psl\Collection;
use Psl\Iter;
use Psl\Str;
use Psl\Type;
Expand All @@ -14,11 +15,11 @@
* @template Tk of array-key
* @template Tv
*
* @extends Type\Type<array<Tk, Tv>>
* @extends Type\Type<Collection\MapInterface<Tk, Tv>>
*
* @internal
*/
final class ArrayType extends Type\Type
final class MapType extends Type\Type
{
/**
* @psalm-var Type\Type<Tk>
Expand All @@ -38,22 +39,27 @@ public function __construct(
Type\Type $key_type,
Type\Type $value_type
) {
$this->key_type = $key_type;
$this->key_type = $key_type;
$this->value_type = $value_type;
}

/**
* @psalm-param mixed $value
*
* @psalm-return array<Tk, Tv>
* @psalm-return Collection\MapInterface<Tk, Tv>
*
* @throws CoercionException
*/
public function coerce($value): array
public function coerce($value): Collection\MapInterface
{
if (Type\is_iterable($value)) {
$key_trace = $this->getTrace()->withFrame(Str\format('array<%s, _>', $this->key_type->toString()));
$value_trace = $this->getTrace()->withFrame(Str\format('array<_, %s>', $this->value_type->toString()));
$key_trace = $this->getTrace()->withFrame(
Str\format('%s<%s, _>', Collection\MapInterface::class, $this->key_type->toString())
);

$value_trace = $this->getTrace()->withFrame(
Str\format('%s<_, %s>', Collection\MapInterface::class, $this->value_type->toString())
);

/** @psalm-var Type\Type<Tk> $key_type */
$key_type = $this->key_type->withTrace($key_trace);
Expand All @@ -72,35 +78,39 @@ public function coerce($value): array
/** @psalm-var Tk $k */
$k = $key_type->coerce($k);
/** @psalm-var Tv $v */
$v = $value_type->coerce($v);
$v = $value_type->coerce($v);

$entries[] = [$k, $v];
}

/** @psalm-var Iter\Iterator<Tk, Tv> $iterator */
$iterator = Iter\from_entries($entries);

/** @psalm-var array<Tk, Tv> */
return Iter\to_array_with_keys($iterator);
return new Collection\Map($iterator);
}


throw CoercionException::withValue($value, $this->toString(), $this->getTrace());
}

/**
* @psalm-param mixed $value
*
* @psalm-return array<Tk, Tv>
* @psalm-return Collection\MapInterface<Tk, Tv>
*
* @psalm-assert array<Tk, Tv> $value
* @psalm-assert Collection\MapInterface<Tk, Tv> $value
*
* @throws AssertException
*/
public function assert($value): array
public function assert($value): Collection\MapInterface
{
if (Type\is_array($value)) {
$key_trace = $this->getTrace()->withFrame(Str\format('array<%s, _>', $this->key_type->toString()));
$value_trace = $this->getTrace()->withFrame(Str\format('array<_, %s>', $this->value_type->toString()));
if (Type\is_object($value) && Type\is_instanceof($value, Collection\MapInterface::class)) {
$key_trace = $this->getTrace()->withFrame(
Str\format('%s<%s, _>', Collection\MapInterface::class, $this->key_type->toString())
);

$value_trace = $this->getTrace()->withFrame(
Str\format('%s<_, %s>', Collection\MapInterface::class, $this->value_type->toString())
);

/** @psalm-var Type\Type<Tk> $key_type */
$key_type = $this->key_type->withTrace($key_trace);
Expand All @@ -119,21 +129,26 @@ public function assert($value): array
/** @psalm-var Tk $k */
$k = $key_type->assert($k);
/** @psalm-var Tv $v */
$v = $value_type->assert($v);
$v = $value_type->assert($v);
$entries[] = [$k, $v];
}

/** @psalm-var Iter\Iterator<Tk, Tv> $iterator */
$iterator = Iter\from_entries($entries);

return Iter\to_array_with_keys($iterator);
return new Collection\Map($iterator);
}

throw AssertException::withValue($value, $this->toString(), $this->getTrace());
}

public function toString(): string
{
return Str\format('array<%s, %s>', $this->key_type->toString(), $this->value_type->toString());
return Str\format(
'%s<%s, %s>',
Collection\MapInterface::class,
$this->key_type->toString(),
$this->value_type->toString(),
);
}
}
154 changes: 154 additions & 0 deletions src/Psl/Type/Internal/MutableMapType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php

declare(strict_types=1);

namespace Psl\Type\Internal;

use Psl\Collection;
use Psl\Iter;
use Psl\Str;
use Psl\Type;
use Psl\Type\Exception\AssertException;
use Psl\Type\Exception\CoercionException;

/**
* @template Tk of array-key
* @template Tv
*
* @extends Type\Type<Collection\MutableMapInterface<Tk, Tv>>
*
* @internal
*/
final class MutableMapType extends Type\Type
{
/**
* @psalm-var Type\Type<Tk>
*/
private Type\Type $key_type;

/**
* @psalm-var Type\Type<Tv>
*/
private Type\Type $value_type;

/**
* @psalm-param Type\Type<Tk> $key_type
* @psalm-param Type\Type<Tv> $value_type
*/
public function __construct(
Type\Type $key_type,
Type\Type $value_type
) {
$this->key_type = $key_type;
$this->value_type = $value_type;
}

/**
* @psalm-param mixed $value
*
* @psalm-return Collection\MutableMapInterface<Tk, Tv>
*
* @throws CoercionException
*/
public function coerce($value): Collection\MutableMapInterface
{
if (Type\is_iterable($value)) {
$key_trace = $this->getTrace()->withFrame(
Str\format('%s<%s, _>', Collection\MutableMapInterface::class, $this->key_type->toString())
);

$value_trace = $this->getTrace()->withFrame(
Str\format('%s<_, %s>', Collection\MutableMapInterface::class, $this->value_type->toString())
);

/** @psalm-var Type\Type<Tk> $key_type */
$key_type = $this->key_type->withTrace($key_trace);
/** @psalm-var Type\Type<Tv> $value_type */
$value_type = $this->value_type->withTrace($value_trace);

/**
* @psalm-var list<array{0: Tk, 1: Tv}> $entries
*/
$entries = [];
/**
* @psalm-var mixed $k
* @psalm-var mixed $v
*/
foreach ($value as $k => $v) {
/** @psalm-var Tk $k */
$k = $key_type->coerce($k);
/** @psalm-var Tv $v */
$v = $value_type->coerce($v);

$entries[] = [$k, $v];
}

/** @psalm-var Iter\Iterator<Tk, Tv> $iterator */
$iterator = Iter\from_entries($entries);

return new Collection\MutableMap($iterator);
}

throw CoercionException::withValue($value, $this->toString(), $this->getTrace());
}

/**
* @psalm-param mixed $value
*
* @psalm-return Collection\MutableMapInterface<Tk, Tv>
*
* @psalm-assert Collection\MutableMapInterface<Tk, Tv> $value
*
* @throws AssertException
*/
public function assert($value): Collection\MutableMapInterface
{
if (Type\is_object($value) && Type\is_instanceof($value, Collection\MutableMapInterface::class)) {
$key_trace = $this->getTrace()->withFrame(
Str\format('%s<%s, _>', Collection\MutableMapInterface::class, $this->key_type->toString())
);

$value_trace = $this->getTrace()->withFrame(
Str\format('%s<_, %s>', Collection\MutableMapInterface::class, $this->value_type->toString())
);

/** @psalm-var Type\Type<Tk> $key_type */
$key_type = $this->key_type->withTrace($key_trace);
/** @psalm-var Type\Type<Tv> $value_type */
$value_type = $this->value_type->withTrace($value_trace);

/**
* @psalm-var list<array{0: Tk, 1: Tv}> $entries
*/
$entries = [];
/**
* @psalm-var mixed $k
* @psalm-var mixed $v
*/
foreach ($value as $k => $v) {
/** @psalm-var Tk $k */
$k = $key_type->assert($k);
/** @psalm-var Tv $v */
$v = $value_type->assert($v);
$entries[] = [$k, $v];
}

/** @psalm-var Iter\Iterator<Tk, Tv> $iterator */
$iterator = Iter\from_entries($entries);

return new Collection\MutableMap($iterator);
}

throw AssertException::withValue($value, $this->toString(), $this->getTrace());
}

public function toString(): string
{
return Str\format(
'%s<%s, %s>',
Collection\MutableMapInterface::class,
$this->key_type->toString(),
$this->value_type->toString(),
);
}
}
Loading

0 comments on commit 9bd00a7

Please sign in to comment.