File Coverage

blib/lib/Resource/Silo.pm
Criterion Covered Total %
statement 60 61 98.3
branch 10 10 100.0
condition 10 13 76.9
subroutine 14 14 100.0
pod 1 1 100.0
total 95 99 95.9


line stmt bran cond sub pod time code
1             package Resource::Silo;
2              
3 49     49   6590400 use 5.010;
  49         214  
4 49     49   324 use strict;
  49         253  
  49         1614  
5 49     49   321 use warnings;
  49         135  
  49         5437  
6              
7             our $VERSION = '0.1703';
8              
9 49     49   324 use Carp;
  49         182  
  49         4712  
10 49     49   379 use Scalar::Util qw( set_prototype );
  49         112  
  49         3709  
11              
12 49     49   29428 use Resource::Silo::Metadata;
  49         190  
  49         2478  
13 49     49   33131 use Resource::Silo::Container;
  49         207  
  49         2514  
14              
15             # This is a dummy block to hint IDEs.
16             # see 'import' below for _real_ resource & silo implementation
17 49     49   26719 use parent 'Exporter';
  49         15589  
  49         301  
18             our @EXPORT = qw( resource silo );
19             #@returns Resource::Silo::Container
20             sub silo (); ## no critic 'prototypes'
21             sub resource (@); ## no critic 'prototypes'
22              
23             # We'll need a global metadata storage
24             # to allow extending container classes
25             our %metadata;
26              
27             sub import {
28 58     58   3598 my ($self, @param) = @_;
29 58         226 my $caller = caller;
30 58         672 my $target;
31             my $shortcut;
32              
33 58         270 while (@param) {
34 41         93 my $flag = shift @param;
35 41 100       163 if ($flag eq '-class') {
    100          
36 37         126 $target = $caller;
37             } elsif ($flag eq '-shortcut') {
38 3         8 $shortcut = shift @param;
39 3 100 33     50 croak "-shortcut must be an identifier"
      66        
40             unless $shortcut and !ref $shortcut and $shortcut =~ /^[a-z_][a-z_0-9]*$/i;
41             } else {
42             # TODO if there's more than 3 elsifs, use jump table instead
43 1         213 croak "Unexpected parameter to 'use $self': '$flag'";
44             };
45             };
46              
47 56 100       217 if (!defined $target) {
48             # we're not in class mode, create a one-off package
49 19         66 $target = __PACKAGE__ . "::container::" . $caller;
50 19   100     141 $shortcut //= 'silo';
51             }
52              
53 56         475 my $spec = Resource::Silo::Metadata->new($target);
54 56         171 $metadata{$target} = $spec;
55              
56 56         119 my $instance;
57             my $shortcut_sub = set_prototype {
58             # cannot instantiate target until the package is fully defined,
59             # thus go lazy
60 64   100 64   534899 $instance //= $target->new;
61 56         700 } '';
62              
63 56 100       252 if (!defined $shortcut) {
64             # TODO remove deprecation after 2027-01-01 and just let it die
65 36         69 my $orig = $shortcut_sub;
66             $shortcut_sub = sub {
67 1     1   11 carp "'silo' is deprecated when -class is in action, use explicit -shortcut instead";
68 0         0 goto &$orig;
69             }
70 36         128 }
71              
72 56   100     523 $shortcut //= 'silo'; # only for deprecation
73              
74 49     49   24007 no strict 'refs'; ## no critic
  49         113  
  49         2681  
75 49     49   314 no warnings 'redefine', 'once'; ## no critic
  49         98  
  49         11624  
76              
77 56         89 push @{"${target}::ISA"}, 'Resource::Silo::Container';
  56         1439  
78              
79 56         308 *{"${caller}::resource"} = $spec->_make_dsl;
  56         383  
80 56         137 *{"${caller}::$shortcut"} = $shortcut_sub;
  56         100248  
81             };
82              
83             sub get_meta {
84 1     1 1 1275 my ($self, $target) = @_;
85              
86 1         3 return $metadata{$target};
87             }
88              
89             1; # End of Resource::Silo
90              
91             __END__