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   173321 use v5.28;
  15         40  
6 15     15   55 use strict;
  15         21  
  15         246  
7 15     15   45 use warnings;
  15         19  
  15         793  
8              
9             our $VERSION = '0.34';
10              
11 15     15   426 use Iterator::Flex::Utils qw( :default INPUT_EXHAUSTION );
  15         22  
  15         1663  
12 15     15   69 use Scalar::Util;
  15         30  
  15         711  
13 15     15   451 use Role::Tiny;
  15         4447  
  15         63  
14 15     15   2826 use experimental 'signatures';
  15         17  
  15         74  
15              
16 15     15   2103 use namespace::clean;
  15         11127  
  15         81  
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__