File Coverage

blib/lib/Result/Trait.pm
Criterion Covered Total %
statement 177 190 93.1
branch 82 120 68.3
condition 23 63 36.5
subroutine 36 39 92.3
pod 23 23 100.0
total 341 435 78.3


line stmt bran cond sub pod time code
1 10     10   227887 use 5.014;
  10         36  
2 10     10   56 use strict;
  10         17  
  10         207  
3 10     10   52 use warnings;
  10         31  
  10         354  
4              
5             # I don't normally do inline pod, but...
6              
7             =pod
8              
9             =encoding utf-8
10              
11             =head1 NAME
12              
13             Result::Trait - the trait which all Result objects implement
14              
15             =head1 SYNOPSIS
16              
17             use results;
18            
19             sub to_uppercase {
20             my $str = shift;
21            
22             return err( "Cannot uppercase a reference." ) if ref $str;
23             return err( "Cannot uppercase undef." ) if not defined $str;
24            
25             return ok( uc $str );
26             }
27            
28             my $got = to_uppercase( "hello world" )->unwrap();
29              
30             =head1 DESCRIPTION
31              
32             The C, C, and C functions from L return objects
33             which have the methods described in this trait.
34              
35             =head2 Methods
36              
37             These methods are available on all Result objects.
38              
39             Many of them will mark the Result as "handled". All Results should be
40             handled.
41              
42             =cut
43              
44 10     10   56 use overload ();
  10         50  
  10         204  
45 10     10   52 use Carp ();
  10         22  
  10         173  
46 10     10   64 use Scalar::Util ();
  10         25  
  10         674  
47             require results;
48              
49             package Result::Trait;
50              
51             our $AUTHORITY = 'cpan:TOBYINK';
52             our $VERSION = '0.004';
53              
54 10     10   5916 use Role::Tiny;
  10         44131  
  10         90  
