File tree 9 files changed +96
-0
lines changed
9 files changed +96
-0
lines changed Original file line number Diff line number Diff line change @@ -52,4 +52,9 @@ public function getOrThrow(\Throwable $e)
52
52
{
53
53
throw $ e ;
54
54
}
55
+
56
+ public function ensure (callable $ condition , $ else ): ResultInterface
57
+ {
58
+ return $ this ;
59
+ }
55
60
}
Original file line number Diff line number Diff line change @@ -34,4 +34,9 @@ public function getOrThrow(\Throwable $e)
34
34
{
35
35
throw $ e ;
36
36
}
37
+
38
+ public function ensure (callable $ condition ): Option
39
+ {
40
+ return $ this ;
41
+ }
37
42
}
Original file line number Diff line number Diff line change @@ -14,6 +14,7 @@ abstract class Option
14
14
private static ?None $ none = null ;
15
15
16
16
/**
17
+ * @psalm-pure
17
18
* @template TNew
18
19
* @param TNew $value
19
20
* @return Some<TNew>
@@ -24,10 +25,12 @@ public static function some($value): Some
24
25
}
25
26
26
27
/**
28
+ * @psalm-pure
27
29
* @return None
28
30
*/
29
31
public static function none (): None
30
32
{
33
+ /** @psalm-suppress ImpureStaticProperty */
31
34
return self ::$ none ??= new None ();
32
35
}
33
36
@@ -113,6 +116,16 @@ abstract public function getOrElse($else);
113
116
*/
114
117
abstract public function getOrThrow (\Throwable $ e );
115
118
119
+ /**
120
+ * Ensures that Some value also validates against the given condition,
121
+ * Otherwise returns None.
122
+ *
123
+ * @return Option<TValue>
124
+ *
125
+ * @param callable(TValue):bool $condition
126
+ */
127
+ abstract public function ensure (callable $ condition ): Option ;
128
+
116
129
/**
117
130
* @template TElse
118
131
* @param TElse $else
Original file line number Diff line number Diff line change 13
13
abstract class Result implements ResultInterface
14
14
{
15
15
/**
16
+ * @psalm-pure
16
17
* @template T
17
18
* @param T $value
18
19
* @return Success<T>
@@ -23,6 +24,7 @@ public static function success($value): Success
23
24
}
24
25
25
26
/**
27
+ * @psalm-pure
26
28
* @template T
27
29
* @param T $value
28
30
* @return Error<T>
Original file line number Diff line number Diff line change @@ -78,4 +78,18 @@ public function getOr(callable $map);
78
78
* @return TSuccess|never-return
79
79
*/
80
80
public function getOrThrow (\Throwable $ e );
81
+
82
+ /**
83
+ * Ensures that the Success value also validates against the given condition,
84
+ * Otherwise returns an Error with a given value.
85
+ *
86
+ * If this Result is already an Error, nothing will change.
87
+ *
88
+ * @template TNewError
89
+ *
90
+ * @param callable(TSuccess):bool $condition
91
+ * @param TNewError $else
92
+ * @return ResultInterface<TSuccess, TError|TNewError>
93
+ */
94
+ public function ensure (callable $ condition , $ else ): self ;
81
95
}
Original file line number Diff line number Diff line change @@ -46,4 +46,11 @@ public function getOrThrow(\Throwable $e)
46
46
{
47
47
return $ this ->value ;
48
48
}
49
+
50
+ public function ensure (callable $ condition ): Option
51
+ {
52
+ return $ condition ($ this ->value )
53
+ ? $ this
54
+ : Option::none ();
55
+ }
49
56
}
Original file line number Diff line number Diff line change @@ -51,4 +51,11 @@ public function getOrThrow(\Throwable $e)
51
51
{
52
52
return $ this ->value ;
53
53
}
54
+
55
+ public function ensure (callable $ condition , $ else ): ResultInterface
56
+ {
57
+ return $ condition ($ this ->value )
58
+ ? $ this
59
+ : Result::error ($ else );
60
+ }
54
61
}
Original file line number Diff line number Diff line change @@ -124,4 +124,26 @@ public function testToNullableNone(): void
124
124
$ nullable = $ option ->toNullable ();
125
125
self ::assertNull ($ nullable );
126
126
}
127
+
128
+ public function testEnsureSomeReturningTrue (): void
129
+ {
130
+ $ option = Option::some (111 );
131
+ $ ensured = $ option ->ensure (fn (int $ i ) => $ i > 100 );
132
+ self ::assertEquals (111 , $ ensured ->getOrElse (null ));
133
+ }
134
+
135
+ public function testEnsureSomeReturningFalse (): void
136
+ {
137
+ $ option = Option::some (111 );
138
+ $ ensured = $ option ->ensure (fn (int $ i ) => $ i < 100 );
139
+ self ::assertEquals (null , $ ensured ->getOrElse (null ));
140
+ }
141
+
142
+ public function testEnsureNone (): void
143
+ {
144
+ /** @var Option<int> $option */
145
+ $ option = Option::none ();
146
+ $ ensured = $ option ->ensure (fn (int $ i ) => $ i > 100 );
147
+ self ::assertEquals (null , $ ensured ->getOrElse (null ));
148
+ }
127
149
}
Original file line number Diff line number Diff line change @@ -173,4 +173,25 @@ public function testErrors(): void
173
173
174
174
self ::assertEquals ([ 3 , 5 ], Result::extractErrors ($ results ));
175
175
}
176
+
177
+ public function testEnsureSuccessReturningTrue (): void
178
+ {
179
+ $ result = Result::success (123 );
180
+ $ ensured = $ result ->ensure (fn (int $ i ) => $ i > 100 , 'failed ' );
181
+ self ::assertEquals (123 , $ ensured ->get ());
182
+ }
183
+
184
+ public function testEnsureSuccessReturningFalse (): void
185
+ {
186
+ $ result = Result::success (123 );
187
+ $ ensured = $ result ->ensure (fn (int $ i ) => $ i < 100 , 'failed ' );
188
+ self ::assertEquals ('failed ' , $ ensured ->get ());
189
+ }
190
+
191
+ public function testEnsureErrorDoesNotChangePreviousError (): void
192
+ {
193
+ $ result = Result::error ('old error ' );
194
+ $ ensured = $ result ->ensure (fn (int $ i ) => $ i > 100 , 'new error ' );
195
+ self ::assertEquals ('old error ' , $ ensured ->get ());
196
+ }
176
197
}
You can’t perform that action at this time.
0 commit comments