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