55              
56             requires qw(
57             _handled
58             _peek
59             _peek_err
60             is_err
61             is_ok
62             );
63              
64             ##############################################################################
65              
66             # Check if we're in global destruction.
67             #
68              
69             sub __IN_GLOBAL_DESTRUCTION__ {
70 127     127   434 ${^GLOBAL_PHASE} eq 'DESTRUCT'
71             }
72              
73             ##############################################################################
74              
75             # Check if something is a coderef.
76             #
77              
78             sub __IS_CODE__ {
79 33     33   136 ref($_[0]) eq 'CODE'
80             }
81              
82             ##############################################################################
83              
84             # Check if something is a Result object.
85             #
86              
87             sub __IS_RESULT__ {
88 17 100 66 17   330 Scalar::Util::blessed( $_[0] )
89             and $_[0]->can( 'DOES' )
90             and $_[0]->DOES( __PACKAGE__ )
91             }
92              
93             ##############################################################################
94              
95             # Check if something is a type constraint object.
96             #
97              
98             sub __IS_TYPE__ {
99 6 50 33 6   82 Scalar::Util::blessed( $_[0] )
100             and $_[0]->can( 'check' )
101             and $_[0]->can( 'get_message' )
102             }
103              
104             ##############################################################################
105              
106             # Check if something is a blessed exception we can work with.
107             #
108              
109             sub __IS_FRIENDLY_EXCEPTION__ {
110 3 100 66 3   58 Scalar::Util::blessed( $_[0] )
111             and $_[0]->can( 'DOES' )
112             and $_[0]->DOES( 'results::exceptions' )
113             }
114              
115             ##############################################################################
116              
117             # Helper for implementations of this trait to use.
118             #
119              
120             sub __OVERLOAD_ARGS__ {
121 30     30   88 my ( $class, $nickname, $peek_method ) = @_;
122              
123             return (
124 0     0   0 bool => sub { !!1 },
125 3     3   8 q[""] => sub { "$nickname(@{[ $_[0]->$peek_method ]})" },
  3         13  
126 30         386 fallback => 1,
127             );
128             }
129              
130             ##############################################################################
131              
132             =head3 C<< $result->and( $other_result ) >>
133              
134             Returns C<< $result >> if it is an err. Returns C<< $other_result >> otherwise.
135             The effect of this is that C returns an ok Result only if both Results are
136             ok, and an err Result otherwise.
137              
138             C<< $result >> is considered to be handled if it was ok.
139             C<< $other_result >> is not considered to have been handled.
140              
141             =head4 Example
142              
143             Supposing the C<< create_file() >> and C<< upload_file() >> functions
144             return Results to indicate success:
145              
146             my $result = create_file()->and( upload_file() );
147            
148             if ( $result->is_err() ) {
149             warn $result->unwrap_err;
150             }
151             else {
152             say "File created and uploaded successfully!";
153             $result->unwrap();
154             }
155              
156             Note that if the C<< create_file() >> function failed, the C<< upload_file() >>
157             will still be run even though it is destined to fail, because method arguments
158             are evaluated eagerly in Perl. For a solution, see C<< and_then() >>.
159              
160             =cut
161              
162             sub and {
163 4     4 1 21 my ( $self, $res ) = @_;
164 4 50 33     14 @_ == 2 && __IS_RESULT__($res)
165             or Carp::croak( 'Usage: $result->and( $other_result )' );
166              
167 4 100       136 return $self if $self->is_err();
168              
169 2         8 $self->_handled( !!1 );
170 2         10 $res;
171             }
172              
173             ##############################################################################
174              
175             =head3 C<< $result->and_then( sub { THEN } ) >>
176              
177             The coderef is expected to return a Result object.
178              
179             Returns C<< $result >> if it is an err.
180              
181             If C<< $result >> is ok, then executes the coderef and returns the coderef's
182             Result. Within the coderef, the unwrapped value of C<< $result >> in scalar
183             context is available as C<< $_ >> and in list context is available as C<< @_ >>.
184              
185             C<< $result >> is considered to be handled if it was ok.
186             C<< $other_result >> is not considered to have been handled.
187              
188             Effectively a version of C with lazy evaluation of the second
189             operand.
190              
191             =head4 Example
192              
193             Supposing the C<< create_file() >> and C<< upload_file() >> functions
194             return Results to indicate success:
195              
196             my $result = create_file()->and_then( sub { upload_file() } );
197            
198             if ( $result->is_err() ) {
199             warn $result->unwrap_err;
200             }
201             else {
202             say "File created and uploaded successfully!";
203             $result->unwrap();
204             }
205              
206             =cut
207              
208             sub and_then {
209 3     3 1 5 my ( $self, $op ) = @_;
210 3 50 33     13 @_ == 2 && __IS_CODE__($op)
211             or Carp::croak( 'Usage: $result->and_then( sub { ...; return $other_result } )' );
212              
213 3 100       10 return $self if $self->is_err();
214              
215 2         6 local $_ = $self->_peek;
216 2         7 my $res = $op->( $self->unwrap() );
217 2 50       8 __IS_RESULT__($res)
218             or Carp::croak( 'Coderef did not return a Result' );
219 2         53 $res;
220             }
221              
222             ##############################################################################
223              
224             =head3 C<< $result->err() >>
225              
226             For err Results, the same as C. For ok Results, returns nothing.
227              
228             The Result is considered to be handled.
229              
230             =cut
231              
232             sub err {
233 2     2 1 15 my ( $self ) = @_;
234 2 50       7 @_ == 1
235             or Carp::croak( 'Usage: $result->err()' );
236              
237 2         7 $self->_handled( !!1 );
238              
239 2 100       7 return $self->unwrap_err() if $self->is_err();
240              
241 1         6 return;
242             }
243              
244             ##############################################################################
245              
246             =head3 C<< $result->expect( $msg ) >>
247              
248             For ok Results, unwraps the result.
249              
250             For err Results, throws an exception with the given message.
251              
252             The Result is considered to be handled.
253              
254             =cut
255              
256             sub expect {
257 2     2 1 32 my ( $self, $message ) = @_;
258 2 50       8 @_ == 2
259             or Carp::croak( 'Usage: $result->expect( $message )' );
260              
261 2 100       7 return $self->unwrap() if $self->is_ok();
262              
263 1         5 $self->_handled( !!1 );
264              
265 1         2 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
266 1         98 Carp::croak( $message );
267             }
268              
269             ##############################################################################
270              
271             =head3 C<< $result->expect_err( $msg ) >>
272              
273             For ok Results, throws an exception with the given message.
274              
275             For err Results, unwraps the result.
276              
277             This is the inverse of C<< expect() >>.
278              
279             The Result is considered to be handled.
280              
281             =cut
282              
283             sub expect_err {
284 2     2 1 31 my ( $self, $message ) = @_;
285 2 50       7 @_ == 2
286             or Carp::croak( 'Usage: $result->expect_err( $message )' );
287              
288 2 100       5 return $self->unwrap_err() if $self->is_err();
289              
290 1         5 $self->_handled( !!1 );
291              
292 1         3 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
293 1         109 Carp::croak( $message );
294             }
295              
296             ##############################################################################
297              
298             =head3 C<< $result->flatten() >>
299              
300             If this is an ok Result containing another Result, returns the inner Result.
301             The outer Result is considered to be handled.
302              
303             If this is an ok Result not containing another Result, throws.
304              
305             If this is an err Result, returns self. The Result is not considered handled.
306              
307             Note this is not a recursive flatten. It only flattens one level of Results.
308              
309             =cut
310              
311             sub flatten {
312 4     4 1 48 my ( $self ) = @_;
313 4 50       10 @_ == 1
314             or Carp::croak( 'Usage: $result->flatten()' );
315              
316 4 100       14 if ( $self->is_ok() ) {
317 3         8 my $inner = $self->unwrap();
318 3 100       8 __IS_RESULT__($inner)
319             or Carp::croak( 'Result did not contain a Result' );
320 2         58 return $inner;
321             }
322              
323 1         8 return $self;
324             }
325              
326             ##############################################################################
327              
328             =head3 C<< $result->inspect( sub { PEEK } ) >>
329              
330             If this is an ok Result, runs the coderef. Within the coderef, the unwrapped
331             value in scalar context is available as C<< $_ >> and in list context is
332             available as C<< @_ >>.
333              
334             If this is an err Result, does nothing.
335              
336             Always returns self, making it suitable for chaining.
337              
338             The Result is not considered handled.
339              
340             =cut
341              
342             sub inspect {
343 2     2 1 20 my ( $self, $f ) = @_;
344 2 50 33     10 @_ == 2 && __IS_CODE__( $f )
345             or Carp::croak( 'Usage: $result->inspect( sub { ... } )' );
346              
347 2 100       11 if ( $self->is_ok() ) {
348 1         3 local $_ = $self->_peek;
349 1         4 $f->( $self->_peek );
350             }
351              
352 2         23 return $self;
353             }
354              
355             ##############################################################################
356              
357             =head3 C<< $result->inspect_err( sub { PEEK } ) >>
358              
359             If this is an ok Result, does nothing.
360              
361             If this is an err Result, runs the coderef. Within the coderef, the unwrapped
362             error in scalar context is available as C<< $_ >> and in list context is
363             available as C<< @_ >>.
364              
365             Always returns self, making it suitable for chaining.
366              
367             This is the inverse of C<< inspect() >>.
368              
369             The Result is not considered handled.
370              
371             =cut
372              
373             sub inspect_err {
374 2     2 1 21 my ( $self, $f ) = @_;
375 2 50 33     9 @_ == 2 && __IS_CODE__( $f )
376             or Carp::croak( 'Usage: $result->inspect( sub { ... } )' );
377              
378 2 100       8 if ( $self->is_err() ) {
379 1         7 local $_ = $self->_peek_err;
380 1         4 $f->( $self->_peek_err );
381             }
382              
383 2         8 return $self;
384             }
385              
386             ##############################################################################
387              
388             =head3 C<< $result->is_err() >>
389              
390             Returns true if and only if this is an err Result.
391              
392             The Result is not considered handled.
393              
394             =cut
395              
396             # Must be implemented by classes consuming this role.
397              
398             ##############################################################################
399              
400             =head3 C<< $result->is_ok() >>
401              
402             Returns true if and only if this is an ok Result.
403              
404             The Result is not considered handled.
405              
406             =cut
407              
408             # Must be implemented by classes consuming this role.
409              
410             ##############################################################################
411              
412             =head3 C<< $result->map( sub { MAP } ) >>
413              
414             If the Result is ok, then runs the coderef. Within the coderef, the unwrapped
415             value in scalar context is available as C<< $_ >> and in list context is
416             available as C<< @_ >>. The return value of the coderef is wrapped in a
417             new ok Result. The original Result is considered to be handled.
418              
419             If the Result is err, then returns self. The Result is not considered handled.
420              
421             =head4 Example
422              
423             In the example below, C<< uppercase_name() >> will return a Result which
424             may be an ok Result with the uppercased name from the database or the
425             err Result with the message "Could not connect to database".
426              
427             sub get_name {
428             if ( connect_to_database() ) {
429             ...;
430             return ok( $name );
431             }
432             else {
433             return err( "Could not connect to database" );
434             }
435             }
436            
437             sub uppercase_name {
438             return get_name()->map( sub {
439             return uc $_;
440             } );
441             }
442            
443             sub lowercase_name {
444             return get_name()->map( sub {
445             return lc $_;
446             } );
447             }
448              
449             =cut
450              
451             sub map {
452 2     2 1 6 my ( $self, $op ) = @_;
453 2 50 33     10 @_ == 2 && __IS_CODE__( $op )
454             or Carp::croak( 'Usage: $result->map( sub { ... } )' );
455              
456 2 100       40 if ( $self->is_err() ) {
457 1         5 return $self;
458             }
459              
460 1         5 local $_ = $self->_peek;
461 1         4 results::ok( $op->( $self->unwrap() ) );
462             }
463              
464             ##############################################################################
465              
466             =head3 C<< $result->map_err( sub { MAP } ) >>
467              
468             If the Result is ok, then returns self. The Result is not considered handled.
469              
470             If the Result is err, then runs the coderef. Within the coderef, the unwrapped
471             error in scalar context is available as C<< $_ >> and in list context is
472             available as C<< @_ >>. The return value of the coderef is wrapped in a
473             new err Result. The original Result is considered to be handled.
474              
475             This is the inverse of C<< map() >>.
476              
477             =cut
478              
479             sub map_err {
480 2     2 1 7 my ( $self, $op ) = @_;
481 2 50 33     8 @_ == 2 && __IS_CODE__( $op )
482             or Carp::croak( 'Usage: $result->map_err( sub { ... } )' );
483              
484 2 100       8 if ( $self->is_ok() ) {
485 1         7 return $self;
486             }
487              
488 1         5 local $_ = $self->_peek_err;
489 1         4 results::err( $op->( $self->unwrap_err() ) );
490             }
491              
492             ##############################################################################
493              
494             =head3 C<< $result->map_or( @default, sub { MAP } ) >>
495              
496             If the Result is ok, then runs the coderef. Within the coderef, the unwrapped
497             value in scalar context is available as C<< $_ >> and in list context is
498             available as C<< @_ >>. Returns the return value of the coderef.
499              
500             If the Result is err, then returns @default (whih may just be a single scalar).
501              
502             Note that unlike C<< map() >>, this does not return a Result, but a value.
503              
504             The Result is considered to be handled.
505              
506             =head4 Example
507              
508             In the example below, C<< uppercase_name() >> will return a Result which
509             may be an ok Result with the uppercased name from the database or the
510             err Result with the message "Could not connect to database".
511              
512             sub get_name {
513             if ( connect_to_database() ) {
514             ...;
515             return ok( $name );
516             }
517             else {
518             return err( "Could not connect to database" );
519             }
520             }
521            
522             say "HELLO, ", get_name()->map_or( "ANON", sub {
523             return uc $_;
524             } );
525              
526             =cut
527              
528             sub map_or {
529 2     2 1 5 my $f = pop;
530 2         6 my ( $self, @default ) = @_;
531 2 50 33     11 @_ >= 1 && __IS_CODE__( $f )
532             or Carp::croak( 'Usage: $result->map_or( $default, sub { ... } )' );
533              
534 2 100       8 if ( $self->is_err() ) {
535 1         4 $self->_handled( !!1 );
536 1         3 return results::ok( @default )->unwrap();
537             }
538              
539 1         5 local $_ = $self->_peek;
540 1         5 results::ok( $f->( $self->unwrap() ) )->unwrap();
541             }
542              
543             ##############################################################################
544              
545             =head3 C<< $result->map_or_else( sub { DEFAULT }, sub { MAP } ) >>
546              
547             Similar to C<< map_or() >> except that the C<< @default >> is replaced
548             by a coderef which should return the default.
549              
550             The Result is considered to be handled.
551              
552             =cut
553              
554             sub map_or_else {
555 2     2 1 6 my ( $self, $default, $f ) = @_;
556 2 50 33     9 @_ == 3 && __IS_CODE__( $default ) && __IS_CODE__( $f )
      33        
557             or Carp::croak( 'Usage: $result->map_or_else( sub { ... }, sub { ... } )' );
558              
559 2 100       7 if ( $self->is_err() ) {
560 1         4 local $_ = $self->_peek_err();
561 1         5 return results::ok( $default->( $self->unwrap_err() ) )->unwrap();
562             }
563              
564 1         4 local $_ = $self->_peek;
565 1         5 results::ok( $f->( $self->unwrap() ) )->unwrap();
566             }
567              
568             ##############################################################################
569              
570             =head3 C<< $result->match( %dispatch_table ) >>
571              
572             The C<< %dispatch_table >> is a hash of coderefs.
573              
574             The keys 'ok' and 'err' are required coderefs to handle ok and err Results.
575              
576             (Additional coderefs with keys "err_XXX" are allowed, where "XXX" is a short
577             name for a kind of error. If C is called on an err Result, and the
578             error is a blessed object which DOES the "results::exceptions" trait, then
579             C<< $result->unwrap_err()->err_kind() >> is called and expected to return
580             a string indicating the error kind. The L module makes
581             it very easy to create exception objects like this!)
582              
583             The unwrapped value or error is available in C<< $_ >> and C<< @_ >> as
584             you might expect.
585              
586             B<< This method is not found in the original Rust implementation of Results. >>
587              
588             =head4 Example
589              
590             get_name()->match(
591             ok => sub { say "Hello, $_" },
592             err => sub { warn $_ },
593             );
594              
595             =head4 Example
596              
597             open_file($filename)->match(
598             ok => sub { $_->write( $data ) },
599             err_Auth => sub { die( "Permissions error!" ) },
600             err_DiskFull => sub { die( "Disk is full!" ) },
601             err => sub { die( "Another error occurred!" ) },
602             );
603              
604             =cut
605              
606             sub match {
607 4     4 1 20 my ( $self, %d ) = @_;
608             exists( $d{ok} ) && exists( $d{err} )
609 4 50 33     25 or Carp::croak( 'Usage: $result->match( ok => sub { ... }, err => sub { ... }, ... )' );
610              
611 4 100       14 if ( $self->is_ok() ) {
612 1         2 my $d = $d{ok};
613 1 50       4 __IS_CODE__($d)
614             or Carp::croak( 'Usage: $result->match( ok => sub { ... }, err => sub { ... }, ... )' );
615 1         6 local $_ = $self->_peek();
616 1         5 return $d->( $self->unwrap );
617             }
618              
619 3         10 my $d = $d{err};
620 3         12 my $peek = $self->_peek_err;
621 3 100       12 if ( __IS_FRIENDLY_EXCEPTION__($peek) ) {
622 2         13 my $err_kind = $peek->err_kind;
623 2   33     14 $d = $d{"err_$err_kind"} // $d{err};
624             }
625 3 50       10 __IS_CODE__($d)
626             or Carp::croak( 'Usage: $result->match( ok => sub { ... }, err => sub { ... }, ... )' );
627 3         6 local $_ = $peek;
628 3         10 return $d->( $self->unwrap_err );
629             }
630              
631             ##############################################################################
632              
633             =head3 C<< $result->ok() >>
634              
635             For ok Results, the same as C. For err Results, returns nothing.
636              
637             The Result is considered to be handled.
638              
639             =cut
640              
641             sub ok {
642 2     2 1 12 my ( $self ) = @_;
643 2 50       7 @_ == 1
644             or Carp::croak( 'Usage: $result->ok()' );
645              
646 2         7 $self->_handled( !!1 );
647              
648 2 100       6 return $self->unwrap() if $self->is_ok();
649              
650 1         4 return;
651             }
652              
653             ##############################################################################
654              
655             =head3 C<< $result->or( $other_result ) >>
656              
657             Returns C<< $result >> if it is ok. Returns C<< $other_result >>
658             otherwise. The effect of this is that C returns an ok Result if
659             either of the Results is ok, and an err Result if both results were
660             err Results.
661              
662             C<< $result >> is considered to be handled if it was an err.
663             C<< $other_result >> is not considered to have been handled.
664              
665             =head4 Example
666              
667             If C<< retrieve_file() >> uses a Result to indicate success:
668              
669             retrieve_file( "server1.example.com" )
670             ->or( retrieve_file( "server2.example.com" ) )
671             ->or( retrieve_file( "server3.example.com" ) )
672             ->expect( "Could not retrieve file from any server!" );
673              
674             Like with C<< and() >>, it needs to be noted that Perl eagerly evaluates
675             method call arguments, so C<< retrieve_file() >> will be called three times,
676             even if the first server succeeded. C<< or_else() >> provides a solution.
677              
678             =cut
679              
680             sub or {
681 4     4 1 33 my ( $self, $res ) = @_;
682 4 50 33     17 @_ == 2 && __IS_RESULT__($res)
683             or Carp::croak( 'Usage: $result->or( $other_result )' );
684              
685 4 100       94 if ( $self->is_err() ) {
686 2         7 $self->_handled( !!1 );
687 2         8 return $res;
688             }
689              
690 2         16 return $self;
691             }
692              
693             ##############################################################################
694              
695             =head3 C<< $result->or_else( sub { ELSE } ) >>
696              
697             The coderef is expected to return a Result object.
698              
699             Returns C<< $result >> if it is ok.
700              
701             Otherwise, executes the coderef and returns the coderef's Result. Within the
702             coderef, the unwrapped error in scalar context is available as C<< $_ >> and
703             in list context is available as C<< @_ >>.
704              
705             C<< $result >> is considered to be handled if it was an err.
706              
707             =head4 Example
708              
709             If C<< retrieve_file() >> uses a Result to indicate success:
710              
711             retrieve_file( "server1.example.com" )
712             ->or_else( sub {
713             return retrieve_file( "server2.example.com" );
714             } )
715             ->or_else( sub {
716             return retrieve_file( "server3.example.com" );
717             } )
718             ->expect( "Could not retrieve file from any server!" );
719              
720             =cut
721              
722             sub or_else {
723 8     8 1 30 my ( $self, $op ) = @_;
724 8 50 33     23 @_ == 2 && __IS_CODE__($op)
725             or Carp::croak( 'Usage: $result->or_else( sub { ...; $other_result } )' );
726              
727 8 100       24 if ( $self->is_err() ) {
728 3         8 local $_ = $self->_peek_err;
729 3         8 my $res = $op->( $self->unwrap_err() );
730 3 50       9 __IS_RESULT__($res)
731             or Carp::croak( 'Coderef did not return a Result' );
732 3         67 return $res;
733             }
734              
735 5         20 return $self;
736             }
737              
738             ##############################################################################
739              
740             =head3 C<< $result->type( $constraint ) >>
741              
742             If this Result is an err, returns self. Not considered handled.
743              
744             If this Result is ok, and passes the type constraint in scalar context,
745             returns self. Not considered handled.
746              
747             Otherwise returns an err Result with the type validation error message.
748             In this case the original Result is considered handled.
749              
750             B<< This method is not found in the original Rust implementation of Results. >>
751              
752             =head4 Example
753              
754             If C<< get_config() >> returns an ok Result containing a hashref, then:
755              
756             use Types::Common qw( HashRef );
757            
758             my $config = get_config->type( HashRef )->unwrap();
759              
760             =cut
761              
762             sub type {
763 2     2 1 157 my ( $self, $type ) = @_;
764 2 50 33     13 @_ == 2 && __IS_TYPE__($type)
765             or Carp::croak( 'Usage: $result->type( $constraint )' );
766              
767 2 50       10 return $self if $self->is_err();
768              
769 2         8 my $peek = $self->_peek();
770 2 100       6 return $self if $type->check( $peek );
771              
772 1         38 return results::err( $type->get_message( $self->unwrap() ) );
773             }
774              
775             ##############################################################################
776              
777             =head3 C<< $result->type_or( @default, $constraint ) >>
778              
779             If this Result is an err, returns self. Not considered handled.
780              
781             If this Result is ok, and passes the type constraint in scalar context,
782             returns self. Not considered handled.
783              
784             Otherwise returns an ok Result with the default value(s). In this case
785             the original Result is considered handled.
786              
787             B<< This method is not found in the original Rust implementation of Results. >>
788              
789             =head4 Example
790              
791             If C<< get_config() >> returns an ok Result containing a hashref, then:
792              
793             use Types::Common qw( HashRef );
794            
795             my $config = get_config->type_or( HashRef, {} )->unwrap();
796              
797             =cut
798              
799             sub type_or {
800 2     2 1 23 my $type = pop;
801 2         6 my ( $self, @default ) = @_;
802 2 50 33     9 @_ >= 1 && __IS_TYPE__($type)
803             or Carp::croak( 'Usage: $result->type_or( $default, $constraint )' );
804              
805 2 50       8 return $self if $self->is_err();
806              
807 2         7 my $peek = $self->_peek();
808 2 100       7 return $self if $type->check( $peek );
809              
810 1         42 $self->_handled( !!1 );
811 1         3 return results::ok( @default );
812             }
813              
814             ##############################################################################
815              
816             =head3 C<< $result->type_or_else( sub { ELSE }, $constraint ) >>
817              
818             If this Result is an err, returns self. Not considered handled.
819              
820             If this Result is ok, and passes the type constraint in scalar context,
821             returns self. Not considered handled.
822              
823             Otherwise executes the coderef, which is expected to return a Result.
824             In this case the original Result is considered handled.
825              
826             B<< This method is not found in the original Rust implementation of Results. >>
827              
828             =cut
829              
830             sub type_or_else {
831 2     2 1 21 my ( $self, $op, $type ) = @_;
832 2 50 33     13 @_ == 3 && __IS_TYPE__($type) && __IS_CODE__($op)
      33        
833             or Carp::croak( 'Usage: $result->type_or_else( $constraint, sub { ... } )' );
834              
835 2 50       8 return $self if $self->is_err();
836              
837 2         7 my $peek = $self->_peek();
838 2 100       7 return $self if $type->check( $peek );
839              
840 1         34 local $_ = $peek;
841 1         5 my $res = $op->( $self->unwrap() );
842 1 50       9 __IS_RESULT__($res)
843             or Carp::croak( 'Coderef did not return a Result' );
844 1         27 return $res;
845             }
846              
847             ##############################################################################
848              
849             =head3 C<< $result->unwrap() >>
850              
851             For ok Results, returns the value and the Result is considered handled.
852              
853             For err Results, throws an exception. If you wish to customize the
854             error message, use C<< expect() >> instead of C<< unwrap() >>.
855              
856             =cut
857              
858             sub unwrap {
859 0     0 1 0 my ( $self ) = @_;
860 0 0       0 @_ == 1
861             or Carp::croak( 'Usage: $result->unwrap()' );
862              
863 0 0       0 if ( $self->is_ok() ) {
864 0         0 $self->_handled( !!1 );
865 0         0 return $self->_peek();
866             }
867             else {
868 0         0 Carp::croak( $self->unwrap_err() );
869             }
870             }
871              
872             ##############################################################################
873              
874             =head3 C<< $result->unwrap_err() >>
875              
876             For err Results, returns the error and the Result is considered handled.
877              
878             For ok Results, throws an exception. If you wish to customize the
879             error message, use C<< expect_err() >> instead of C<< unwrap_err() >>.
880              
881             =cut
882              
883             sub unwrap_err {
884 0     0 1 0 my ( $self ) = @_;
885 0 0       0 @_ == 1
886             or Carp::croak( 'Usage: $result->unwrap_err()' );
887              
888 0 0       0 if ( $self->is_ok() ) {
889 0         0 Carp::croak( $self->unwrap() );
890             }
891             else {
892 0         0 $self->_handled( !!1 );
893 0         0 return $self->_peek_err();
894             }
895             }
896              
897             ##############################################################################
898              
899             =head3 C<< $result->unwrap_or( @default ) >>
900              
901             For ok Results, returns the value and the Result is considered handled.
902              
903             For err Results, returns the default value(s).
904              
905             =cut
906              
907             sub unwrap_or {
908 2     2 1 17 my ( $self, @default ) = @_;
909              
910 2 100       8 if ( $self->is_err() ) {
911 1         7 $self->_handled( !!1 );
912 1         5 return results::ok( @default )->unwrap();
913             }
914              
915 1         6 $self->unwrap();
916             }
917              
918             ##############################################################################
919              
920             =head3 C<< $result->unwrap_or_else( sub { ELSE } ) >>
921              
922             For ok Results, returns the value and the Result is considered handled.
923              
924             For err Results, executes the coderef and returns whatever the coderef
925             returned.
926              
927             This is effectively a lazy version of C<< unwrap_or() >>.
928              
929             =cut
930              
931             sub unwrap_or_else {
932 2     2 1 6 my ( $self, $op ) = @_;
933 2 50 33     11 @_ == 2 && __IS_CODE__( $op )
934             or Carp::croak( 'Usage: $result->unwrap_or_else( sub { ...; return $other_result } )' );
935              
936 2 100       9 if ( $self->is_err() ) {
937 1         6 local $_ = $self->_peek_err();
938 1         5 return results::ok( $op->( $self->unwrap_err() ) )->unwrap();
939             }
940              
941 1         4 $self->unwrap();
942             }
943              
944             ##############################################################################
945              
946             =head3 C<< $result->DESTROY() >>
947              
948             You should not call this method directly. Called by Perl when the object goes
949             out of scope or is otherwise destroyed.
950              
951             Attempts to throw an exception if the Result has not been handled. However,
952             the current implementation of Perl downgrades exceptions thrown by DESTROY
953             to be warnings.
954              
955             =cut
956              
957             sub DESTROY {
958 127     127   28904 my ( $self ) = @_;
959              
960 127 50       280 return if __IN_GLOBAL_DESTRUCTION__;
961 127 100       455 return if $self->_handled;
962              
963 3         13 $self->_handled( !!1 );
964 3         12 Carp::croak( "$self went out of scope without being unwrapped" );
965             }
966              
967             ##############################################################################
968             1;
969             ##############################################################################
970              
971             __END__