File Coverage

blib/lib/ArrayDataRole/Source/Iterator.pm
Criterion Covered Total %
statement 48 51 94.1
branch 23 28 82.1
condition 1 2 50.0
subroutine 10 11 90.9
pod 0 6 0.0
total 82 98 83.6


line stmt bran cond sub pod time code
1             package ArrayDataRole::Source::Iterator;
2              
3 1     1   671 use strict;
  1         3  
  1         31  
4 1     1   28 use 5.010001;
  1         4  
5 1     1   6 use Role::Tiny;
  1         2  
  1         7  
6 1     1   191 use Role::Tiny::With;
  1         2  
  1         635  
7             with 'ArrayDataRole::Spec::Basic';
8              
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2021-12-01'; # DATE
11             our $DIST = 'ArrayDataRoles-Standard'; # DIST
12             our $VERSION = '0.007'; # VERSION
13              
14             sub _new {
15 1     1   6 my ($class, %args) = @_;
16              
17 1 50       4 my $gen_iterator = delete $args{gen_iterator} or die "Please specify 'gen_iterator' argument";
18 1   50     7 my $gen_iterator_params = delete $args{gen_iterator_params} // {};
19              
20 1 50       6 die "Unknown argument(s): ". join(", ", sort keys %args)
21             if keys %args;
22              
23 1         7 bless {
24             gen_iterator => $gen_iterator,
25             gen_iterator_params => $gen_iterator_params,
26             iterator => undef,
27             pos => 0,
28             # buf => '', # exists when there is a buffer
29             }, $class;
30             }
31              
32             sub get_next_item {
33 14     14 0 80 my $self = shift;
34 14 50       32 $self->reset_iterator unless $self->{iterator};
35 14 100       28 if (exists $self->{buf}) {
36 9         14 $self->{pos}++;
37 9         18 return delete $self->{buf};
38             } else {
39 5         14 my $elem = $self->{iterator}->();
40 5 100       24 die "StopIteration" unless defined $elem;
41 4         6 $self->{pos}++;
42 4         23 return $elem;
43             }
44             }
45              
46             sub has_next_item {
47 12     12 0 31 my $self = shift;
48 12 50       28 if (exists $self->{buf}) {
49 0         0 return 1;
50             }
51 12 50       26 $self->reset_iterator unless $self->{iterator};
52 12         26 my $elem = $self->{iterator}->();
53 12 100       43 return 0 unless defined $elem;
54 9         14 $self->{buf} = $elem;
55 9         20 1;
56             }
57              
58             sub reset_iterator {
59 5     5 0 21 my $self = shift;
60 5         10 $self->{iterator} = $self->{gen_iterator}->(%{ $self->{gen_iterator_params} });
  5         23  
61 5         12 $self->{pos} = 0;
62             }
63              
64             sub get_iterator_pos {
65 0     0 0 0 my $self = shift;
66 0         0 $self->{pos};
67             }
68              
69             sub get_item_at_pos {
70 3     3 0 52 my ($self, $pos) = @_;
71 3 100       14 $self->reset_iterator if $self->{pos} > $pos;
72 3         6 while (1) {
73 5 100       11 die "Out of range" unless $self->has_next_item;
74 4         8 my $item = $self->get_next_item;
75 4 100       16 return $item if $self->{pos} > $pos;
76             }
77             }
78              
79             sub has_item_at_pos {
80 3     3 0 549 my ($self, $pos) = @_;
81 3 100       15 return 1 if $self->{pos} > $pos;
82 2         4 while (1) {
83 3 100       9 return 0 unless $self->has_next_item;
84 2         6 $self->get_next_item;
85 2 100       9 return 1 if $self->{pos} > $pos;
86             }
87             }
88              
89             1;
90             # ABSTRACT: Get array data from an iterator
91              
92             __END__