Skip to content

Commit f7dd33b

Browse files
committed
Implement the Nexus Option library
1 parent 2d878fb commit f7dd33b

15 files changed

+975
-3
lines changed

composer.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,18 @@
2828
"phpstan/phpstan-strict-rules": "^1.6",
2929
"phpunit/phpunit": "^11.2"
3030
},
31+
"replace": {
32+
"nexusphp/option": "self.version"
33+
},
3134
"minimum-stability": "dev",
3235
"prefer-stable": true,
3336
"autoload": {
3437
"psr-4": {
3538
"Nexus\\": "src/Nexus/"
36-
}
39+
},
40+
"files": [
41+
"src/Nexus/Option/functions.php"
42+
]
3743
},
3844
"autoload-dev": {
3945
"psr-4": {

phpstan-baseline.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php declare(strict_types = 1);
2+
3+
$ignoreErrors = [];
4+
$ignoreErrors[] = [
5+
// identifier: return.unusedType
6+
'message' => '#^Method Nexus\\\\Option\\\\Choice\\:\\:from\\(\\) never returns Nexus\\\\Option\\\\Some\\<T of mixed\\> so it can be removed from the return type\\.$#',
7+
'count' => 1,
8+
'path' => __DIR__ . '/src/Nexus/Option/Choice.php',
9+
];
10+
11+
return ['parameters' => ['ignoreErrors' => $ignoreErrors]];

phpstan.dist.neon

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
includes:
22
- vendor/phpstan/phpstan/conf/bleedingEdge.neon
3+
- phpstan-baseline.php
34

45
parameters:
56
phpVersion: 80200
6-
level: 8
7+
level: 9
78
tmpDir: build/phpstan
89
paths:
910
- src
@@ -16,7 +17,6 @@ parameters:
1617
- vendor/autoload.php
1718
exceptions:
1819
check:
19-
missingCheckedExceptionInThrows: true
2020
tooWideThrowType: true
2121
checkTooWideReturnTypesInProtectedAndPublicMethods: true
2222
checkUninitializedProperties: true
@@ -26,3 +26,4 @@ parameters:
2626
reportAlwaysTrueInLastCondition: true
2727
reportAnyTypeWideningInVarTag: true
2828
checkMissingCallableSignature: true
29+
treatPhpDocTypesAsCertain: false

src/Nexus/Option/Choice.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the Nexus framework.
7+
*
8+
* (c) John Paul E. Balandan, CPA <[email protected]>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Nexus\Option;
15+
16+
/**
17+
* @internal
18+
*/
19+
final class Choice
20+
{
21+
/**
22+
* Creates an option from the given `$value`.
23+
*
24+
* The value of a **None** option can be defined by assigning a `$none` value.
25+
* By default, this is equal to `null` but can be another value.
26+
*
27+
* @template T
28+
* @template S
29+
*
30+
* @param T $value
31+
* @param S $none
32+
*
33+
* @return (T is S ? None : Some<T>)
34+
*/
35+
public static function from(mixed $value, mixed $none = null): Option
36+
{
37+
if ($value === $none) {
38+
return new None();
39+
}
40+
41+
return new Some($value);
42+
}
43+
}

src/Nexus/Option/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 John Paul E. Balandan, CPA <[email protected]>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

src/Nexus/Option/None.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the Nexus framework.
7+
*
8+
* (c) John Paul E. Balandan, CPA <[email protected]>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Nexus\Option;
15+
16+
/**
17+
* @implements Option<never>
18+
*/
19+
final readonly class None implements Option
20+
{
21+
public function isSome(): bool
22+
{
23+
return false;
24+
}
25+
26+
public function isSomeAnd(\Closure $predicate): bool
27+
{
28+
return false;
29+
}
30+
31+
public function isNone(): bool
32+
{
33+
return true;
34+
}
35+
36+
public function unwrap(): mixed
37+
{
38+
throw new NoneException();
39+
}
40+
41+
public function unwrapOr(mixed $default): mixed
42+
{
43+
return $default;
44+
}
45+
46+
public function unwrapOrElse(\Closure $default): mixed
47+
{
48+
return $default();
49+
}
50+
51+
public function map(\Closure $predicate): Option
52+
{
53+
return clone $this;
54+
}
55+
56+
public function mapOr(mixed $default, \Closure $predicate): mixed
57+
{
58+
return $default;
59+
}
60+
61+
public function mapOrElse(\Closure $default, \Closure $predicate): mixed
62+
{
63+
return $default();
64+
}
65+
66+
public function and(Option $other): Option
67+
{
68+
return clone $this;
69+
}
70+
71+
public function andThen(\Closure $predicate): Option
72+
{
73+
return clone $this;
74+
}
75+
76+
public function filter(\Closure $predicate): Option
77+
{
78+
return clone $this;
79+
}
80+
81+
public function or(Option $other): Option
82+
{
83+
return $other;
84+
}
85+
86+
public function orElse(\Closure $other): Option
87+
{
88+
return $other();
89+
}
90+
91+
public function xor(Option $other): Option
92+
{
93+
return $other->isSome() ? $other : clone $this;
94+
}
95+
96+
/**
97+
* @return \EmptyIterator
98+
*/
99+
public function getIterator(): \Traversable
100+
{
101+
return new \EmptyIterator();
102+
}
103+
}

src/Nexus/Option/NoneException.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the Nexus framework.
7+
*
8+
* (c) John Paul E. Balandan, CPA <[email protected]>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Nexus\Option;
15+
16+
/**
17+
* Exception thrown when accessing the value of a `None` option.
18+
*/
19+
final class NoneException extends \UnderflowException
20+
{
21+
public function __construct()
22+
{
23+
parent::__construct('Attempting to unwrap a None option.');
24+
}
25+
}

0 commit comments

Comments
 (0)