File Coverage

blib/lib/Iterator/Flex/Cache.pm
Criterion Covered Total %
statement 68 68 100.0
branch 10 14 71.4
condition 12 12 100.0
subroutine 19 19 100.0
pod 1 2 50.0
total 110 115 95.6


line stmt bran cond sub pod time code
1             package Iterator::Flex::Cache;
2              
3             # ABSTRACT: Cache Iterator Class
4              
5 3     3   172480 use v5.28;
  3         11  
6 3     3   11 use strict;
  3         4  
  3         93  
7 3     3   11 use warnings;
  3         3  
  3         130  
8 3     3   375 use experimental qw( signatures postderef );
  3         1243  
  3         15  
9              
10             our $VERSION = '0.34';
11              
12 3     3   488 use parent 'Iterator::Flex::Base';
  3         5  
  3         29  
13 3     3   192 use Iterator::Flex::Utils qw( STATE :IterAttrs :IterStates throw_failure );
  3         5  
  3         550  
14 3     3   423 use Iterator::Flex::Factory 'to_iterator';
  3         5  
  3         136  
15 3     3   13 use Scalar::Util;
  3         3  
  3         98  
16 3     3   11 use Ref::Util;
  3         4  
  3         86  
17              
18 3     3   11 use namespace::clean;
  3         4  
  3         39  
19              
20              
21              
22              
23              
24              
25              
26              
27              
28              
29              
30              
31              
32              
33              
34              
35              
36              
37              
38              
39              
40              
41              
42              
43              
44              
45              
46              
47              
48              
49              
50              
51              
52              
53              
54              
55              
56              
57              
58              
59              
60              
61 13     13 1 14 sub new ( $class, $iterable, $pars = {} ) {
  13         15  
  13         14  
  13         16  
  13         16  
62              
63 13 50       23 throw_failure( parameter => 'q{pars} argument must be a hash' )
64             unless Ref::Util::is_hashref( $pars );
65              
66 13         26 my %pars = $pars->%*;
67              
68 13   100     33 my $capacity = delete $pars{capacity} // 2;
69 13 100 100     89 Scalar::Util::looks_like_number( $capacity ) && int( $capacity ) == $capacity && $capacity > 0
      100        
70             or throw_failure( parameter => "parameter 'capacity' ($capacity) is not a positive integer" );
71              
72 9         27 $class->SUPER::new( {
73             capacity => $capacity,
74             depends => [ to_iterator( $iterable ) ],
75             },
76             \%pars,
77             );
78             }
79              
80              
81              
82              
83              
84              
85              
86              
87              
88              
89 11     11 0 12 sub construct ( $class, $state ) {
  11         13  
  11         12  
  11         29  
90              
91 11 50       17 throw_failure( parameter => q{state must be a HASH reference} )
92             unless Ref::Util::is_hashref( $state );
93              
94 11         14 my ( $src, $capacity, $idx, $cache ) = @{$state}{qw[ depends capacity idx cache ]};
  11         26  
95 11         19 $src = $src->[0];
96 11   100     31 $idx //= -1;
97 11   100     29 $cache //= [];
98              
99 11         39 my $self;
100 11         45 my $is_exhausted = $src->can( 'is_exhausted' );
101 11         14 my $iterator_state;
102              
103             return {
104              
105             ( +_SELF ) => \$self,
106              
107             ( +STATE ) => \$iterator_state,
108              
109             ( +RESET ) => sub {
110 2     2   3 $idx = -1;
111 2         2 @{$cache} = ();
  2         3  
112             },
113              
114       2     ( +REWIND ) => sub {
115             },
116              
117             ( +PREV ) => sub {
118 34 50   34   99 return defined $idx ? $cache->[ ( $idx - 1 ) % $capacity ] : undef;
119             },
120              
121             ( +CURRENT ) => sub {
122 34 50   34   100 return defined $idx ? $cache->[ $idx % $capacity ] : undef;
123             },
124              
125             ( +NEXT ) => sub {
126              
127 95 100   95   212 return $self->signal_exhaustion
128             if $iterator_state == IterState_EXHAUSTED;
129              
130 83         121 $idx = ++$idx % $capacity;
131 83         177 my $current = $cache->[$idx] = $src->();
132              
133 83 100       156 return $self->signal_exhaustion
134             if $src->$is_exhausted;
135              
136 72         166 return $current;
137             },
138              
139 110         149 ( +METHODS ) => {
140 110     110   152 at => sub ( $, $at ) {
  110         141  
141 110         392 $cache->[ ( $idx - $at ) % $capacity ];
142             },
143             },
144              
145             ( +FREEZE ) => sub {
146 2     2   11 return [ $class, { idx => $idx, capacity => $capacity, cache => $cache } ];
147             },
148              
149 11         171 ( +_DEPENDS ) => $src,
150             };
151             }
152              
153              
154              
155             __PACKAGE__->_add_roles( qw[
156             State::Closure
157             Next::ClosedSelf
158             Rewind::Closure
159             Reset::Closure
160             Prev::Closure
161             Current::Closure
162             Freeze
163             ] );
164              
165              
166             1;
167              
168             #
169             # This file is part of Iterator-Flex
170             #
171             # This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
172             #
173             # This is free software, licensed under:
174             #
175             # The GNU General Public License, Version 3, June 2007
176             #
177              
178             __END__