Skip to content

Commit

Permalink
Simplify the Codec interface (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
ilario-pierbattista authored Apr 5, 2021
1 parent 91366ea commit 0d88c71
Show file tree
Hide file tree
Showing 22 changed files with 168 additions and 297 deletions.
14 changes: 3 additions & 11 deletions src/Codec.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,9 @@
* @template I
* @template O
*
* @implements Decoder<I, A>
* @implements Encoder<A, O>
* @implements Refiner<A>
* @extends Decoder<I, A>
* @extends Encoder<A, O>
*/
interface Codec extends Decoder, Encoder, Refiner
interface Codec extends Decoder, Encoder
{
/**
* @param mixed $i
*
* @return static
* @psalm-assert I $i
*/
public function forceCheckPrecondition($i);
}
26 changes: 7 additions & 19 deletions src/Codecs.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@

namespace Facile\PhpCodec;

use Facile\PhpCodec\Internal\Arrays\ListType;
use Facile\PhpCodec\Internal\Arrays\ListCodec;
use Facile\PhpCodec\Internal\Arrays\MapType;
use Facile\PhpCodec\Internal\Combinators\ClassFromArray;
use Facile\PhpCodec\Internal\Combinators\ComposeType;
use Facile\PhpCodec\Internal\Combinators\UnionType;
use Facile\PhpCodec\Internal\Experimental\AssociativeArrayType;
use Facile\PhpCodec\Internal\Combinators\ComposeCodec;
use Facile\PhpCodec\Internal\Combinators\UnionCodec;
use Facile\PhpCodec\Internal\Primitives\BoolType;
use Facile\PhpCodec\Internal\Primitives\FloatType;
use Facile\PhpCodec\Internal\Primitives\IntType;
use Facile\PhpCodec\Internal\Primitives\LiteralType;
use Facile\PhpCodec\Internal\Primitives\NullType;
use Facile\PhpCodec\Internal\Primitives\StringType;
use Facile\PhpCodec\Internal\Type;
use Facile\PhpCodec\Internal\Useful\DateTimeFromIsoStringType;
use Facile\PhpCodec\Internal\Useful\IntFromStringType;
use Facile\PhpCodec\Internal\Useful\RegexType;
Expand Down Expand Up @@ -100,17 +98,7 @@ public static function dateTimeFromIsoString(): Codec
*/
public static function listt(Codec $itemCodec): Codec
{
return new ListType($itemCodec);
}

/**
* @param non-empty-array<string, Type> $props
*
* @return Codec<array, mixed, array>
*/
public static function associativeArray(array $props): Codec
{
return new AssociativeArrayType($props);
return new ListCodec($itemCodec);
}

/**
Expand Down Expand Up @@ -167,7 +155,7 @@ public static function pipe(
?Codec $e = null
): Codec {
// Order is important: composition is not commutative
return new ComposeType(
return new ComposeCodec(
$a,
$c instanceof Codec
? self::pipe($b, $c, $d, $e)
Expand All @@ -188,9 +176,9 @@ public static function union(Codec $a, Codec $b, Codec ...$others): Codec
return \array_reduce(
$others,
static function (Codec $carry, Codec $current): Codec {
return new UnionType($current, $carry);
return new UnionCodec($current, $carry);
},
new UnionType($a, $b)
new UnionCodec($a, $b)
);
}

Expand Down
53 changes: 53 additions & 0 deletions src/ConcreteCodec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Facile\PhpCodec;

use Facile\PhpCodec\Validation\Context;
use Facile\PhpCodec\Validation\Validation;

/**
* @template A
* @template I
* @template O
*
* @implements Codec<A, I, O>
*/
class ConcreteCodec implements Codec
{
/** @var Decoder<I, A> */
private $decoder;
/** @var Encoder<A, O> */
private $encoder;

/**
* @param Decoder<I, A> $decoder
* @param Encoder<A, O> $encoder
*/
public function __construct(Decoder $decoder, Encoder $encoder)
{
$this->decoder = $decoder;
$this->encoder = $encoder;
}

public function validate($i, Context $context): Validation
{
return $this->decoder->validate($i, $context);
}

public function decode($i): Validation
{
return $this->decoder->decode($i);
}

public function getName(): string
{
return $this->decoder->getName();
}

public function encode($a)
{
return $this->encoder->encode($a);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@
namespace Facile\PhpCodec\Internal\Arrays;

use Facile\PhpCodec\Codec;
use Facile\PhpCodec\Internal\Encode;
use Facile\PhpCodec\Internal\Type;
use function Facile\PhpCodec\Internal\standardDecode;
use Facile\PhpCodec\Validation\Context;
use Facile\PhpCodec\Validation\ContextEntry;
use Facile\PhpCodec\Validation\Validation;

/**
* @template T
*
* @extends Type<list<T>, mixed, list<T>>
* @implements Codec<list<T>, mixed, list<T>>
*/
class ListType extends Type
class ListCodec implements Codec
{
/** @var Codec<T, mixed, T> */
private $itemCodec;
Expand All @@ -26,11 +25,6 @@ class ListType extends Type
*/
public function __construct(Codec $itemCodec)
{
parent::__construct(
$itemCodec->getName() . '[]',
new ListRefiner($itemCodec),
Encode::identity()
);
$this->itemCodec = $itemCodec;
}

Expand Down Expand Up @@ -60,4 +54,19 @@ public function validate($i, Context $context): Validation

return Validation::sequence($validation);
}

public function decode($i): Validation
{
return standardDecode($this, $i);
}

public function getName(): string
{
return $this->itemCodec->getName() . '[]';
}

public function encode($a)
{
return $a;
}
}
11 changes: 0 additions & 11 deletions src/Internal/Combinators/ClassFromArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@

use Facile\PhpCodec\Codec;
use function Facile\PhpCodec\destructureIn;
use Facile\PhpCodec\Internal\Arrays\MapRefiner;
use Facile\PhpCodec\Internal\Encode;
use function Facile\PhpCodec\Internal\nameFromProps;
use Facile\PhpCodec\Internal\PreconditionFailureExcepion;
use Facile\PhpCodec\Internal\Primitives\InstanceOfRefiner;
use Facile\PhpCodec\Internal\Type;
use Facile\PhpCodec\Internal\Undefined;
Expand Down Expand Up @@ -65,13 +63,4 @@ public function validate($i, Context $context): Validation
Validation::reduceToSuccessOrAllFailures($validations)
);
}

