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   6600 use strict;
  14         37  
  14         461  
3 14     14   55 use warnings;
  14         15  
  14         347  
4 14     14   52 use parent qw(Data::Focus::Lens);
  14         19  
  14         61  
5 14     14   5355 use Data::Focus::LensMaker ();
  14         22  
  14         240  
6 14     14   64 use Carp;
  14         18  
  14         7774  
7              
8             our @CARP_NOT = qw(Data::Focus::Lens Data::Focus);
9              
10             sub new {
11 222     222 1 222555 my ($class, %args) = @_;
12 222         375 my $indices = [];
13 222 50       595 if(exists($args{index})) {
14 222 100       526 if(ref($args{index}) eq "ARRAY") {
15 63         107 $indices = $args{index};
16             }else {
17 159         285 $indices = [$args{index}];
18             }
19             }
20 222 50       487 croak "index must be mandatory" if !@$indices;
21 222 50       325 croak "index must be defined" if grep { !defined($_) } @$indices;
  352         874  
22 222         1011 my $self = bless {
23             indices => $indices,
24             immutable => $args{immutable},
25             }, $class;
26 222         715 return $self;
27             }
28              
29             sub _getter {
30 9058     9058   9095 my ($self, $whole) = @_;
31 9058         10024 my $type = ref($whole);
32 9058 100       19743 if(!defined($whole)) {
    100          
    100          
33             ## slots for autovivification
34 1630         1517 return map { undef } @{$self->{indices}};
  3494         5076  
  1630         2671  
35             }elsif($type eq "ARRAY") {
36 3328         3295 my @indices = map { int($_) } @{$self->{indices}};
  5836         8428  
  3328         6107  
37 3328         3658 return @{$whole}[@indices];
  3328         8606  
38             }elsif($type eq "HASH") {
39 2920         2558 return @{$whole}{@{$self->{indices}}};
  2920         7778  
  2920         4047  
40             }else {
41             ## no slot. cannot set.
42 1180         2937 return ();
43             }
44             }
45            
46             sub _setter {
47 8336     8336   9914 my ($self, $whole, @parts) = @_;
48 8336 100       14488 return $whole if !@parts;
49 7224 100       12976 if(!defined($whole)) {
50             ## autovivifying
51 1565 100       1215 if(grep { $_ !~ /^\d+$/ } @{$self->{indices}}) {
  3376         9518  
  1565         2116  
52 790         838 return +{ map { $self->{indices}[$_] => $parts[$_] } 0 .. $#{$self->{indices}} };
  1569         4064  
  790         1239  
53             }else {
54 775         983 my $ret = [];
55 775         781 $ret->[$self->{indices}[$_]] = $parts[$_] foreach 0 .. $#{$self->{indices}};
  775         3496  
56 775         2004 return $ret;
57             }
58             }
59 5659         5995 my $type = ref($whole);
60 5659 100       10073 if($type eq "ARRAY") {
    50          
61 3017         2598 my @indices = map { int($_) } @{$self->{indices}};
  5341         7147  
  3017         4347  
62 3017 100       7020 my $ret = $self->{immutable} ? [@$whole] : $whole;
63 3017         5595 foreach my $i (0 .. $#indices) {
64 5339         4934 my $index = $indices[$i];
65 5339 100       9614 croak "$index: negative out-of-range index" if $index < -(@$ret);
66 5333         8505 $ret->[$index] = $parts[$i];
67             }
68 3011         7849 return $ret;
69             }elsif($type eq "HASH") {
70 2642 100       6983 my $ret = $self->{immutable} ? {%$whole} : $whole;
71 2642         2428 $ret->{$self->{indices}[$_]} = $parts[$_] foreach 0 .. $#{$self->{indices}};
  2642         10705  
72 2642         6478 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__