File Coverage

blib/lib/Future/Exception.pm
Criterion Covered Total %
statement 27 27 100.0
branch 2 2 100.0
condition n/a
subroutine 11 11 100.0
pod 3 7 42.8
total 43 47 91.4


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2019 -- leonerd@leonerd.org.uk
5              
6             package Future::Exception;
7              
8 33     33   416 use v5.10;
  33         112  
9 33     33   232 use strict;
  33         65  
  33         683  
10 33     33   173 use warnings;
  33         72  
  33         1746  
11              
12             our $VERSION = '0.50';
13              
14             =head1 NAME
15              
16             C - an exception type for failed Ls
17              
18             =head1 SYNOPSIS
19              
20             use Scalar::Util qw( blessed );
21             use Syntax::Keyword::Try;
22              
23             try {
24             my $f = ...;
25             my @result = $f->result;
26             ...
27             }
28             catch {
29             if( blessed($@) and $@->isa( "Future::Exception" ) {
30             print STDERR "The ", $@->category, " failed: ", $@->message, "\n";
31             }
32             }
33              
34             =head1 DESCRIPTION
35              
36             The C method on a failed L instance will throw an exception to
37             indicate that the future failed. A failed future can contain a failure
38             category name and other details as well as the failure message, so in this
39             case the exception will be an instance of C to make these
40             values accessible.
41              
42             Users should not depend on exact class name matches, but instead rely on
43             inheritence, as a later version of this implementation might dynamically
44             create subclasses whose names are derived from the Future failure category
45             string, to assist with type matching. Note the use of C<< ->isa >> in the
46             SYNOPSIS example.
47              
48             =cut
49              
50             use overload
51 33         307 '""' => "message",
52 33     33   259 fallback => 1;
  33         111  
53              
54             =head1 CONSTRUCTOR
55              
56             =head2 from_future
57              
58             $e = Future::Exception->from_future( $f )
59              
60             Constructs a new C wrapping the given failed future.
61              
62             =cut
63              
64             sub from_future
65             {
66 1     1 1 2 my $class = shift;
67 1         3 my ( $f ) = @_;
68 1         4 return $class->new( $f->failure );
69             }
70              
71 5     5 0 7 sub new { my $class = shift; bless [ @_ ], $class; }
  5         23  
72              
73             =head1 ACCESSORS
74              
75             $message = $e->message
76             $category = $e->category
77             @details = $e->details
78              
79             Additionally, the object will stringify to return the message value, for the
80             common use-case of printing, regexp testing, or other behaviours.
81              
82             =cut
83              
84 10     10 0 6164 sub message { shift->[0] }
85 5     5 0 19 sub category { shift->[1] }
86 5     5 0 8 sub details { my $self = shift; @{$self}[2..$#$self] }
  5         11  
  5         26  
87              
88             =head1 METHODS
89              
90             =cut
91              
92             =head2 throw
93              
94             Future::Exception->throw( $message, $category, @details )
95              
96             I
97              
98             Constructs a new exception object and throws it using C. This method
99             will not return, as it raises the exception directly.
100              
101             If C<$message> does not end in a linefeed then the calling file and line
102             number are appended to it, in the same way C does.
103              
104             =cut
105              
106             sub throw
107             {
108 2     2 1 1016 my $class = shift;
109 2         5 my ( $message, $category, @details ) = @_;
110 2 100       16 $message =~ m/\n$/ or
111             $message .= sprintf " at %s line %d.\n", ( caller )[1,2];
112 2         7 die $class->new( $message, $category, @details );
113             }
114              
115             # TODO: consider a 'croak' method that uses Carp::shortmess to find a suitable
116             # file/linenumber
117              
118             =head2 as_future
119              
120             $f = $e->as_future
121              
122             Returns a new C object in a failed state matching the exception.
123              
124             =cut
125              
126             sub as_future
127             {
128 1     1 1 3 my $self = shift;
129 1         3 return Future->fail( $self->message, $self->category, $self->details );
130             }
131              
132             =head1 AUTHOR
133              
134             Paul Evans
135              
136             =cut
137              
138             0x55AA;