File Coverage

blib/lib/Iterator/Flex/Role/Wrap/Throw.pm
Criterion Covered Total %
statement 26 26 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 35 35 100.0


line stmt bran cond sub pod time code
1             package Iterator::Flex::Role::Wrap::Throw;
2              
3             # ABSTRACT: Role to add throw on exhaustion to an iterator which adapts another iterator
4              
5 4     4   268096 use v5.28;
  4         13  
6 4     4   15 use strict;
  4         7  
  4         80  
7 4     4   12 use warnings;
  4         5  
  4         273  
8              
9             our $VERSION = '0.33';
10              
11 4     4   17 use List::Util 'first';
  4         9  
  4         315  
12 4     4   368 use Iterator::Flex::Utils qw( INPUT_EXHAUSTION PASSTHROUGH );
  4         13  
  4         292  
13 4     4   17 use Ref::Util qw( is_ref is_blessed_ref is_regexpref is_arrayref is_coderef );
  4         13  
  4         243  
14 4     4   489 use Role::Tiny;
  4         7620  
  4         22  
15 4     4   1226 use experimental 'signatures';
  4         8  
  4         26  
16              
17 4     4   1258 use namespace::clean;
  4         17821  
  4         53  
18              
19             around _construct_next => sub ( $orig, $class, $ipar, $gpar ) {
20              
21             my $next = $class->$orig( $ipar, $gpar );
22              
23             my $exception = (
24             $gpar->{ +INPUT_EXHAUSTION } // do {
25             require Iterator::Flex::Failure;
26             Iterator::Flex::Failure::parameter->throw(
27             q{internal error: input exhaustion policy was not registered} );
28             }
29             )->[1];
30              
31             my $wsub;
32              
33             ## no critic ( CascadingIfElse )
34             if ( !defined $exception ) {
35              
36             $wsub = sub {
37             my $self = $_[0] // $wsub;
38             my $val = eval { $next->( $self ) };
39             return $@ ne q{} ? $self->signal_exhaustion( $@ ) : $val;
40             };
41             }
42              
43             elsif ( !is_ref( $exception ) && $exception eq PASSTHROUGH ) {
44              
45             $wsub = sub {
46             my $self = $_[0] // $wsub;
47             my $val = eval { $next->( $self ) };
48             return $@ ne q{} ? $self->signal_exhaustion( $@ ) : $val;
49             };
50             }
51              
52             elsif ( !is_ref( $exception ) || is_arrayref( $exception ) ) {
53             $exception = [$exception]
54             unless is_arrayref( $exception );
55              
56             $wsub = sub {
57             my $self = $_[0] // $wsub;
58             my $val = eval { $next->( $self ) };
59             if ( $@ ne q{} ) {
60             my $e = $@;
61             return $self->signal_exhaustion( $e )
62             if is_blessed_ref( $e ) && first { $e->isa( $_ ) } @$exception;
63             die $e;
64             }
65             return $val;
66             };
67             }
68              
69             elsif ( is_regexpref( $exception ) ) {
70              
71             $wsub = sub {
72             my $self = $_[0] // $wsub;
73             my $val = eval { $next->( $self ) };
74             if ( $@ ne q{} ) {
75             my $e = $@;
76             return $self->signal_exhaustion( $e ) if $e =~ $exception;
77             die $e;
78             }
79             return $val;
80             };
81             }
82              
83             elsif ( is_coderef( $exception ) ) {
84              
85             $wsub = sub {
86             my $self = $_[0] // $wsub;
87             my $val = eval { $next->( $self ) };
88             if ( $@ ne q{} ) {
89             my $e = $@;
90             return $self->signal_exhaustion( $e ) if $exception->( $e );
91             die $e;
92             }
93             return $val;
94             };
95             }
96              
97             else {
98             require Iterator::Flex::Failure;
99             require Scalar::Util;
100             Iterator::Flex::Failure::parameter->throw(
101             "internal error: unknown type for input exhaustion policy: ${ \Scalar::Util::reftype( $exception ) }",
102             );
103              
104             }
105              
106              
107             # create a second reference to $wsub, before we weaken it,
108             # otherwise it will lose its contents, as it would be the only
109             # reference.
110              
111             my $sub = $wsub;
112             Scalar::Util::weaken( $wsub );
113             return $sub;
114             };
115              
116             requires 'signal_exhaustion';
117              
118             1;
119              
120             #
121             # This file is part of Iterator-Flex
122             #
123             # This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
124             #
125             # This is free software, licensed under:
126             #
127             # The GNU General Public License, Version 3, June 2007
128             #
129              
130             __END__