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 <paulbalandan@gmail.com> |
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\Result; |
15: | |
16: | /** |
17: | * A PHP implementation of Rust's Result enum. |
18: | * |
19: | * `Result<T, E>` is the type used for returning and propagating errors. It is |
20: | * an enum with the variants, `Ok(T)`, representing success and containing a |
21: | * value, and `Err(E)`, representing error and containing an error value. |
22: | * |
23: | * @template T |
24: | * @template E |
25: | * |
26: | * @see https://doc.rust-lang.org/std/result/enum.Result.html |
27: | */ |
28: | interface Result |
29: | { |
30: | /** |
31: | * Returns `true` if the result is `Ok`. |
32: | * |
33: | * @phpstan-assert-if-true Ok<T> $this |
34: | * @phpstan-assert-if-false Err<E> $this |
35: | */ |
36: | public function isOk(): bool; |
37: | |
38: | /** |
39: | * Returns `true` if the result is `Ok` and the value inside of it matches a predicate. |
40: | * |
41: | * @param (\Closure(T): bool) $predicate |
42: | */ |
43: | public function isOkAnd(\Closure $predicate): bool; |
44: | |
45: | /** |
46: | * Returns `true` if the result is `Err`. |
47: | * |
48: | * @phpstan-assert-if-true Err<E> $this |
49: | * @phpstan-assert-if-false Ok<T> $this |
50: | */ |
51: | public function isErr(): bool; |
52: | |
53: | /** |
54: | * Returns `true` if the result is `Err` and the value inside of it matches a predicate. |
55: | * |
56: | * @param (\Closure(E): bool) $predicate |
57: | */ |
58: | public function isErrAnd(\Closure $predicate): bool; |
59: | |
60: | /** |
61: | * Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a |
62: | * contained `Ok` value, leaving an `Err` value untouched. |
63: | * |
64: | * @template U |
65: | * |
66: | * @param (\Closure(T): U) $predicate |
67: | * |
68: | * @return self<U, E> |
69: | */ |
70: | public function map(\Closure $predicate): self; |
71: | |
72: | /** |
73: | * Returns the provided default (if `Err`), or applies a function to the contained value |
74: | * (if `Ok`). |
75: | * |
76: | * Arguments passed to `Result::mapOr()` are eagerly evaluated; if you are passing the result |
77: | * of a method call, it is recommended to use `Result::mapOrElse()`, which is lazily |
78: | * evaluated. |
79: | * |
80: | * @template U |
81: | * |
82: | * @param U $default |
83: | * @param (\Closure(T): U) $predicate |
84: | * |
85: | * @return U |
86: | */ |
87: | public function mapOr(mixed $default, \Closure $predicate): mixed; |
88: | |
89: | /** |
90: | * Maps a `Result<T, E>` to `U` by applying fallback function `$default` to a contained |
91: | * `Err` value, or function `$predicate` to a contained `Ok` value. |
92: | * |
93: | * This method can be used to unpack a successful result while handling an error. |
94: | * |
95: | * @template U |
96: | * |
97: | * @param (\Closure(E): U) $default |
98: | * @param (\Closure(T): U) $predicate |
99: | * |
100: | * @return U |
101: | */ |
102: | public function mapOrElse(\Closure $default, \Closure $predicate): mixed; |
103: | |
104: | /** |
105: | * Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a contained |
106: | * `Err` value, leaving an `Ok` value untouched. |
107: | * |
108: | * This method can be used to pass through a successful result while handling an error. |
109: | * |
110: | * @template F |
111: | * |
112: | * @param (\Closure(E): F) $predicate |
113: | * |
114: | * @return self<T, F> |
115: | */ |
116: | public function mapErr(\Closure $predicate): self; |
117: | |
118: | /** |
119: | * Returns the contained `Ok` value. |
120: | * |
121: | * Because this method may throw, its use is generally discouraged. Instead, prefer to |
122: | * use pattern matching and handle the `Err` case explicitly, or call `Result::unwrapOr()`, |
123: | * or `Result::unwrapOrElse()`. |
124: | * |
125: | * @return T |
126: | * |
127: | * @throws UnwrappedResultException if result is `Err` |
128: | */ |
129: | public function unwrap(): mixed; |
130: | |
131: | /** |
132: | * Returns the contained `Ok` value or a provided `$default`. |
133: | * |
134: | * Arguments passed to `Result::unwrapOr()` are eagerly evaluated; if you are passing |
135: | * the result of a method call, it is recommended to use `Result::unwrapOrElse()`, |
136: | * which is lazily evaluated. |
137: | * |
138: | * @template U |
139: | * |
140: | * @param U $default |
141: | * |
142: | * @return T|U |
143: | */ |
144: | public function unwrapOr(mixed $default): mixed; |
145: | |
146: | /** |
147: | * Returns the contained `Ok` value or computes it from a closure. |
148: | * |
149: | * @template U |
150: | * |
151: | * @param (\Closure(E): U) $op |
152: | * |
153: | * @return T|U |
154: | */ |
155: | public function unwrapOrElse(\Closure $op): mixed; |
156: | |
157: | /** |
158: | * Returns the contained `Err` value. |
159: | * |
160: | * Throws if the value is an `Ok`, with a custom exception message |
161: | * provided by the `Ok`’s value. |
162: | * |
163: | * @return E |
164: | * |
165: | * @throws UnwrappedResultException if result is `Ok` |
166: | */ |
167: | public function unwrapErr(): mixed; |
168: | |
169: | /** |
170: | * Returns `$res` if the result is `Ok`, otherwise returns the `Err` value of self. |
171: | * |
172: | * Arguments passed to `Result::and()` are eagerly evaluated; if you are passing the |
173: | * result of a method call, it is recommended to use `Result::andThen()`, which is |
174: | * lazily evaluated. |
175: | * |
176: | * @template U |
177: | * |
178: | * @param self<U, E> $res |
179: | * |
180: | * @return self<U, E> |
181: | */ |
182: | public function and(self $res): self; |
183: | |
184: | /** |
185: | * Calls `$op` if the result is `Ok`, otherwise returns the `Err` value of self. |
186: | * |
187: | * This method can be used for control flow based on `Result` values. Often used to chain |
188: | * fallible operations that may return `Err`. |
189: | * |
190: | * @template U |
191: | * |
192: | * @param (\Closure(T): self<U, E>) $op |
193: | * |
194: | * @return self<U, E> |
195: | */ |
196: | public function andThen(\Closure $op): self; |
197: | |
198: | /** |
199: | * Returns `$res` if the result is `Err`, otherwise returns the `Ok` value of self. |
200: | * |
201: | * Arguments passed to `Result::or()` are eagerly evaluated; if you are passing the |
202: | * result of a method call, it is recommended to use `Result::orElse()`, which is |
203: | * lazily evaluated. |
204: | * |
205: | * @template F |
206: | * |
207: | * @param self<T, F> $res |
208: | * |
209: | * @return self<T, F> |
210: | */ |
211: | public function or(self $res): self; |
212: | |
213: | /** |
214: | * Calls `$op` if the result is `Err`, otherwise returns the `Ok` value of self. |
215: | * |
216: | * This method can be used for control flow based on result values. |
217: | * |
218: | * @template F |
219: | * |
220: | * @param (\Closure(E): self<T, F>) $op |
221: | * |
222: | * @return self<T, F> |
223: | */ |
224: | public function orElse(\Closure $op): self; |
225: | } |
226: |