File Coverage

blib/lib/Smart/Dispatch.pm
Criterion Covered Total %
statement 78 79 98.7
branch 8 18 44.4
condition 16 20 80.0
subroutine 25 26 96.1
pod n/a
total 127 143 88.8


line stmt bran cond sub pod time code
1             package Smart::Dispatch;
2              
3 5     5   43162 use 5.010;
  5         15  
  5         200  
4 5     5   26 use strict;
  5         9  
  5         307  
5              
6 5     5   26 use Carp;
  5         14  
  5         465  
7 5     5   3197 use Smart::Dispatch::Table ();
  5         20  
  5         158  
8 5     5   4037 use Smart::Dispatch::Match ();
  5         14  
  5         269  
9              
10             BEGIN {
11 5     5   14 $Smart::Dispatch::AUTHORITY = 'cpan:TOBYINK';
12 5         147 $Smart::Dispatch::VERSION = '0.005';
13             }
14              
15 5     5   55 use constant DEFAULT_MATCH_CLASS => (__PACKAGE__.'::Match');
  5         11  
  5         328  
16 5     5   26 use constant DEFAULT_TABLE_CLASS => (__PACKAGE__.'::Table');
  5         8  
  5         750  
17              
18             our ($IN_FLIGHT, @LIST, @EXPORT);
19             BEGIN
20             {
21             $Carp::Internal{$_}++
22 5     5   60 foreach (__PACKAGE__, DEFAULT_MATCH_CLASS, DEFAULT_TABLE_CLASS);
23 5         12 $IN_FLIGHT = 0;
24 5         12 @LIST = ();
25 5         230 @EXPORT = qw/dispatcher match match_using otherwise dispatch failover/;
26             }
27              
28 5     5   39 use namespace::clean ();
  5         13  
  5         929  
29             use Sub::Exporter -setup => {
30             exports => [
31             dispatcher => \&_build_dispatcher,
32             match => \&_build_match,
33             match_using => \&_build_match_using,
34             otherwise => \&_build_otherwise,
35             dispatch => \&_build_dispatch,
36             failover => \&_build_failover,
37             ],
38             groups => [
39             default => [@EXPORT],
40             tiny => [qw/dispatcher match/],
41             ],
42             collectors => [qw/class/],
43             installer => sub {
44 60         143 namespace::clean::->import(
45             -cleanee => $_[0]{into},
46 5         66 grep { !ref } @{ $_[1] },
  5         15  
47             );
48 5         4434 goto \&Sub::Exporter::default_installer;
49             },
50 5     5   25858 };
  5         82826  
  5         146  
51              
52             sub _build_dispatcher
53             {
54 10     10   1153 my ($class, $name, $arg, $col) = @_;
55 10   66     101 my $table_class =
      100        
56             $arg->{class}
57             // $col->{class}{table}
58             // DEFAULT_TABLE_CLASS;
59            
60             return sub (&)
61             {
62 4     4   315 my $body = shift;
63 4         16 local @LIST = ();
64 4         14 local $IN_FLIGHT = 1;
65 4         15 $body->();
66 4         56 return $table_class->new(match_list => [@LIST]);
67             }
68 10         62 }
69              
70             sub _build_match
71             {
72 10     10   127 my ($class, $name, $arg, $col) = @_;
73 10   66     90 my $match_class =
      100        
74             $arg->{class}
75             // $col->{class}{match}
76             // DEFAULT_MATCH_CLASS;
77            
78             return sub
79             {
80 13 50   13   39 croak "$name cannot be used outside dispatcher" unless $IN_FLIGHT;
81 13 50       64 my ($condition, %args) = (@_ == 2) ? (shift, _k($_[-1]), shift) : (@_);
82 13         275 push @LIST, $match_class->new(%args, test => $condition);
83 13         166 return;
84             }
85 10         62 }
86              
87             sub _build_match_using
88             {
89 10     10   113 my ($class, $name, $arg, $col) = @_;
90 10   66     89 my $match_class =
      100        
91             $arg->{class}
92             // $col->{class}{match}
93             // DEFAULT_MATCH_CLASS;
94            
95             return sub (&@)
96             {
97 5 50   5   18 croak "$name cannot be used outside dispatcher" unless $IN_FLIGHT;
98 5 50       27 my ($condition, %args) = (@_ == 2) ? (shift, _k($_[-1]), shift) : (@_);
99 5         132 push @LIST, $match_class->new(%args, test => $condition);
100 5         54 return;
101             }
102 10         55 }
103              
104             sub _build_otherwise
105             {
106 10     10   124 my ($class, $name, $arg, $col) = @_;
107 10   66     86 my $match_class =
      100        
108             $arg->{class}
109             // $col->{class}{match}
110             // DEFAULT_MATCH_CLASS;
111            
112             return sub
113             {
114 2 50   2   11 croak "$name cannot be used outside dispatcher" unless $IN_FLIGHT;
115 2 50       10 my (%args) = (@_ == 1) ? (_k($_[-1]), shift) : (@_);
116 2     2   49 push @LIST, $match_class->new(%args, is_unconditional => 1, test => sub {1});
  2         50  
117 2         53 return;
118             }
119 10         49 }
120              
121             sub _build_dispatch
122             {
123 10     10   403 my ($class, $name, $arg, $col) = @_;
124            
125             return sub (&)
126             {
127 14 50   14   87 croak "$name cannot be used outside dispatcher" unless $IN_FLIGHT;
128 14         55 return('dispatch', shift);
129             }
130 10         48 }
131              
132             sub _build_failover
133             {
134 10     10   1440 my ($class, $name, $arg, $col) = @_;
135            
136             return sub (&)
137             {
138 4 50   4   18 croak "$name cannot be used outside dispatcher" unless $IN_FLIGHT;
139 4         23 return('dispatch', shift, is_failover => 1);
140             }
141 10         51 }
142              
143             sub _k
144             {
145 0 0   0     ref $_[0] eq 'CODE' ? 'dispatch' : 'value';
146             }
147              
148             foreach my $f (@EXPORT)
149             {
150 5     5   7723 no strict 'refs';
  5         11  
  5         544  
151             *{"$f"} = &{"_build_$f"}(__PACKAGE__, $f, {}, {});
152             }
153              
154             __PACKAGE__
155             __END__