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 71     71   325150 use v5.28;
  71         1287  
6 71     71   306 use strict;
  71         102  
  71         2043  
7 71     71   220 use warnings;
  71         100  
  71         2968  
8              
9 71     71   7707 use experimental 'signatures', 'postderef';
  71         25414  
  71         1105  
10              
11             our $VERSION = '0.34';
12              
13 71     71   10819 use Scalar::Util qw( refaddr );
  71         125  
  71         3353  
14 71     71   10854 use Ref::Util qw( is_hashref );
  71         47734  
  71         3935  
15 71     71   411 use Exporter 'import';
  71         158  
  71         1973  
16 71     71   263 use experimental 'declared_refs';
  71         131  
  71         245  
17 71     71   17884 use Module::Runtime;
  71         39976  
  71         365  
18              
19             our %REGISTRY;
20              
21             sub mk_indices {
22 426     426 0 582 my $idx = 0;
23 426         634 return { map { $_ => $idx++ } @_ };
  4473         123373  
24             }
25              
26             sub mk_lc {
27 355     355 0 633 return { map { $_ => lc $_ } @_ };
  2343         58300  
28             }
29              
30 71         5719 use constant ITER_ATTRS => qw(
31             CLASS CURRENT FREEZE METHODS NEXT PREV RESET REWIND STATE _DEPENDS _NAME _ROLES _SELF
32 71     71   13118 );
  71         106  
33 71     71   328 use constant mk_lc ITER_ATTRS;
  71         103  
  71         324  
34 71     71   379 use constant REGISTRY_ITERATION_INDICES => map { 'REG_ITER_' . $_ } ITER_ATTRS, 'MAY_METHOD';
  71         118  
  71         206  
  994         5430  
35 71     71   338 use constant mk_indices REGISTRY_ITERATION_INDICES;
  71         102  
  71         276  
36             our \%RegIterationIndexMap = mk_indices map { lc } ITER_ATTRS;
37              
38 71     71   334 use constant EXHAUSTED_METHODS => qw( IS_EXHAUSTED SET_EXHAUSTED );
  71         101  
  71         5588  
39 71     71   304 use constant mk_lc EXHAUSTED_METHODS;
  71         846  
  71         243  
40              
41 71     71   315 use constant ITER_STATES => qw( IterState_CLEAR IterState_EXHAUSTED IterState_ERROR );
  71         108  
  71         5434  
42 71     71   1078 use constant mk_indices ITER_STATES;
  71         874  
  71         2283  
43              
44 71     71   980 use constant REGISTRY_INDICES => qw( REG_ITERATOR REG_GENERAL REG_METHODS );
  71         100  
  71         3340  
45 71     71   976 use constant mk_indices REGISTRY_INDICES;
  71         238  
  71         249  
46              
47 71     71   359 use constant EXHAUSTION_ACTIONS => qw[ THROW RETURN PASSTHROUGH ];
  71         201  
  71         2903  
48 71     71   283 use constant mk_lc EXHAUSTION_ACTIONS;
  71         89  
  71         184  
49              
50             # these duplicate ITER_ATTRS. combine?
51 71         5196 use constant INTERFACE_PARAMETERS =>
52 71     71   306 qw( CURRENT FREEZE METHODS NEXT PREV RESET REWIND STATE _DEPENDS _NAME _ROLES _SELF );
  71         97  
53 71     71   961 use constant INTERFACE_PARAMETER_VALUES => map { lc $_ } INTERFACE_PARAMETERS;
  71         108  
  71         143  
  852         4751  
54 71     71   296 use constant mk_lc INTERFACE_PARAMETERS;
  71         109  
  71         280  
55              
56              
57 71     71   346 use constant SIGNAL_PARAMETERS => qw( INPUT_EXHAUSTION EXHAUSTION ERROR );
  71         98  
  71         5019  
