File Coverage

blib/lib/Dispatch/Fu.pm
Criterion Covered Total %
statement 39 43 90.7
branch 12 16 75.0
condition 5 6 83.3
subroutine 11 12 91.6
pod 5 5 100.0
total 72 82 87.8


line stmt bran cond sub pod time code
1             package Dispatch::Fu;
2              
3 6     6   154514 use strict;
  6         13  
  6         253  
4 6     6   90 use warnings;
  6         11  
  6         357  
5 6     6   52 use Exporter qw/import/;
  6         36  
  6         262  
6 6     6   30 use Carp qw/carp croak/;
  6         16  
  6         5237  
7              
8             our $VERSION = q{1.06};
9             our @EXPORT = qw(dispatch on cases xdefault xshift_and_deref);
10             our @EXPORT_OK = qw(dispatch on cases xdefault xshift_and_deref);
11              
12             my $DISPATCH_TABLE = {};
13              
14             # sub for introspection, returns the string names of each case
15             # added using the C keyword
16             sub cases() {
17 201     201 1 2975 return sort keys %$DISPATCH_TABLE;
18             }
19              
20             sub _reset_default_handler() {
21             $DISPATCH_TABLE = {
22             default => sub {
23 0     0   0 carp qq{Supported cases are:\n};
24 0         0 foreach my $case (cases) {
25 0         0 print qq{\t$case\n};
26             };
27             },
28 114     114   1329 };
29 114         257 return;
30             }
31              
32             _reset_default_handler;
33              
34             sub dispatch (&@) {
35 110     110 1 278411 my $code_ref = shift; # catch sub ref that was coerced from the 'dispatch' BLOCK
36 110         176 my $match_ref = shift; # catch the input reference passed after the 'dispatch' BLOCK
37              
38             # build up dispatch table for each k/v pair preceded by 'on'
39 110         407 while ( my $key = shift @_ ) {
40 654         961 my $HV = shift @_;
41 654         1053 $DISPATCH_TABLE->{$key} = _to_sub($HV);
42             }
43              
44 110 50       295 croak qq{Dispatch::Fu [warning]: no cases defined. Make sure no semicolons are in places that need commas!} if not %$DISPATCH_TABLE;
45              
46             # call $code_ref that needs to return a valid bucket name
47 110         365 my $key = $code_ref->($match_ref);
48              
49 110 100 66     92495 croak qq{Computed static bucket "$key" not found\n} if not $DISPATCH_TABLE->{$key} or 'CODE' ne ref $DISPATCH_TABLE->{$key};
50              
51             # call subroutine ref defined as the v in the k/v $DISPATCH_TABLE->{$key} slot
52 108         237 my $sub_to_call = $DISPATCH_TABLE->{$key};
53              
54             # reset table, happens after call to CODE ref so that C is available inside
55             # of the body of the sub
56 108         346 _reset_default_handler;
57              
58 108         346 return $sub_to_call->($match_ref);
59             }
60              
61             # on accumulater, wants h => v pair, where h is a static bucket string and v is a sub ref
62             sub on (@) {
63 655     655 1 1762793 my ($key, $val) = @_;
64             # detect situations like when instead of a comma, "on" sits behind a semicolon
65 655 100       1400 carp qq{Dispatch::Fu [warning]: "on $key" used in void context is always a mistake. The "on" method always follows a comma!} unless wantarray;
66 655         2203 return @_;
67             }
68              
69             # if $case is in cases(), return $case; otherwise return $default
70             # Note: $default defaults to q{default}; i.e., if the name of the
71             # default case is not specified, the string 'default' is returned
72             sub xdefault($;$) {
73 5     5 1 30 my ($case, $default) = @_;
74 5 100 100     17 if ($case and grep { /$case/ } (cases)){
  22         119  
75 1         6 return $case;
76             }
77 4 100       19 return (defined $default) ? $default : q{default};
78             }
79              
80             # for multi-assignment syntax, given the first reference in the parameter list; e.g., "my ($x, $y, $z) = ..."
81             sub xshift_and_deref(@) {
82 2 100   2 1 15 return %{ +shift } if ref $_[0] eq q{HASH};
  1         7  
83 1 50       4 return @{ +shift } if ref $_[0] eq q{ARRAY};
  1         5  
84 0 0       0 return shift @_ if ref $_[0] eq q{SCALAR};
85             }
86              
87             # utility sub to force a BLOCK into a sub reference
88             sub _to_sub (&) {
89 654     654   2260 shift;
90             }
91              
92             1;
93              
94             __END__