File Coverage

blib/lib/Iterator/Flex/Utils.pm
Criterion Covered Total %
statement 156 162 96.3
branch 21 30 70.0
condition 0 3 0.0
subroutine 38 38 100.0
pod 5 8 62.5
total 220 241 91.2


line stmt bran cond sub pod time code
1             package Iterator::Flex::Utils;
2              
3             # ABSTRACT: Internal utilities
4              
5 70     70   483236 use v5.28;
  70         314  
6 70     70   491 use strict;
  70         128  
  70         1957  
7 70     70   312 use warnings;
  70         1160  
  70         3901  
8              
9 70     70   11179 use experimental 'signatures', 'postderef';
  70         45664  
  70         482  
10              
11             our $VERSION = '0.33';
12              
13 70     70   16800 use Scalar::Util qw( refaddr );
  70         196  
  70         4741  
14 70     70   13443 use Ref::Util qw( is_hashref );
  70         66580  
  70         5494  
15 70     70   616 use Exporter 'import';
  70         180  
  70         2581  
16 70     70   440 use experimental 'declared_refs';
  70         155  
  70         442  
17 70     70   24661 use Module::Runtime;
  70         55012  
  70         463  
18              
19             our %REGISTRY;
20              
21             sub mk_indices {
22 420     420 0 806 my $idx = 0;
23 420         787 return { map { $_ => $idx++ } @_ };
  4410         176839  
24             }
25              
26             sub mk_lc {
27 350     350 0 822 return { map { $_ => lc $_ } @_ };
  2310         83033  
28             }
29              
30 70         7689 use constant ITER_ATTRS => qw(
31             CLASS CURRENT FREEZE METHODS NEXT PREV RESET REWIND STATE _DEPENDS _NAME _ROLES _SELF
32 70     70   18284 );
  70         149  
33 70     70   461 use constant mk_lc ITER_ATTRS;
  70         134  
  70         423  
34 70     70   538 use constant REGISTRY_ITERATION_INDICES => map { 'REG_ITER_' . $_ } ITER_ATTRS, 'MAY_METHOD';
  70         188  
  70         234  
  980         12211  
35 70     70   541 use constant mk_indices REGISTRY_ITERATION_INDICES;
  70         168  
  70         401  
36             our \%RegIterationIndexMap = mk_indices map { lc } ITER_ATTRS;
37              
38 70     70   546 use constant EXHAUSTED_METHODS => qw( IS_EXHAUSTED SET_EXHAUSTED );
  70         151  
  70         6403  
39 70     70   409 use constant mk_lc EXHAUSTED_METHODS;
  70         2025  
  70         3602  
40              
41 70     70   1210 use constant ITER_STATES => qw( IterState_CLEAR IterState_EXHAUSTED IterState_ERROR );
  70         151  
  70         8557  
42 70     70   482 use constant mk_indices ITER_STATES;
  70         133  
  70         3214  
43              
44 70     70   425 use constant REGISTRY_INDICES => qw( REG_ITERATOR REG_GENERAL REG_METHODS );
  70         162  
  70         5698  
45 70     70   418 use constant mk_indices REGISTRY_INDICES;
  70         354  
  70         327  
46              
47 70     70   506 use constant EXHAUSTION_ACTIONS => qw[ THROW RETURN PASSTHROUGH ];
  70         212  
  70         4230  
48 70     70   500 use constant mk_lc EXHAUSTION_ACTIONS;
  70         144  
  70         666  
49              
50             # these duplicate ITER_ATTRS. combine?
51 70         7588 use constant INTERFACE_PARAMETERS =>
52 70     70   441 qw( CURRENT FREEZE METHODS NEXT PREV RESET REWIND STATE _DEPENDS _NAME _ROLES _SELF );
  70         144  
53 70     70   462 use constant INTERFACE_PARAMETER_VALUES => map { lc $_ } INTERFACE_PARAMETERS;
  70         1203  
  70         191  
  840         7838  
