File Coverage

blib/lib/Smart/Dispatch.pm
Criterion Covered Total %
statement 81 82 98.7
branch 8 18 44.4
condition 16 20 80.0
subroutine 26 27 96.3
pod n/a
total 131 147 89.1


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