File Coverage

blib/lib/Data/Focus/Lens/HashArray/Index.pm
Criterion Covered Total %
statement 69 70 98.5
branch 26 30 86.6
condition n/a
subroutine 8 8 100.0
pod 1 1 100.0
total 104 109 95.4


line stmt bran cond sub pod time code
1             package Data::Focus::Lens::HashArray::Index;
2 14     14   7131 use strict;
  14         19  
  14         509  
3 14     14   69 use warnings;
  14         22  
  14         366  
4 14     14   53 use parent qw(Data::Focus::Lens);
  14         14  
  14         68  
5 14     14   6029 use Data::Focus::LensMaker ();
  14         56  
  14         264  
6 14     14   69 use Carp;
  14         21  
  14         8463  
7              
8             our @CARP_NOT = qw(Data::Focus::Lens Data::Focus);
9              
10             sub new {
11 222     222 1 180527 my ($class, %args) = @_;
12 222         347 my $indices = [];
13 222 50       617 if(exists($args{index})) {
14 222 100       515 if(ref($args{index}) eq "ARRAY") {
15 63         114 $indices = $args{index};
16             }else {
17 159         272 $indices = [$args{index}];
18             }
19             }
20 222 50       521 croak "index must be mandatory" if !@$indices;
21 222 50       310 croak "index must be defined" if grep { !defined($_) } @$indices;
  352         789  
22 222         944 my $self = bless {
23             indices => $indices,
24             immutable => $args{immutable},
25             }, $class;
26 222         650 return $self;
27             }
28              
29             sub _getter {
30 9058     9058   7473 my ($self, $whole) = @_;
31 9058         8907 my $type = ref($whole);
32 9058 100       19090 if(!defined($whole)) {
    100          
    100          
33             ## slots for autovivification
34 1630         1501 return map { undef } @{$self->{indices}};
  3494         5725  
  1630         2520  
35             }elsif($type eq "ARRAY") {
36 3328         2907 my @indices = map { int($_) } @{$self->{indices}};
  5836         7436  
  3328         5064  
37 3328         3298 return @{$whole}[@indices];
  3328         8461  
38             }elsif($type eq "HASH") {
39 2920         2560 return @{$whole}{@{$self->{indices}}};
  2920         8087  
  2920         3659  
40             }else {
41             ## no slot. cannot set.
42 1180         2260 return ();
43             }
44             }
45            
46             sub _setter {
47 8336     8336   9703 my ($self, $whole, @parts) = @_;
48 8336 100       15565 return $whole if !@parts;
49 7224 100       11325 if(!defined($whole)) {
50             ## autovivifying
51 1565 100       1210 if(grep { $_ !~ /^\d+$/ } @{$self->{indices}}) {
  3376         9503  
  1565         2018  
52 790         800 return +{ map { $self->{indices}[$_] => $parts[$_] } 0 .. $#{$self->{indices}} };
  1569         4304  
  790         1184  
53             }else {
54 775         1022 my $ret = [];
55 775         719 $ret->[$self->{indices}[$_]] = $parts[$_] foreach 0 .. $#{$self->{indices}};
  775         3326  
56 775         1892 return $ret;
57             }
58             }
59 5659         5357 my $type = ref($whole);
60 5659 100       8824 if($type eq "ARRAY") {
    50          
61 3017         2494 my @indices = map { int($_) } @{$self->{indices}};
  5341         6373  
  3017         4283  
62 3017 100       6104 my $ret = $self->{immutable} ? [@$whole] : $whole;
63 3017         5308 foreach my $i (0 .. $#indices) {
64 5339         4557 my $index = $indices[$i];
65 5339 100       9199 croak "$index: negative out-of-range index" if $index < -(@$ret);
66 5333         8354 $ret->[$index] = $parts[$i];
67             }
68 3011         7633 return $ret;
69             }elsif($type eq "HASH") {
70 2642 100       6883 my $ret = $self->{immutable} ? {%$whole} : $whole;
71 2642         2521 $ret->{$self->{indices}[$_]} = $parts[$_] foreach 0 .. $#{$self->{indices}};
  2642         9559  
72 2642         5971 return $ret;
73             }else {
74 0           confess "This should not be executed because the getter should return an empty list.";
75             }
76             }
77              
78             Data::Focus::LensMaker::make_lens_from_accessors(\&_getter, \&_setter);
79              
80             1;
81              
82             __END__