File Coverage

blib/lib/Object/Stash.pm
Criterion Covered Total %
statement 14 14 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 19 19 100.0


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