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   4689602 use 5.010;
  49         155  
4 49     49   225 use strict;
  49         186  
  49         1142  
5 49     49   223 use warnings;
  49         63  
  49         2960  
6              
7             our $VERSION = '0.1701';
8              
9 49     49   224 use Carp;
  49         132  
  49         3111  
10 49     49   256 use Scalar::Util qw( set_prototype );
  49         79  
  49         2419  
11              
12 49     49   21579 use Resource::Silo::Metadata;
  49         154  
  49         1838  
13 49     49   24238 use Resource::Silo::Container;
  49         141  
  49         1900  
14              
15             # This is a dummy block to hint IDEs.
16             # see 'import' below for _real_ resource & silo implementation
17 49     49   17813 use parent 'Exporter';
  49         12164  
  49         242  
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   3191 my ($self, @param) = @_;
29 58         273 my $caller = caller;
30 58         609 my $target;
31             my $shortcut;
32              
33 58         214 while (@param) {
34 41         75 my $flag = shift @param;
35 41 100       129 if ($flag eq '-class') {
    100          
36 37         96 $target = $caller;
37             } elsif ($flag eq '-shortcut') {
38 3         8 $shortcut = shift @param;
39 3 100 33     44 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         147 croak "Unexpected parameter to 'use $self': '$flag'";
44             };
45             };
46              
47 56 100       127 if (!defined $target) {
48             # we're not in class mode, create a one-off package
49 19         35 $target = __PACKAGE__ . "::container::" . $caller;
50 19   100     119 $shortcut //= 'silo';
51             }
52              
53 56         349 my $spec = Resource::Silo::Metadata->new($target);
54 56         145 $metadata{$target} = $spec;
55              
56 56         97 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   366971 $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       663 } '';
67              
68 56   100     358 $shortcut //= 'silo'; # only for deprecation
69              
70 49     49   16174 no strict 'refs'; ## no critic
  49         76  
  49         1852  
71 49     49   191 no warnings 'redefine', 'once'; ## no critic
  49         99  
  49         9064  
72              
73 56         125 push @{"${target}::ISA"}, 'Resource::Silo::Container';
  56         731  
74              
75 56         247 *{"${caller}::resource"} = $spec->_make_dsl;
  56         233  
76 56         99 *{"${caller}::$shortcut"} = $shortcut_sub;
  56         80919  
77             };
78              
79             sub get_meta {
80 1     1 1 794 my ($self, $target) = @_;
81              
82 1         2 return $metadata{$target};
83             }
84              
85             1; # End of Resource::Silo
86              
87             __END__