Iterator-Flex
view release on metacpan or search on metacpan
lib/Iterator/Flex/Flatten.pm view on Meta::CPAN
package Iterator::Flex::Flatten;
# ABSTRACT: Flatten Iterator Class
use v5.28;
use strict;
use warnings;
use experimental 'signatures';
our $VERSION = '0.34';
use Iterator::Flex::Utils qw( STATE RETURN EXHAUSTION :IterAttrs :IterStates throw_failure);
use Iterator::Flex::Factory 'construct_from_iterable', 'to_iterator';
use Ref::Util 'is_plain_arrayref', 'is_plain_hashref', 'is_blessed_ref';
use parent 'Iterator::Flex::Base';
use namespace::clean;
sub new ( $class, $iterable, $pars = {} ) {
$class->SUPER::new( { src => $iterable }, $pars );
}
## no critic( ExcessComplexity )
sub construct ( $class, $state ) {
throw_failure( parameter => q{'state' parameter must be a HASH reference} )
unless Ref::Util::is_hashref( $state );
my ( $prev, $current, $idx, $iter )
= @{$state}{qw[ prev current idx iter src ]};
my $src = @{$state}{qw[ code src ]};
$src = to_iterator( $src );
my $self;
my $iterator_state;
my $is_exhausted = $src->can( 'is_exhausted' );
my $iter_is_exhausted = is_blessed_ref( $iter )
&& $iter->can( 'is_exhausted' );
my $rewind = !!0;
my $reset = !!0;
return {
( +_NAME ) => 'iflatten',
( +_SELF ) => \$self,
( +STATE ) => \$iterator_state,
( +PREV ) => sub {
return $prev;
},
( +CURRENT ) => sub {
return $current;
},
( +NEXT ) => sub {
return $self->signal_exhaustion if $iterator_state == IterState_EXHAUSTED;
my $value;
LOOP:
while ( 1 ) {
if ( !defined $iter ) {
$value = $src->();
if ( !defined $value && $src->$is_exhausted ) {
$prev = $current;
$current = undef;
return $self->signal_exhaustion;
}
# most likely
last LOOP
if !ref $value || is_plain_hashref( $value );
# handle arrays directly; could use an iterator, but this is
# faster
if ( is_plain_arrayref( $value ) ) {
$iter = $value;
$idx = 0;
}
( run in 0.806 second using v1.01-cache-2.11-cpan-99c4e6809bf )