File Coverage

blib/lib/ArrayDataRole/Source/Iterator.pm
Criterion Covered Total %
statement 45 48 93.7
branch 23 28 82.1
condition 1 2 50.0
subroutine 9 10 90.0
pod 0 6 0.0
total 78 94 82.9


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