public function forceCheckPrecondition($i)
{
if (! (new MapRefiner())->is($i)) {
throw PreconditionFailureExcepion::create('array<string, mixed>', $i);
}

return $this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
namespace Facile\PhpCodec\Internal\Combinators;

use Facile\PhpCodec\Codec;
use Facile\PhpCodec\Internal\Encode;
use Facile\PhpCodec\Internal\Type;
use function Facile\PhpCodec\Internal\standardDecode;
use Facile\PhpCodec\Validation\Context;
use Facile\PhpCodec\Validation\Validation;

Expand All @@ -17,12 +16,12 @@
* @template B
* @template OB
*
* Type<A, IA, OA>
* Type<B, A, OB>
* Codec<A, IA, OA>
* Codec<B, A, OB>
*
* @extends Type<B, IA, OB>
* @implements Codec<B, IA, OB>
*/
class ComposeType extends Type
class ComposeCodec implements Codec
{
/** @var Codec<A, IA, OA> */
private $a;
Expand All @@ -39,16 +38,13 @@ public function __construct(
) {
$this->a = $a;
$this->b = $b;

parent::__construct(
$b->getName(),
$b,
Encode::fromCodec($b)
);
}

/**
* @param IA $i
* @param IA $i
* @param Context $context
*
* @return Validation<B>
*/
public function validate($i, Context $context): Validation
{
Expand All @@ -57,9 +53,24 @@ public function validate($i, Context $context): Validation
* @param A $aValue
*/
function ($aValue) use ($context): Validation {
return $this->b->forceCheckPrecondition($aValue)->validate($aValue, $context);
return $this->b->validate($aValue, $context);
},
$this->a->forceCheckPrecondition($i)->validate($i, $context)
$this->a->validate($i, $context)
);
}

public function decode($i): Validation
{
return standardDecode($this, $i);
}

public function getName(): string
{
return $this->b->getName();
}

public function encode($a)
{
return $this->b->encode($a);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@
namespace Facile\PhpCodec\Internal\Combinators;

use Facile\PhpCodec\Codec;
use Facile\PhpCodec\Internal\Encode;
use Facile\PhpCodec\Internal\Type;
use function Facile\PhpCodec\Internal\standardDecode;
use Facile\PhpCodec\Validation\Context;
use Facile\PhpCodec\Validation\Validation;
use Facile\PhpCodec\Validation\ValidationSuccess;

/**
* @template A
* @template B
* @extends Type<A|B, mixed, A|B>
* @implements Codec<A|B, mixed, A|B>
*/
class UnionType extends Type
class UnionCodec implements Codec
{
/** @var Codec<A, mixed, A> */
private $a;
Expand All @@ -31,34 +30,34 @@ public function __construct(
Codec $a,
Codec $b
) {
$name = \sprintf(
'%s | %s',
$a->getName(),
$b->getName()
);

parent::__construct(
$name,
new UnionRefiner($a, $b),
Encode::identity()
);
$this->a = $a;
$this->b = $b;
}

public function validate($i, Context $context): Validation
{
$va = $this->a
->forceCheckPrecondition($i)
->validate($i, $context);
$va = $this->a->validate($i, $context);

if ($va instanceof ValidationSuccess) {
/** @var ValidationSuccess<A> */
return $va;
}

return $this->b
->forceCheckPrecondition($i)
->validate($i, $context);
return $this->b->validate($i, $context);
}

public function decode($i): Validation
{
return standardDecode($this, $i);
}

public function getName(): string
{
return \sprintf('%s | %s', $this->a->getName(), $this->b->getName());
}

public function encode($a)
{
return $a;
}
}
Loading

0 comments on commit 0d88c71

Please sign in to comment.