58 71     71   307 use constant SIGNAL_PARAMETER_VALUES => map { lc $_ } SIGNAL_PARAMETERS;
  71         90  
  71         140  
  213         3706  
59 71     71   292 use constant mk_lc SIGNAL_PARAMETERS;
  71         102  
  71         251  
60              
61 71     71   265 use constant GENERAL_PARAMETERS => ( INTERFACE_PARAMETERS, SIGNAL_PARAMETERS );
  71         133  
  71         5924  
62 71     71   324 use constant REGISTRY_GENPAR_INDICES => map { 'REG_GP_' . $_ } GENERAL_PARAMETERS;
  71         95  
  71         144  
  1065         5035  
63 71     71   280 use constant mk_indices REGISTRY_GENPAR_INDICES;
  71         128  
  71         392  
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 26     26 0 5257 sub throw_failure ( $failure, $msg ) {
  26         35  
  26         30  
  26         30  
100 26         3317 require Iterator::Flex::Failure;
101 26         90 local @Iterator::Flex::Role::Utils::CARP_NOT = scalar caller;
102 26         89 my $type = join( q{::}, 'Iterator::Flex::Failure', $failure );
103 26         110 $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 208     208 1 262 sub parse_pars ( @args ) {
  208         276  
  208         220  
119              
120 208         241 my %pars = do {
121              
122 208 50       367 if ( @args == 1 ) {
123 208 50       487 is_hashref( $args[0] )
124             or throw_failure( parameter => 'expected a hashref' );
125 208         613 $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 208         1354 my %ipars = delete %pars{ grep exists $pars{$_}, INTERFACE_PARAMETER_VALUES };
136 208         872 my %spars = delete %pars{ grep exists $pars{$_}, SIGNAL_PARAMETER_VALUES };
137              
138 208         614 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 318     318 1 231088 sub can_meth ( $obj, @methods ) {
  318         344  
  318         395  
  318         298  
175              
176 318 100       440 my $par = Ref::Util::is_hashref( $methods[-1] ) ? pop @methods : {};
177              
178 318         424 for my $method ( @methods ) {
179 318 100       450 throw_failure( parameter => q{'method' parameters must be a string} )
180             if Ref::Util::is_ref( $method );
181              
182 316         328 my $sub;
183 316         469 foreach ( "__${method}__", $method ) {
184 383 100       1071 if ( defined( $sub = $obj->can( $_ ) ) ) {
185 296 100       524 my @ret = ( ( !!$par->{name} ? $_ : () ), ( !!$par->{code} ? $sub : () ) );
    100          
186 296 100       414 push @ret, $sub unless @ret;
187 296 100       846 return @ret > 1 ? @ret : $ret[0];
188             }
189             }
190             }
191              
192 20         52 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         13  
  14         15  
  14         16  
  14         15  
213              
214 14         14 my $code = do {
215              
216 14 50       20 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         19 can_meth( $target, @fallbacks );
225             }
226             };
227              
228 14         20 return $code;
229             }
230              
231              
232              
233              
234              
235              
236              
237              
238              
239              
240              
241              
242              
243              
244              
245              
246 1824     1824 1 1840 sub load_module ( $path, @namespaces ) {
  1824         1922  
  1824         1995  
  1824         1796  
247              
248 1824 100       3246 if ( substr( $path, 0, 1 ) eq q{+} ) {
249 41         161 my $module = substr( $path, 1 );
250 41 50       55 return $module if eval { Module::Runtime::require_module( $module ) };
  41         89  
251 0         0 throw_failure( class => "unable to load $module" );
252             }
253             else {
254 1783         2358 for my $namespace ( @namespaces ) {
255 1783         2479 my $module = $namespace . q{::} . $path;
256 1783 50       1886 return $module if eval { Module::Runtime::require_module( $module ) };
  1783         3246  
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 1824     1824 1 2032 sub load_role ( $role, @namespaces ) {
  1824         2006  
  1824         2206  
  1824         1749  
277 1824         2527 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__