Iterator-Flex

 view release on metacpan or  search on metacpan

lib/Iterator/Flex/ArrayLike.pm  view on Meta::CPAN

package Iterator::Flex::ArrayLike;

# ABSTRACT: ArrayLike Iterator Class

use v5.28;
use strict;
use warnings;
use experimental 'signatures';

our $VERSION = '0.33';

use Ref::Util;
use Iterator::Flex::Utils ':IterAttrs', 'resolve_meth';
use namespace::clean;

use parent 'Iterator::Flex::Base';



























































sub new ( $class, $obj, $pars = {} ) {

    $class->_croak( parameter => q{argument must be a blessed reference} )
      unless Ref::Util::is_blessed_ref( $obj );

    $class->SUPER::new( { object => $obj }, $pars );
}

sub construct ( $class, $state ) {

    throw_failure( parameter => q{state must be a HASH reference} )
      unless Ref::Util::is_hashref( $state );

    my ( $obj, $prev, $current, $next, $length, $at )
      = @{$state}{qw[ object prev current next length at ]};

    throw_failure( parameter => q{state 'object' argument must be a blessed reference} )
      unless Ref::Util::is_blessed_ref( $obj );

    $length = resolve_meth( $obj, $length, 'length', 'len' );

    $at = resolve_meth( $obj, $at, 'at', 'getitem' );

    my $len = $obj->$length;

    $next = 0 unless defined $next;

    throw_failure( parameter => q{illegal value for state 'prev' argument} )
      if defined $prev && ( $prev < 0 || $prev >= $len );

    throw_failure( parameter => q{illegal value for state 'current' argument} )
      if defined $current && ( $current < 0 || $current >= $len );

    throw_failure( parameter => q{illegal value for state 'next' argument} )
      if $next < 0 || $next > $len;

    my $self;

    return {

        ( +_SELF ) => \$self,

        ( +RESET ) => sub {
            $prev = $current = undef;
            $next = 0;
        },

        ( +REWIND ) => sub {
            $next = 0;
        },

        ( +PREV ) => sub {
            return defined $prev ? $obj->$at( $prev ) : undef;
        },

        ( +CURRENT ) => sub {
            return defined $current ? $obj->$at( $current ) : undef;
        },

        ( +NEXT ) => sub {
            if ( $next == $len ) {
                # if first time through, set current
                $prev = $current
                  if !$self->is_exhausted;
                return $current = $self->signal_exhaustion;
            }
            $prev    = $current;
            $current = $next++;

            return $obj->$at( $current );
        },
    };
}


__PACKAGE__->_add_roles( qw[
      State::Registry
      Next::ClosedSelf



( run in 0.993 second using v1.01-cache-2.11-cpan-39bf76dae61 )