File Coverage

blib/lib/Data/Focus/Lens/HashArray/Index.pm
Criterion Covered Total %
statement 77 78 98.7
branch 30 34 88.2
condition n/a
subroutine 10 10 100.0
pod 1 1 100.0
total 118 123 95.9


line stmt bran cond sub pod time code
1             package Data::Focus::Lens::HashArray::Index;
2 17     17   6628 use strict;
  17         23  
  17         527  
3 17     17   63 use warnings;
  17         19  
  17         424  
4 17     17   57 use parent qw(Data::Focus::Lens);
  17         19  
  17         71  
5 17     17   5335 use Data::Focus::LensMaker ();
  17         22  
  17         313  
6 17     17   68 use Scalar::Util qw(reftype);
  17         17  
  17         878  
7 17     17   60 use Carp;
  17         16  
  17         8889  
8              
9             our @CARP_NOT = qw(Data::Focus::Lens Data::Focus);
10              
11             sub new {
12 356     356 1 348928 my ($class, %args) = @_;
13 356         511 my $indices = [];
14 356 50       842 if(exists($args{index})) {
15 356 100       752 if(ref($args{index}) eq "ARRAY") {
16 101         162 $indices = $args{index};
17             }else {
18 255         389 $indices = [$args{index}];
19             }
20             }
21 356 50       791 croak "index must be mandatory" if !@$indices;
22 356 50       481 croak "index must be defined" if grep { !defined($_) } @$indices;
  572         1143  
23 356         1589 my $self = bless {
24             indices => $indices,
25             immutable => $args{immutable},
26             allow_blessed => $args{allow_blessed},
27             }, $class;
28 356         829 return $self;
29             }
30              
31             sub _type_of {
32 29544     29544   19168 my ($self, $target) = @_;
33 29544 100       39697 if($self->{allow_blessed}) {
34 14805         19176 my $ref = reftype($target);
35 14805 100       27295 return defined($ref) ? $ref : "";
36             }else {
37 14739         21594 return ref($target);
38             }
39             }
40              
41             sub _getter {
42 17923     17923   14564 my ($self, $whole) = @_;
43 17923         20456 my $type = $self->_type_of($whole);
44 17923 100       34044 if(!defined($whole)) {
    100          
    100          
45             ## slots for autovivification
46 3204         2523 return map { undef } @{$self->{indices}};
  6896         8078  
  3204         3825  
47             }elsif($type eq "ARRAY") {
48 6592         4947 my @indices = map { int($_) } @{$self->{indices}};
  11582         13031  
  6592         7912  
49 6592         5998 return @{$whole}[@indices];
  6592         13473  
50             }elsif($type eq "HASH") {
51 6158         4568 return @{$whole}{@{$self->{indices}}};
  6158         13186  
  6158         6471  
52             }else {
53             ## no slot. cannot set.
54 1969         3921 return ();
55             }
56             }
57            
58             sub _setter {
59 16575     16575   17621 my ($self, $whole, @parts) = @_;
60 16575 100       24346 return $whole if !@parts;
61 14723 100       21457 if(!defined($whole)) {
62             ## autovivifying
63 3102 100       2166 if(grep { $_ !~ /^\d+$/ } @{$self->{indices}}) {
  6705         14731  
  3102         3459  
64 1559         1303 return +{ map { $self->{indices}[$_] => $parts[$_] } 0 .. $#{$self->{indices}} };
  3106         6629  
  1559         2118  
65             }else {
66 1543         1509 my $ret = [];
67 1543         1159 $ret->[$self->{indices}[$_]] = $parts[$_] foreach 0 .. $#{$self->{indices}};
  1543         5612  
68 1543         3240 return $ret;
69             }
70             }
71 11621         12676 my $type = $self->_type_of($whole);
72 11621 100       16806 if($type eq "ARRAY") {
    50          
73 6007         3866 my @indices = map { int($_) } @{$self->{indices}};
  10639         11552  
  6007         6613  
74 6007 100       10732 my $ret = $self->{immutable} ? [@$whole] : $whole;
75 6007         9104 foreach my $i (0 .. $#indices) {
76 10637         7975 my $index = $indices[$i];
77 10637 100       14199 croak "$index: negative out-of-range index" if $index < -(@$ret);
78 10631         13905 $ret->[$index] = $parts[$i];
79             }
80 6001         11560 return $ret;
81             }elsif($type eq "HASH") {
82 5614 100       11480 my $ret = $self->{immutable} ? {%$whole} : $whole;
83 5614         4629 $ret->{$self->{indices}[$_]} = $parts[$_] foreach 0 .. $#{$self->{indices}};
  5614         19039  
84 5614         10300 return $ret;
85             }else {
86 0           confess "This should not be executed because the getter should return an empty list.";
87             }
88             }
89              
90             Data::Focus::LensMaker::make_lens_from_accessors(\&_getter, \&_setter);
91              
92             1;
93              
94             __END__