File Coverage

blib/lib/Data/Focus.pm
Criterion Covered Total %
statement 61 61 100.0
branch 13 16 81.2
condition 2 3 66.6
subroutine 16 16 100.0
pod 8 8 100.0
total 100 104 96.1


line stmt bran cond sub pod time code
1             package Data::Focus;
2 29     29   382420 use strict;
  29         50  
  29         941  
3 29     29   103 use warnings;
  29         38  
  29         824  
4 29     29   8758 use Data::Focus::Lens::Composite;
  29         232  
  29         648  
5 29     29   137 use Carp;
  29         34  
  29         2154  
6 29     29   151 use Exporter qw(import);
  29         32  
  29         670  
7 29     29   105 use Scalar::Util ();
  29         33  
  29         14275  
8              
9             our $VERSION = "0.03";
10              
11             our @EXPORT_OK = qw(focus);
12              
13             sub focus {
14 22483     22483 1 319669 my ($target, @lenses) = @_;
15 22483         38894 return __PACKAGE__->new(target => $target, lens => \@lenses);
16             }
17              
18             sub new {
19 22493     22493 1 35669 my ($class, %args) = @_;
20 22493 50       34761 croak "target param is mandatory" if !exists($args{target});
21 22493         18069 my $target = $args{target};
22 22493 100       45240 my $lenses = exists($args{lens}) ?
    100          
23             (ref($args{lens}) eq "ARRAY" ? $args{lens} : [$args{lens}])
24             : [];
25 22493         28341 $_ = $class->coerce_to_lens($_) foreach @$lenses;
26 22493         49226 my $self = bless {
27             target => $target,
28             lenses => $lenses
29             }, $class;
30 22493         50341 return $self;
31             }
32              
33             sub coerce_to_lens {
34 22584     22584 1 19629 my (undef, $maybe_lens) = @_;
35 22584 100 66     99717 if(Scalar::Util::blessed($maybe_lens) && $maybe_lens->isa("Data::Focus::Lens")) {
36 22538         49362 return $maybe_lens;
37             }else {
38 46         1299 require Data::Focus::Lens::Dynamic;
39 46         99 return Data::Focus::Lens::Dynamic->new($maybe_lens);
40             }
41             }
42              
43             sub into {
44 6     6 1 11 my ($self, @lenses) = @_;
45 6         7 unshift @lenses, @{$self->{lenses}};
  6         10  
46 6         13 my $deeper = ref($self)->new(
47             target => $self->{target},
48             lens => \@lenses,
49             );
50 6         11 return $deeper;
51             }
52              
53             sub _apply_lenses_to_target {
54 22528     22528   24261 my ($self, $app_class, $updater, @additional_lenses) = @_;
55 22528         15172 my @lenses = (@{$self->{lenses}}, map { $self->coerce_to_lens($_) } @additional_lenses);
  22528         31333  
  22515         24167  
56 22528 100       26403 if(@lenses == 1) {
57 22443         47489 return $lenses[0]->apply_lens(
58             $app_class, $app_class->create_part_mapper($updater), $self->{target}
59             );
60             }else {
61 85         246 return Data::Focus::Lens::Composite->apply_composite_lens(
62             \@lenses,
63             $app_class,
64             $app_class->create_part_mapper($updater),
65             $self->{target}
66             );
67             }
68             }
69              
70             sub get {
71 642     642 1 4126 my ($self, @lenses) = @_;
72 642         11272 require Data::Focus::Applicative::Const::First;
73 642         1178 my $ret = $self->_apply_lenses_to_target(
74             "Data::Focus::Applicative::Const::First", undef, @lenses
75             )->get_const;
76 639 100       3485 return defined($ret) ? $$ret : undef;
77             }
78              
79             sub list {
80 1011     1011 1 1299 my ($self, @lenses) = @_;
81 1011         11426 require Data::Focus::Applicative::Const::List;
82 1011         1648 my $traversed_list = $self->_apply_lenses_to_target(
83             "Data::Focus::Applicative::Const::List", undef, @lenses
84             )->get_const;
85 1011 50       5569 return wantarray ? @$traversed_list : $traversed_list->[0];
86             }
87              
88             sub over {
89 20875     20875 1 14649 my $updater = pop;
90 20875         21163 my ($self, @lenses) = @_;
91 20875 50       30058 croak "updater param must be a code-ref" if ref($updater) ne "CODE";
92 20875         71144 require Data::Focus::Applicative::Identity;
93 20875         28601 return $self->_apply_lenses_to_target(
94             "Data::Focus::Applicative::Identity", $updater, @lenses
95             )->run_identity;
96             }
97              
98             sub set {
99 20852     20852 1 21131 my $datum = pop;
100 20852         13880 my $self = shift;
101 20852     31159   51688 return $self->over(@_, sub { $datum });
  31159         52016  
102             }
103              
104             1;
105             __END__