File Coverage

blib/lib/Iterator/Flex/Role/Wrap/Return.pm
Criterion Covered Total %
statement 23 23 100.0
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 31 31 100.0


line stmt bran cond sub pod time code
1             package Iterator::Flex::Role::Wrap::Return;
2              
3             # ABSTRACT: wrap imported iterator which returns a sentinel on exhaustion
4              
5 15     15   237316 use v5.28;
  15         57  
6 15     15   77 use strict;
  15         32  
  15         361  
7 15     15   63 use warnings;
  15         26  
  15         4213  
8              
9             our $VERSION = '0.33';
10              
11 15     15   661 use Iterator::Flex::Utils qw( :default INPUT_EXHAUSTION );
  15         41  
  15         2169  
12 15     15   95 use Scalar::Util;
  15         31  
  15         733  
13 15     15   800 use Role::Tiny;
  15         8404  
  15         91  
14 15     15   4377 use experimental 'signatures';
  15         42  
  15         141  
15              
16 15     15   3157 use namespace::clean;
  15         19172  
  15         101  
17              
18             around _construct_next => sub ( $orig, $class, $ipar, $gpar ) {
19              
20             my $next = $class->$orig( $ipar, $gpar );
21              
22             # this will be weakened latter.
23             my $wsub;
24              
25             my $sentinel = (
26             $gpar->{ +INPUT_EXHAUSTION } // do {
27             require Iterator::Flex::Failure;
28             Iterator::Flex::Failure::parameter->throw(
29             q{internal error: input exhaustion policy was not registered} );
30             }
31             )->[1];
32              
33             # undef
34             if ( !defined $sentinel ) {
35             $wsub = sub {
36             my $self = $_[0] // $wsub;
37             my $val = $next->( $self );
38             return !defined $val ? $self->signal_exhaustion : $val;
39             };
40             }
41              
42             # reference
43             elsif ( ref $sentinel ) {
44             my $refaddr_sentinel = refaddr $sentinel;
45              
46             $wsub = sub {
47             my $self = $_[0] // $wsub;
48             my $val = $next->( $self );
49             my $addr = refaddr $val;
50             return defined $addr
51             && $addr == $refaddr_sentinel ? $self->signal_exhaustion : $val;
52             };
53             }
54              
55             # number
56             elsif ( Scalar::Util::looks_like_number( $sentinel ) ) {
57             $wsub = sub {
58             my $self = $_[0] // $wsub;
59             my $val = $next->( $self );
60             return defined $val
61             && $val == $sentinel ? $self->signal_exhaustion : $val;
62             };
63             }
64              
65             # string
66             else {
67             $wsub = sub {
68             my $self = $_[0] // $wsub;
69             my $val = $next->( $_[0] );
70             return defined $val
71             && $val eq $sentinel ? $self->signal_exhaustion : $val;
72             };
73             }
74              
75             # create a second reference to $wsub, before we weaken it,
76             # otherwise it will lose its contents, as it would be the only
77             # reference.
78              
79             my $sub = $wsub;
80             Scalar::Util::weaken( $wsub );
81             return $sub;
82             };
83              
84             requires 'signal_exhaustion';
85              
86             1;
87              
88             #
89             # This file is part of Iterator-Flex
90             #
91             # This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
92             #
93             # This is free software, licensed under:
94             #
95             # The GNU General Public License, Version 3, June 2007
96             #
97              
98             __END__