Skip to content

Commit 9b02bd3

Browse files
authored
Implemented callable codec (#18) (#21)
1 parent 5c979b6 commit 9b02bd3

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed

src/Codecs.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Facile\PhpCodec\Internal\Combinators\UnionCodec;
1313
use Facile\PhpCodec\Internal\IdentityEncoder;
1414
use Facile\PhpCodec\Internal\Primitives\BoolType;
15+
use Facile\PhpCodec\Internal\Primitives\CallableDecoder;
1516
use Facile\PhpCodec\Internal\Primitives\FloatType;
1617
use Facile\PhpCodec\Internal\Primitives\IntType;
1718
use Facile\PhpCodec\Internal\Primitives\MixedDecoder;
@@ -227,4 +228,12 @@ public static function mixed(): Codec
227228
{
228229
return self::fromDecoder(new MixedDecoder());
229230
}
231+
232+
/**
233+
* @return Codec<callable, mixed, callable>
234+
*/
235+
public static function callable(): Codec
236+
{
237+
return self::fromDecoder(new CallableDecoder());
238+
}
230239
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Facile\PhpCodec\Internal\Primitives;
6+
7+
use Facile\PhpCodec\Decoder;
8+
use function Facile\PhpCodec\Internal\standardDecode;
9+
use Facile\PhpCodec\Validation\Context;
10+
use Facile\PhpCodec\Validation\Validation;
11+
12+
/**
13+
* @implements Decoder<mixed, callable>
14+
*/
15+
class CallableDecoder implements Decoder
16+
{
17+
public function validate($i, Context $context): Validation
18+
{
19+
return \is_callable($i)
20+
? Validation::success($i)
21+
: Validation::failure($i, $context);
22+
}
23+
24+
public function decode($i): Validation
25+
{
26+
return standardDecode($this, $i);
27+
}
28+
29+
public function getName(): string
30+
{
31+
return 'callable';
32+
}
33+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Facile\PhpCodec\Internal\Primitives;
6+
7+
use Eris\Generator as g;
8+
use Eris\TestTrait;
9+
use Facile\PhpCodec\Codecs;
10+
use Tests\Facile\PhpCodec\BaseTestCase;
11+
use Tests\Facile\PhpCodec\GeneratorUtils;
12+
13+
class CallableDecoderTest extends BaseTestCase
14+
{
15+
use TestTrait;
16+
17+
public function testLaws(): void
18+
{
19+
$this
20+
->forAll(
21+
g\oneOf(
22+
GeneratorUtils::scalar(),
23+
g\map(
24+
function ($x): callable {
25+
return static function () use ($x) {
26+
return $x;
27+
};
28+
},
29+
GeneratorUtils::scalar()
30+
),
31+
g\map(
32+
function ($x): callable {
33+
return new class($x) {
34+
private $n;
35+
36+
public function __construct($n)
37+
{
38+
$this->n = $n;
39+
}
40+
41+
public function __invoke()
42+
{
43+
return $this->n;
44+
}
45+
};
46+
},
47+
GeneratorUtils::scalar()
48+
),
49+
g\constant('date'),
50+
g\constant([T::class, 'm'])
51+
),
52+
g\oneOf(
53+
g\map(
54+
function ($x): callable {
55+
return static function () use ($x) {
56+
return $x;
57+
};
58+
},
59+
GeneratorUtils::scalar()
60+
),
61+
g\map(
62+
function ($x): callable {
63+
return new class($x) {
64+
private $n;
65+
66+
public function __construct($n)
67+
{
68+
$this->n = $n;
69+
}
70+
71+
public function __invoke()
72+
{
73+
return $this->n;
74+
}
75+
};
76+
},
77+
GeneratorUtils::scalar()
78+
),
79+
g\constant('date'),
80+
g\constant([T::class, 'm'])
81+
)
82+
)
83+
->then(self::codecLaws(Codecs::callable()));
84+
}
85+
}
86+
87+
class T
88+
{
89+
public static function m(): int
90+
{
91+
return 1;
92+
}
93+
}

0 commit comments

Comments
 (0)