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: | * @template E |
18: | * |
19: | * @implements Result<never, E> |
20: | */ |
21: | final readonly class Err implements Result |
22: | { |
23: | /** |
24: | * @param E $err |
25: | */ |
26: | public function __construct( |
27: | private mixed $err, |
28: | ) {} |
29: | |
30: | public function isOk(): bool |
31: | { |
32: | return false; |
33: | } |
34: | |
35: | public function isOkAnd(\Closure $predicate): bool |
36: | { |
37: | return false; |
38: | } |
39: | |
40: | public function isErr(): bool |
41: | { |
42: | return true; |
43: | } |
44: | |
45: | public function isErrAnd(\Closure $predicate): bool |
46: | { |
47: | return $predicate($this->err); |
48: | } |
49: | |
50: | /** |
51: | * @return self<E> |
52: | */ |
53: | public function map(\Closure $predicate): self |
54: | { |
55: | return $this; |
56: | } |
57: | |
58: | public function mapOr(mixed $default, \Closure $predicate): mixed |
59: | { |
60: | return $default; |
61: | } |
62: | |
63: | public function mapOrElse(\Closure $default, \Closure $predicate): mixed |
64: | { |
65: | return $default($this->err); |
66: | } |
67: | |
68: | /** |
69: | * @template F |
70: | * |
71: | * @param (\Closure(E): F) $predicate |
72: | * |
73: | * @return self<F> |
74: | */ |
75: | public function mapErr(\Closure $predicate): self |
76: | { |
77: | return new self($predicate($this->err)); |
78: | } |
79: | |
80: | public function unwrap(): never |
81: | { |
82: | $message = static fn(string $arg): string => \sprintf('Unwrapped an Err result: %s', $arg); |
83: | |
84: | if ($this->err instanceof \Throwable) { |
85: | throw new UnwrappedResultException($message($this->err->getMessage()), 0, $this->err); |
86: | } |
87: | |
88: | if (\is_scalar($this->err)) { |
89: | throw new UnwrappedResultException($message(var_export($this->err, true))); |
90: | } |
91: | |
92: | throw new UnwrappedResultException('Unwrapped an Err result.'); |
93: | } |
94: | |
95: | /** |
96: | * @template U |
97: | * |
98: | * @param U $default |
99: | * |
100: | * @return U |
101: | */ |
102: | public function unwrapOr(mixed $default): mixed |
103: | { |
104: | return $default; |
105: | } |
106: | |
107: | /** |
108: | * @template U |
109: | * |
110: | * @param (\Closure(E): U) $op |
111: | * |
112: | * @return U |
113: | */ |
114: | public function unwrapOrElse(\Closure $op): mixed |
115: | { |
116: | return $op($this->err); |
117: | } |
118: | |
119: | public function unwrapErr(): mixed |
120: | { |
121: | return $this->err; |
122: | } |
123: | |
124: | /** |
125: | * @return self<E> |
126: | */ |
127: | public function and(Result $res): self |
128: | { |
129: | return $this; |
130: | } |
131: | |
132: | /** |
133: | * @return self<E> |
134: | */ |
135: | public function andThen(\Closure $op): self |
136: | { |
137: | return $this; |
138: | } |
139: | |
140: | /** |
141: | * @template T |
142: | * @template F |
143: | * @template R of Result<T, F> |
144: | * |
145: | * @param R $res |
146: | * |
147: | * @return R |
148: | */ |
149: | public function or(Result $res): Result |
150: | { |
151: | return $res; |
152: | } |
153: | |
154: | /** |
155: | * @template T |
156: | * @template F |
157: | * @template R of Result<T, F> |
158: | * |
159: | * @param (\Closure(E): R) $op |
160: | * |
161: | * @return R |
162: | */ |
163: | public function orElse(\Closure $op): Result |
164: | { |
165: | return $op($this->err); |
166: | } |
167: | } |
168: |