File Coverage

blib/lib/Factory/Sub.pm
Criterion Covered Total %
statement 65 67 97.0
branch 22 24 91.6
condition 2 2 100.0
subroutine 13 13 100.0
pod 3 4 75.0
total 105 110 95.4


line stmt bran cond sub pod time code
1             package Factory::Sub;
2 3     3   335210 use 5.006; use strict; use warnings;
  3     3   11  
  3     3   22  
  3         21  
  3         128  
  3         38  
  3         4  
  3         170  
3 3     3   1774 use Import::Into; use Carp qw/croak/; use Coerce::Types::Standard qw//;
  3     3   9913  
  3     3   153  
  3         26  
  3         8  
  3         228  
  3         1903  
  3         597176  
  3         370  
4             our $VERSION = '0.10';
5              
6             use overload
7 11     11   6700 "&{}" => sub {my $self = shift; sub { $self->call(@_) }},
  11         50  
  11         35  
8 3     3   43 fallback => 1;
  3         8  
  3         36  
9              
10             sub import {
11 3     3   61 my ($pkg, @import) = @_;
12 3 100       31 if (@import) {
13 2         12 my $target = caller;
14 2         17 Coerce::Types::Standard->import::into($target, @import)
15             }
16             }
17              
18             sub new {
19 2     2 1 456142 my $self = shift;
20 2         7 my $fallback;
21 2         14 for (my $i = 0; $i < scalar @_; $i++) {
22 5 100       7 if ( scalar @{$_[$i]} == 1 ) {
  5         18  
23 1         3 $fallback = splice @_, $i, 1;
24 1         4 $i--;
25             }
26             }
27 2 100       21 bless { factory => [ @_ ], ($fallback ? (fallback => $fallback->[0]) : ()) }, $self;
28             }
29              
30             sub add {
31 6     6 1 14742 my ($self, @args) = @_;
32 6 100       19 if (scalar @args == 1) {
33 1         6 $self->{fallback} = $args[0];
34             } else {
35 5         7 push @{ $self->{factory} }, \@args;
  5         63  
36             }
37             }
38              
39             sub call {
40 11     11 1 45 my ($self, @params) = @_;
41             FACTORY:
42 11         13 for my $factory ( @{ $self->{factory} } ) {
  11         31  
43 35 100       19530 if ( scalar @{$factory} - 1 == scalar @params) {
  35         81  
44 17         23 my @factory_params = @{clone(\@params)};
  17         36  
45 17         49 for (my $i = 0; $i < scalar @factory_params; $i++) {
46 29 100       37 eval { $factory_params[$i] = $factory->[$i]->(
47             ref $factory->[$i] eq 'Type::Tiny'
48 29 100 100     95 && scalar @{$factory->[$i]->{coercion}->{type_coercion_map}}
49             ? $factory->[$i]->coerce($factory_params[$i])
50             : $factory_params[$i]
51 21         5530 ); 1; } or next FACTORY;
52             }
53 9         31 return $factory->[-1]->(@factory_params);
54             }
55             }
56 2 100       306 if ($self->{fallback}) {
57 1         5 return $self->{fallback}->(@params);
58             }
59 1 50       3 croak "No matching factory sub for given params " . join " ", map { ! defined $_ ? 'undef' : $_ } @params;
  3         143  
60             }
61              
62             sub clone {
63 84     84 0 122 my ($clone) = @_;
64 84         119 my $ref = ref $clone;
65 84 100       195 if ($ref eq 'ARRAY') { return [ map { clone($_) } @{$clone} ]; }
  23 100       37  
  55 50       80  
  23         38  
66 12         16 elsif ($ref eq 'HASH') { return { map +( $_ => clone($clone->{$_}) ), keys %{$clone} }; }
  12         45  
67 0         0 elsif ($ref eq 'SCALAR') { my $r = clone($$clone); return \$r; }
  0         0  
68 49         146 return $clone;
69             }
70              
71             1;
72              
73             __END__;