File Coverage

blib/lib/Net/CLI/Interact/Role/Iterator.pm
Criterion Covered Total %
statement 9 40 22.5
branch 0 12 0.0
condition 0 3 0.0
subroutine 3 14 21.4
pod 11 11 100.0
total 23 80 28.7


line stmt bran cond sub pod time code
1             package Net::CLI::Interact::Role::Iterator;
2             { $Net::CLI::Interact::Role::Iterator::VERSION = '2.400000' }
3              
4 1     1   5332 use Moo::Role;
  1         4  
  1         8  
5 1     1   410 use Sub::Quote;
  1         3  
  1         101  
6 1     1   11 use MooX::Types::MooseLike::Base qw(ArrayRef Any Int);
  1         10  
  1         757  
7              
8             has '_sequence' => (
9             is => 'rw',
10             isa => ArrayRef[Any],
11             required => 1,
12             );
13              
14             # fiddly only in case of auto_deref
15 0     0 1   sub count { return scalar @{ (shift)->_sequence } }
  0            
16              
17 0     0 1   sub first { return (shift)->_sequence->[0] }
18 0     0 1   sub last { return (shift)->_sequence->[-1] }
19              
20             sub item_at {
21 0     0 1   my ($self, $pos) = @_;
22 0 0         die "position is past the end of sequence\n"
23             if $pos >= $self->count;
24 0           return $self->_sequence->[$pos];
25             }
26              
27             sub insert_at {
28 0     0 1   my ($self, $pos, @rest) = @_;
29 0           my @seq = @{ $self->_sequence };
  0            
30 0           splice @seq, $pos, 0, @rest;
31 0           $self->_sequence( \@seq );
32             }
33              
34             sub append {
35 0     0 1   my $self = shift;
36 0           $self->insert_at( $self->count, @{ (shift)->_sequence } );
  0            
37             }
38              
39             has '_position' => (
40             is => 'rw',
41             isa => Int,
42             default => quote_sub('-1'),
43             );
44              
45             sub idx {
46 0     0 1   my $self = shift;
47 0           my $pos = $self->_position;
48 0 0 0       die "attempt to read iter index before pulling a value\n"
49             if scalar @_ == 0 and $pos == -1;
50 0 0         $self->_position(shift) if scalar @_;
51 0           return $pos;
52             }
53              
54             sub next {
55 0     0 1   my $self = shift;
56 0 0         die "er, please check has_next before next\n"
57             if not $self->has_next;
58              
59 0           my $position = $self->_position;
60 0 0         die "fell off end of iterator\n"
61             if ++$position == $self->count;
62              
63 0           $self->_position($position);
64 0           return $self->_sequence->[ $position ];
65             }
66              
67             sub has_next {
68 0     0 1   my $self = shift;
69 0           return ($self->_position < ($self->count - 1));
70             }
71              
72             sub peek {
73 0     0 1   my $self = shift;
74 0 0         return $self->_sequence->[ $self->_position + 1 ]
75             if $self->has_next;
76             }
77              
78 0     0 1   sub reset { (shift)->_position(-1) }
79              
80             1;
81              
82             =pod
83              
84             =head1 NAME
85              
86             Net::CLI::Interact::Role::Iterator - Array-based Iterator
87              
88             =head1 SYNOPSIS
89              
90             my $count = $iter->count;
91            
92             $iter->reset;
93             while ( $iter->has_next ) {
94             print $iter->next;
95             }
96              
97             =head1 DESCRIPTION
98              
99             This module implements an array-based iterator which may be mixed-in to add
100             management of a sequence of elements and processing of that sequence.
101              
102             The iterator is inspired by L<MooseX::Iterator> but limited to arrays and adds
103             many other facilities. The following section describes the methods provided by
104             this class.
105              
106             =head1 USAGE
107              
108             The slot used for storing iterator elements is named C<_sequence> and you
109             should write your consuming class to marshall data into this slot, perhaps via
110             C<BUILD> or C<init_arg>. For example:
111              
112             has '+_sequence' => (
113             isa => 'ArrayRef[Thingy]',
114             init_arg => 'things',
115             );
116              
117             =head1 INTERFACE
118              
119             =head2 count
120              
121             The number of elements currently stored in the iterator. Note that this is of
122             course not the same as the index of the last item in the iterator (which is
123             0-based)
124              
125             =head2 first
126              
127             Returns the first item in the iterator.
128              
129             =head2 last
130              
131             Returns the last item in the iterator.
132              
133             =head2 item_at( $pos )
134              
135             Returns the item at the given position in the iterator, or throws an exception
136             if C<$pos> is past the end of the iterator. The position is 0-based.
137              
138             =head2 insert_at( $pos, $iter )
139              
140             Inserts the contents of the passed iterator starting I<at> (not I<after>) the
141             position given. The passed iterator must also be a consumer of this role. The
142             position is 0-based.
143              
144             =head2 append( $iter )
145              
146             Shorthand for C<insert_at> when you want to add the contents of the passed
147             iterator I<after> the end of the sequence.
148              
149             =head2 idx( $pos? )
150              
151             Returns the index (0-based) of the current iterator cursor, or sets the
152             cursor if a position (again, 0-based) is passed.
153              
154             An exception is thrown if you attempt to read the cursor position before
155             having read any elements from the iterator, or if the iterator is empty.
156              
157             =head2 next
158              
159             Returns the next item in the iterator sequence, and advances the cursor.
160             Throws an exception if you have already reached the end of the sequence.
161              
162             =head2 has_next
163              
164             Returns true if there are further elements to be read from the iterator.
165              
166             =head2 peek
167              
168             Returns the next item in the sequence without advancing the position of the
169             cursor. It returns C<undef> if you are already at the end of the sequence.
170              
171             =head2 reset
172              
173             Resets the cursor so you can iterate through the sequence of elements again.
174              
175             =cut
176