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