1010 * Will catch exceptions and return them as a value.
1111 *
1212 * @template T
13+ * @template E
1314 */
1415class TryBox
1516{
1617 /**
1718 * @template U
1819 * @param U $value
19- * @return TryBox<U>
20+ * @return TryBox<U, null >
2021 */
2122 public static function of ($ value ): TryBox
2223 {
23- return new self ($ value );
24+ /** @var TryBox<U, null> $box */
25+ $ box = new self ($ value , null );
26+
27+ return $ box ;
2428 }
2529
2630 /**
2731 * @param T $value
2832 */
29- public function __construct (private mixed $ value )
30- {
33+ public function __construct (
34+ private $ value ,
35+ private ?Throwable $ error = null
36+ ) {
3137 }
3238
3339 /**
3440 * Apply a transformation function to the value.
3541 *
3642 * @template U
3743 * @param callable(T): U $callback
38- * @return TryBox<Throwable >|TryBox<U >
44+ * @return TryBox<U, null >|TryBox<T, Throwable >
3945 */
4046 public function map (callable $ callback ): TryBox
4147 {
42- return $ this ->value instanceof Throwable
43- ? $ this
44- : $ this ->transform ($ callback );
45- }
46-
47- /**
48- * Apply a transformation function to the value.
49- * Will catch exceptions and return them as a value.
50- *
51- * @template U
52- * @param callable(T): U $callback
53- * @return TryBox<U>|TryBox<Throwable>
54- */
55- private function transform (callable $ callback ): TryBox
56- {
57- try {
58- return new self ($ callback ($ this ->value ));
59- } catch (Throwable $ e ) {
60- return new self ($ e );
48+ if ($ this ->error !== null ) {
49+ return $ this ;
6150 }
62- }
6351
64- /**
65- * Apply a transformation function to the box itself
66- *
67- * @template U
68- * @param callable(self<T>): TryBox<U> $callback
69- * @return TryBox<U>|TryBox<Throwable>
70- */
71- public function mod (callable $ callback ): TryBox
72- {
73- try {
74- return $ callback ($ this );
75- } catch (Throwable $ e ) {
76- return new self ($ e );
77- }
52+ return $ this ->try ($ callback );
7853 }
7954
8055 /**
8156 * Unbox the value, which might be anything including a throwable.
8257 *
83- * @return T
58+ * @return Throwable| T
8459 */
8560 public function value ()
8661 {
87- return $ this ->value ;
62+ return $ this ->error ?? $ this -> value ;
8863 }
8964
90-
9165 /**
9266 * @return T
9367 *
9468 * @throws Throwable
9569 */
96- public function rip (): mixed
70+ public function rip ()
9771 {
98- if ($ this ->value instanceof Throwable ) {
99- throw $ this ->value ;
72+ if ($ this ->error !== null ) {
73+ throw $ this ->error ;
10074 }
10175
102- assert (($ this ->value instanceof Throwable) === false );
103-
10476 return $ this ->value ;
10577 }
10678
10779 /**
108- * Assert that the value is equal to the expected value.
109- *
110- * @param T $expected
111- * @return TryBox<T>|TryBox<Throwable>
80+ * @template U
81+ * @param callable(T):U $callback
82+ * @return TryBox<U, null>|TryBox<T, Throwable>
11283 */
113- public function assert ( mixed $ expected ): TryBox
84+ private function try ( callable $ callback ): TryBox
11485 {
11586 try {
116- return $ this ->performAssertion ($ expected );
87+ /** @var TryBox<U, null> $result */
88+ $ result = new self ($ callback ($ this ->value ), null );
11789 } catch (Throwable $ e ) {
118- return new self ($ e );
119- }
120- }
121-
122- /**
123- * Run an assertion against the value.
124- * Example of a simple strict equality check: ->assert(5)
125- * Example of a callback check: ->assert(fn($x) => $x > 5)
126- *
127- * @template U
128- * @param U|callable(T):bool $check
129- * @return TryBox<T>|TryBox<Throwable>
130- */
131- public function performAssertion (mixed $ check , string $ message = '' ): TryBox
132- {
133- $ isClosure = is_callable ($ check );
134-
135- $ pass = $ isClosure
136- ? $ check ($ this ->value )
137- : $ this ->value === $ check ;
138-
139- if (! $ pass ) {
140- $ report = $ isClosure
141- ? 'Value did not pass the callback check. '
142- : sprintf (
143- 'Failed asserting that two values are the same. Expected %s, got %s. ' ,
144- var_export ($ check , true ),
145- var_export ($ this ->value , true )
146- );
147-
148- if ($ message !== '' ) {
149- $ report = $ message . ' | ' . $ report ;
150- }
151-
152- throw new LogicException ($ report );
90+ /** @var TryBox<T, Throwable> $result */
91+ $ result = new self ($ this ->value , $ e );
15392 }
15493
155- return $ this ;
94+ return $ result ;
15695 }
15796}
0 commit comments