File Coverage

blib/lib/Object/Stash.pm
Criterion Covered Total %
statement 77 78 98.7
branch 25 30 83.3
condition 15 19 78.9
subroutine 17 17 100.0
pod 1 1 100.0
total 135 145 93.1


line stmt bran cond sub pod time code
1             package Object::Stash;
2              
3 5     5   131020 use 5.010;
  5         18  
  5         197  
4 5     5   33 use strict;
  5         26  
  5         179  
5 5     5   5548 use utf8;
  5         56  
  5         25  
6              
7             BEGIN {
8 5     5   264 $Object::Stash::AUTHORITY = 'cpan:TOBYINK';
9 5         130 $Object::Stash::VERSION = '0.005';
10             }
11              
12 5     5   28 use Carp qw/croak/;
  5         7  
  5         342  
13 5     5   4464 use Hash::FieldHash qw/fieldhashes/;
  5         9695  
  5         343  
14 5     5   33 use Scalar::Util qw/blessed/;
  5         9  
  5         602  
15 5     5   4253 use Sub::Name qw/subname/;
  5         3092  
  5         364  
16              
17             my %known_stashes;
18             my %Stashes;
19             BEGIN {
20 5     5   21 fieldhashes \%known_stashes, \%Stashes;
21             }
22              
23             sub import
24             {
25 10     10   70 my ($invocant, @args) = @_;
26            
27 10         15 my %args;
28 10         38 while (defined(my $arg = shift @args))
29             {
30 5 100       42 if ($arg =~ /^-/)
31             {
32 2         8 $args{$arg} = shift @args;
33             }
34             else
35             {
36 3         1 push @{$args{-method}}, $arg;
  3         12  
37             }
38             }
39 10   100     66 $args{-method} //= ['stash'];
40 10   100     49 $args{-type} //= 'hashref';
41            
42 10 50       46 croak sprintf("Stash type '%s' is unknown.", $args{-type})
43             unless $args{-type} =~ m{^ hashref | object $}ix;
44            
45 10   66     54 my $caller = $args{-package} // caller;
46            
47 10         10 for my $method (@{$args{-method}})
  10         24  
48             {
49 5     5   1048 no strict 'refs';
  5         8  
  5         3144  
50 11         37 my $name = "$caller\::$method";
51 11     28   147 *$name = my $ref = subname($name, sub { unshift @_, $name, lc $args{-type}; goto &_stash; });
  28     28   4066  
  28     10   99  
52 11         50 $known_stashes{ $ref } = $name;
53              
54 11 100       4342 if (lc $args{-type} eq 'object')
55             {
56 1         2 my $name_autoload = $name . '::AUTOLOAD';
57             my $autoload = sub :lvalue
58             {
59 5     23   7 my ($func) = (${$name_autoload} =~ /::([^:]+)$/);
  5         42  
60 5         10 my $self = shift;
61 5 100       12 $self->{$func} = shift if @_;
62 5         27 $self->{$func};
63 1         9 };
64 1         1749 *$name_autoload = subname($name_autoload, $autoload);
65             }
66             }
67             }
68              
69             sub is_stash
70             {
71 6 100 66 11 1 87 shift if (!ref $_[0] and $_[0]->isa(__PACKAGE__));
72 6         10 my ($name) = @_;
73            
74 6 100       41 return $known_stashes{ $name } if exists $known_stashes{ $name };
75 1         6 return;
76             }
77              
78             {
79             sub _stash
80             {
81 28     33   63 my ($stashname, $type, $self, @args) = @_;
82            
83 28         35 my (%set, @retrieve);
84 28 100 100     199 if (scalar @args == 1 and ref $args[0] eq 'HASH')
    100 66        
    50          
    0          
85             {
86 1         3 %set = %{ $args[0] };
  1         5  
87             }
88             elsif (scalar @args == 1 and ref $args[0] eq 'ARRAY')
89             {
90 2         5 @retrieve = @{ $args[0] };
  2         24  
91             }
92             elsif (scalar @args % 2 == 0)
93             {
94 25         59 %set = @args;
95             }
96             elsif (@args)
97             {
98 0         0 croak "$stashname expects to be passed a hash, hash reference, or nothing.";
99             }
100            
101 28 50 66     115 return unless (defined wantarray or @args);
102            
103 28         113 my $stash = $Stashes{ $self }{ $stashname };
104 28 100       73 unless (defined $stash)
105             {
106 16 100       70 $stash = $Stashes{ $self }{ $stashname }
107             = ($type eq 'object' ? (bless {}, $stashname) : {});
108             }
109            
110 28         113 while (my ($k, $v) = each %set)
111             {
112 18         76 $stash->{$k} = $v;
113             }
114            
115 28 100       675 if (@retrieve)
116             {
117 2         5 my @return = map { $stash->{$_} } @retrieve;
  4         12  
118 2 100       17 return wantarray ? @return : \@return;
119             }
120            
121 26         726 return $stash;
122             }
123             }
124              
125             'Secret stash';
126              
127             __END__