File Coverage

blib/lib/Resource/Silo.pm
Criterion Covered Total %
statement 57 57 100.0
branch 10 10 100.0
condition 10 13 76.9
subroutine 14 14 100.0
pod 1 1 100.0
total 92 95 96.8


line stmt bran cond sub pod time code
1             package Resource::Silo;
2              
3 49     49   5070477 use 5.010;
  49         183  
4 49     49   258 use strict;
  49         224  
  49         1158  
5 49     49   232 use warnings;
  49         150  
  49         3339  
6              
7             our $VERSION = '0.17';
8              
9 49     49   269 use Carp;
  49         188  
  49         3435  
10 49     49   273 use Scalar::Util qw( set_prototype );
  49         79  
  49         2715  
11              
12 49     49   21705 use Resource::Silo::Metadata;
  49         148  
  49         1840  
13 49     49   25370 use Resource::Silo::Container;
  49         159  
  49         2171  
14              
15             # This is a dummy block to hint IDEs.
16             # see 'import' below for _real_ resource & silo implementation
17 49     49   18439 use parent 'Exporter';
  49         12326  
  49         256  
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   2495 my ($self, @param) = @_;
29 58         163 my $caller = caller;
30 58         582 my $target;
31             my $shortcut;
32              
33 58         213 while (@param) {
34 41         86 my $flag = shift @param;
35 41 100       132 if ($flag eq '-class') {
    100          
36 37         105 $target = $caller;
37             } elsif ($flag eq '-shortcut') {
38 3         9 $shortcut = shift @param;
39 3 100 33     49 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         180 croak "Unexpected parameter to 'use $self': '$flag'";
44             };
45             };
46              
47 56 100       143 if (!defined $target) {
48             # we're not in class mode, create a one-off package
49 19         40 $target = __PACKAGE__ . "::container::" . $caller;
50 19   100     109 $shortcut //= 'silo';
51             }
52              
53 56         358 my $spec = Resource::Silo::Metadata->new($target);
54 56         151 $metadata{$target} = $spec;
55              
56 56         81 my $instance;
57             my $shortcut_sub = defined $shortcut
58             ? set_prototype {
59             # cannot instantiate target until the package is fully defined,
60             # thus go lazy
61 64   100 64   452355 $instance //= $target->new;
62             } ''
63             : set_prototype {
64             # TODO 2027-01-01: remove the deprecation & just skip it entirely
65 1     1   10 croak "Resource::Silo: 'silo' is not exported anymore when -class is in action, use explicit -shortcut => ... instead"
66 56 100       694 } '';
67              
68 56   100     515 $shortcut //= 'silo'; # only for deprecation
69              
70 49     49   18220 no strict 'refs'; ## no critic
  49         118  
  49         1985  
71 49     49   233 no warnings 'redefine', 'once'; ## no critic
  49         97  
  49         9603  
72              
73 56         68 push @{"${target}::ISA"}, 'Resource::Silo::Container';
  56         874  
74              
75 56         247 *{"${caller}::resource"} = $spec->_make_dsl;
  56         381  
76 56         97 *{"${caller}::$shortcut"} = $shortcut_sub;
  56         78968  
77             };
78              
79             sub get_meta {
80 1     1 1 831 my ($self, $target) = @_;
81              
82 1         3 return $metadata{$target};
83             }
84              
85             1; # End of Resource::Silo
86              
87             __END__