File Coverage

blib/lib/Class/Enumemon.pm
Criterion Covered Total %
statement 83 83 100.0
branch 15 16 93.7
condition n/a
subroutine 20 20 100.0
pod n/a
total 118 119 99.1


line stmt bran cond sub pod time code
1             package Class::Enumemon;
2 2     2   22252 use 5.008001;
  2         8  
3 2     2   10 use strict;
  2         3  
  2         42  
4 2     2   18 use warnings;
  2         3  
  2         89  
5              
6             our $VERSION = "0.01";
7              
8 2     2   10 use Carp ();
  2         3  
  2         30  
9 2     2   9937 use Guard ();
  2         1136  
  2         745  
10              
11             sub import {
12 7     7   64 shift;
13 7         15 my $pkg = caller;
14 7         13 my $meta = {};
15 7         13 my $defs = [];
16 7         27 while (my $v = shift @_) {
17 20 100       41 if (ref $v) {
18 11         38 push @$defs, $v;
19             } else {
20 9         31 $meta->{$v} = shift @_;
21             }
22             }
23              
24 7         15 my $data = _generate_data($pkg, $meta, $defs);
25 7 100       27 _mk_values($pkg, $data) if $meta->{values};
26 7 100       25 _mk_getter($pkg, $defs) if $meta->{getter};
27 7 100       24 _mk_indexer($pkg, $meta, $data) if $meta->{indexer};
28 7         18 _mk_local($pkg, $meta, $data);
29             }
30              
31             sub _generate_data {
32 11     11   20 my ($pkg, $meta, $defs) = @_;
33 11         17 my $data = {};
34              
35             # values
36 11         25 $data->{values} = [ map { bless $_, $pkg } @$defs ];
  16         51  
37              
38             # indexer
39 11 100       35 if ($meta->{indexer}) {
40 5         10 $data->{indexer} = {};
41 5         8 for my $indexer (keys %{$meta->{indexer}}) {
  5         18  
42 8         12 my $field = $meta->{indexer}->{$indexer};
43             $data->{indexer}->{$indexer} = +{
44 8         15 map { ( $_->{$field} => $_ ) } @{$data->{values}}
  15         77  
  8         17  
45             }
46             }
47             }
48              
49 11         25 return $data;
50             }
51              
52             sub _mk_values {
53 4     4   7 my ($pkg, $data) = @_;
54 2     2   11 no strict 'refs';
  2         4  
  2         326  
55 4         25 *{"$pkg\::values"} = sub {
56 15     15   10554 my $values = $data->{values};
57 15 100       81 wantarray ? @$values : [ @$values ];
58 4         14 };
59             }
60              
61             sub _mk_indexer {
62 3     3   5 my ($pkg, $meta, $data) = @_;
63 3         4 for my $indexer (keys %{$meta->{indexer}}) {
  3         10  
64 4         7 my $field = $meta->{indexer}->{$indexer};
65              
66 2     2   14 no strict 'refs';
  2         4  
  2         391  
67 4         27 *{"$pkg\::$indexer"} = sub {
68 19     19   18367 my ($class, $field_val) = @_;
69             return defined $field_val
70 19 50       103 ? $data->{indexer}->{$indexer}->{$field_val}
71             : undef;
72 4         13 };
73             }
74             }
75              
76             sub _mk_getter {
77 2     2   3 my ($pkg, $defs) = @_;
78 2         3 my $all_keys = [ keys %{ +{ map { %$_ } @$defs } }];
  2         4  
  5         29  
79 2         10 for my $field (@$all_keys) {
80 2     2   12 no strict 'refs';
  2         4  
  2         214  
81 6     12   25 *{"$pkg\::$field"} = sub { $_[0]->{$field} } ;
  6         31  
  12         1017  
82             }
83             }
84              
85             sub _mk_local {
86 7     7   14 my ($pkg, $meta, $data) = @_;
87 2     2   14 no strict 'refs';
  2         4  
  2         338  
88 7         3854 *{"$pkg\::local"} = sub {
89 5     5   3605 my ($class, @defs) = @_;
90 5 100       167 Carp::croak("Cannot use $class\::local in void context") unless defined wantarray;
91              
92 4         16 my %orig_data = %$data;
93 4         12 my $local_data = _generate_data($pkg, $meta, \@defs);
94 4         16 %$data = %$local_data;
95 4     4   35 return Guard::guard { %$data = %orig_data };
  4         1374  
96 7         37 };
97             }
98              
99             1;
100             __END__