54 70     70   422 use constant mk_lc INTERFACE_PARAMETERS;
  70         163  
  70         378  
55              
56              
57 70     70   584 use constant SIGNAL_PARAMETERS => qw( INPUT_EXHAUSTION EXHAUSTION ERROR );
  70         127  
  70         7333  
58 70     70   432 use constant SIGNAL_PARAMETER_VALUES => map { lc $_ } SIGNAL_PARAMETERS;
  70         146  
  70         207  
  210         5172  
59 70     70   489 use constant mk_lc SIGNAL_PARAMETERS;
  70         136  
  70         306  
60              
61 70     70   412 use constant GENERAL_PARAMETERS => ( INTERFACE_PARAMETERS, SIGNAL_PARAMETERS );
  70         193  
  70         8553  
62 70     70   444 use constant REGISTRY_GENPAR_INDICES => map { 'REG_GP_' . $_ } GENERAL_PARAMETERS;
  70         127  
  70         184  
  1050         7076  
63 70     70   397 use constant mk_indices REGISTRY_GENPAR_INDICES;
  70         109  
  70         572  
64              
65             our \%RegGeneralParameterIndexMap = mk_indices map { lc } GENERAL_PARAMETERS;
66              
67             our %EXPORT_TAGS = (
68             ExhaustionActions => [EXHAUSTION_ACTIONS],
69             ExhaustedMethods => [EXHAUSTED_METHODS],
70             RegistryIndices => [
71             REGISTRY_INDICES, REGISTRY_ITERATION_INDICES,
72             '%RegIterationIndexMap', REGISTRY_GENPAR_INDICES,
73             '%RegGeneralParameterIndexMap',
74             ],
75             IterAttrs => [ITER_ATTRS],
76             IterStates => [ITER_STATES],
77             SignalParameters => [ SIGNAL_PARAMETERS, 'SIGNAL_PARAMETER_VALUES' ],
78             InterfaceParameters => [ INTERFACE_PARAMETERS, 'INTERFACE_PARAMETER_VALUES' ],
79             GeneralParameters => [ GENERAL_PARAMETERS, ],
80             Functions => [ qw(
81             throw_failure
82             parse_pars
83             can_meth
84             resolve_meth
85             load_role
86             ),
87             ],
88             default => [qw( %REGISTRY refaddr )],
89             );
90              
91             $EXPORT_TAGS{':all'} = [ map { $_->@* } values %EXPORT_TAGS ];
92              
93             ## no critic ( AutomaticExportation )
94             our @EXPORT = @{ $EXPORT_TAGS{default} }; # ??? is this needed?
95              
96             our @EXPORT_OK = ( map { $_->@* } values %EXPORT_TAGS, );
97              
98              
99 10     10 0 10032 sub throw_failure ( $failure, $msg ) {
  10         21  
  10         21  
  10         25  
100 10         2687 require Iterator::Flex::Failure;
101 10         58 local @Iterator::Flex::Role::Utils::CARP_NOT = scalar caller;
102 10         70 my $type = join( q{::}, 'Iterator::Flex::Failure', $failure );
103 10         94 $type->throw( { msg => $msg, trace => Iterator::Flex::Failure->croak_trace } );
104             }
105              
106              
107              
108              
109              
110              
111              
112              
113              
114              
115              
116              
117              
118 200     200 1 350 sub parse_pars ( @args ) {
  200         391  
  200         312  
119              
120 200         346 my %pars = do {
121              
122 200 50       560 if ( @args == 1 ) {
123 200 50       599 is_hashref( $args[0] )
124             or throw_failure( parameter => 'expected a hashref' );
125 200         851 $args[0]->%*;
126             }
127              
128             else {
129 0 0       0 @args % 2
130             and throw_failure( parameter => 'expected an even number of arguments for hash' );
131 0         0 @args;
132             }
133             };
134              
135 200         1952 my %ipars = delete %pars{ grep exists $pars{$_}, INTERFACE_PARAMETER_VALUES };
136 200         1209 my %spars = delete %pars{ grep exists $pars{$_}, SIGNAL_PARAMETER_VALUES };
137              
138 200         891 return ( \%pars, \%ipars, \%spars );
139             }
140              
141              
142              
143              
144              
145              
146              
147              
148              
149              
150              
151              
152              
153              
154              
155              
156              
157              
158              
159              
160              
161              
162              
163              
164              
165              
166              
167              
168              
169              
170              
171              
172              
173              
174 306     306 1 448570 sub can_meth ( $obj, @methods ) {
  306         459  
  306         564  
  306         427  
175              
176 306 100       726 my $par = Ref::Util::is_hashref( $methods[-1] ) ? pop @methods : {};
177              
178 306         585 for my $method ( @methods ) {
179 306 100       648 throw_failure( parameter => q{'method' parameters must be a string} )
180             if Ref::Util::is_ref( $method );
181              
182 304         466 my $sub;
183 304         704 foreach ( "__${method}__", $method ) {
184 369 100       1690 if ( defined( $sub = $obj->can( $_ ) ) ) {
185 284 100       826 my @ret = ( ( !!$par->{name} ? $_ : () ), ( !!$par->{code} ? $sub : () ) );
    100          
186 284 100       712 push @ret, $sub unless @ret;
187 284 100       1580 return @ret > 1 ? @ret : $ret[0];
188             }
189             }
190             }
191              
192 20         73 return undef;
193             }
194              
195              
196              
197              
198              
199              
200              
201              
202              
203              
204              
205              
206              
207              
208              
209              
210              
211              
212 14     14 1 16 sub resolve_meth ( $target, $method, @fallbacks ) {
  14         17  
  14         14  
  14         26  
  14         14  
213              
214 14         15 my $code = do {
215              
216 14 50       24 if ( defined $method ) {
217 0 0 0     0 Ref::Util::is_coderef( $method )
218             ? $method
219             : $target->can( $method )
220             // throw_failure( parameter => qq{method '$method' is not provided by the object} );
221             }
222              
223             else {
224 14         35 can_meth( $target, @fallbacks );
225             }
226             };
227              
228 14         30 return $code;
229             }
230              
231              
232              
233              
234              
235              
236              
237              
238              
239              
240              
241              
242              
243              
244              
245              
246 1764     1764 1 2583 sub load_module ( $path, @namespaces ) {
  1764         2633  
  1764         2764  
  1764         2526  
247              
248 1764 100       4652 if ( substr( $path, 0, 1 ) eq q{+} ) {
249 41         89 my $module = substr( $path, 1 );
250 41 50       202 return $module if eval { Module::Runtime::require_module( $module ) };
  41         95  
251 0         0 throw_failure( class => "unable to load $module" );
252             }
253             else {
254 1723         3438 for my $namespace ( @namespaces ) {
255 1723         3333 my $module = $namespace . q{::} . $path;
256 1723 50       2907 return $module if eval { Module::Runtime::require_module( $module ) };
  1723         4675  
257             }
258             }
259              
260 0         0 throw_failure(
261             class => join q{ },
262 0         0 "unable to find a module for '$path' in @{[ join( ', ', @namespaces ) ]}",
263             );
264             }
265              
266              
267              
268              
269              
270              
271              
272              
273              
274              
275              
276 1764     1764 1 2715 sub load_role ( $role, @namespaces ) {
  1764         2876  
  1764         3093  
  1764         2544  
277 1764         3679 load_module( $role, @namespaces );
278             }
279              
280              
281             1;
282              
283             #
284             # This file is part of Iterator-Flex
285             #
286             # This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
287             #
288             # This is free software, licensed under:
289             #
290             # The GNU General Public License, Version 3, June 2007
291             #
292              
293             __END__