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   24232 use 5.010;
  5         14  
  5         274  
4 5     5   26 use strict;
  5         7  
  5         361  
5              
6 5     5   25 use Carp;
  5         18  
  5         446  
7 5     5   4431 use Smart::Dispatch::Table ();
  5         19  
  5         123  
8 5     5   3380 use Smart::Dispatch::Match ();
  5         15  
  5         211  
9              
10             BEGIN {
11 5     5   11 $Smart::Dispatch::AUTHORITY = 'cpan:TOBYINK';
12 5         121 $Smart::Dispatch::VERSION = '0.004';
13             }
14              
15 5     5   33 use constant DEFAULT_MATCH_CLASS => (__PACKAGE__.'::Match');
  5         8  
  5         248  
16 5     5   21 use constant DEFAULT_TABLE_CLASS => (__PACKAGE__.'::Table');
  5         8  
  5         668  
17              
18             our ($IN_FLIGHT, @LIST, @EXPORT);
19             BEGIN
20             {
21             $Carp::Internal{$_}++
22 5     5   40 foreach (__PACKAGE__, DEFAULT_MATCH_CLASS, DEFAULT_TABLE_CLASS);
23 5         10 $IN_FLIGHT = 0;
24 5         10 @LIST = ();
25 5         177 @EXPORT = qw/dispatcher match match_using otherwise dispatch failover/;
26             }
27              
28 5     5   25 use namespace::clean ();
  5         12  
  5         932  
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         131 namespace::clean::->import(
45             -cleanee => $_[0]{into},
46 5         56 grep { !ref } @{ $_[1] },
  5         15  
47             );
48 5         263 goto \&Sub::Exporter::default_installer;
49             },
50 5     5   1652708 };
  5         69292  
  5         152  
51              
52             sub _build_dispatcher
53             {
54 10     10   1008 my ($class, $name, $arg, $col) = @_;
55 10   66     99 my $table_class =
      100        
56             $arg->{class}
57             // $col->{class}{table}
58             // DEFAULT_TABLE_CLASS;
59            
60             return sub (&)
61             {
62 4     4   306 my $body = shift;
63 4         17 local @LIST = ();
64 4         13 local $IN_FLIGHT = 1;
65 4         16 $body->();
66 4         42 return $table_class->new(match_list => [@LIST]);
67             }
68 10         62 }
69              
70             sub _build_match
71             {
72 10     10   136 my ($class, $name, $arg, $col) = @_;
73 10   66     80 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       62 my ($condition, %args) = (@_ == 2) ? (shift, _k($_[-1]), shift) : (@_);
82 13         296 push @LIST, $match_class->new(%args, test => $condition);
83 13         142 return;
84             }
85 10         57 }
86              
87             sub _build_match_using
88             {
89 10     10   107 my ($class, $name, $arg, $col) = @_;
90 10   66     76 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       28 my ($condition, %args) = (@_ == 2) ? (shift, _k($_[-1]), shift) : (@_);
99 5         116 push @LIST, $match_class->new(%args, test => $condition);
100 5         51 return;
101             }
102 10         50 }
103              
104             sub _build_otherwise
105             {
106 10     10   110 my ($class, $name, $arg, $col) = @_;
107 10   66     75 my $match_class =
      100        
108             $arg->{class}
109             // $col->{class}{match}
110             // DEFAULT_MATCH_CLASS;
111            
112             return sub
113             {
114 2 50   2   10 croak "$name cannot be used outside dispatcher" unless $IN_FLIGHT;
115 2 50       12 my (%args) = (@_ == 1) ? (_k($_[-1]), shift) : (@_);
116 2     2   53 push @LIST, $match_class->new(%args, is_unconditional => 1, test => sub {1});
  2         41  
117 2         58 return;
118             }
119 10         43 }
120              
121             sub _build_dispatch
122             {
123 10     10   333 my ($class, $name, $arg, $col) = @_;
124            
125             return sub (&)
126             {
127 14 50   14   72 croak "$name cannot be used outside dispatcher" unless $IN_FLIGHT;
128 14         54 return('dispatch', shift);
129             }
130 10         39 }
131              
132             sub _build_failover
133             {
134 10     10   99 my ($class, $name, $arg, $col) = @_;
135            
136             return sub (&)
137             {
138 4 50   4   19 croak "$name cannot be used outside dispatcher" unless $IN_FLIGHT;
139 4         20 return('dispatch', shift, is_failover => 1);
140             }
141 10         41 }
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   8290 no strict 'refs';
  5         13  
  5         451  
151             *{"$f"} = &{"_build_$f"}(__PACKAGE__, $f, {}, {});
152             }
153              
154             __PACKAGE__
155             __END__