File Coverage

blib/lib/Perinci/Sub/GetArgs/Array.pm
Criterion Covered Total %
statement 38 39 97.4
branch 14 18 77.7
condition 8 10 80.0
subroutine 5 5 100.0
pod 1 1 100.0
total 66 73 90.4


line stmt bran cond sub pod time code
1             package Perinci::Sub::GetArgs::Array;
2              
3             our $DATE = '2016-12-10'; # DATE
4             our $VERSION = '0.16'; # VERSION
5              
6 1     1   49949 use 5.010001;
  1         3  
7 1     1   3 use strict;
  1         2  
  1         16  
8 1     1   3 use warnings;
  1         1  
  1         20  
9             #use Log::Any '$log';
10              
11 1     1   3 use Exporter;
  1         1  
  1         439  
12             our @ISA = qw(Exporter);
13             our @EXPORT_OK = qw(get_args_from_array);
14              
15             our %SPEC;
16              
17             $SPEC{':package'} = {
18             v => 1.1,
19             };
20              
21             $SPEC{get_args_from_array} = {
22             v => 1.1,
23             summary => 'Get subroutine arguments (%args) from array',
24             description => <<'_',
25              
26             Using information in metadata's `args` property (particularly the `pos` and
27             `greedy` arg type clauses), extract arguments from an array into a hash
28             `\%args`, suitable for passing into subs.
29              
30             Example:
31              
32             my $meta = {
33             v => 1.1,
34             summary => 'Multiply 2 numbers (a & b)',
35             args => {
36             a => {schema=>'num*', pos=>0},
37             b => {schema=>'num*', pos=>1},
38             }
39             }
40              
41             then `get_args_from_array(array=>[2, 3], meta=>$meta)` will produce:
42              
43             [200, "OK", {a=>2, b=>3}]
44              
45             _
46             args => {
47             array => {
48             schema => ['array*' => {}],
49             req => 1,
50             description => <<'_',
51              
52             NOTE: array will be modified/emptied (elements will be taken from the array as
53             they are put into the resulting args). Copy your array first if you want to
54             preserve its content.
55              
56             _
57             },
58             meta => {
59             schema => ['hash*' => {}],
60             req => 1,
61             },
62             meta_is_normalized => {
63             summary => 'Can be set to 1 if your metadata is normalized, '.
64             'to avoid duplicate effort',
65             schema => 'bool',
66             default => 0,
67             },
68             allow_extra_elems => {
69             schema => ['bool' => {default=>0}],
70             summary => 'Allow extra/unassigned elements in array',
71             description => <<'_',
72              
73             If set to 1, then if there are array elements unassigned to one of the arguments
74             (due to missing `pos`, for example), instead of generating an error, the
75             function will just ignore them.
76              
77             _
78             },
79             },
80             };
81             sub get_args_from_array {
82 11     11 1 34473 my %fargs = @_;
83 11 50       30 my $ary = $fargs{array} or return [400, "Please specify array"];
84 11 50       23 my $meta = $fargs{meta} or return [400, "Please specify meta"];
85 11 50       19 unless ($fargs{meta_is_normalized}) {
86 11         487 require Perinci::Sub::Normalize;
87 11         847 $meta = Perinci::Sub::Normalize::normalize_function_metadata(
88             $meta);
89             }
90 11   100     4957 my $allow_extra_elems = $fargs{allow_extra_elems} // 0;
91              
92 11         13 my $rargs = {};
93              
94 11   50     21 my $args_p = $meta->{args} // {};
95 11         24 for my $i (reverse 0..@$ary-1) {
96             #$log->tracef("i=$i");
97 24         50 while (my ($a, $as) = each %$args_p) {
98 41         33 my $o = $as->{pos};
99 41 100 100     145 if (defined($o) && $o == $i) {
100 13 100       25 if ($as->{greedy}) {
101 5         7 my $type = $as->{schema}[0];
102 5         13 my @elems = splice(@$ary, $i);
103 5 100       12 if ($type eq 'array') {
    100          
104 2         8 $rargs->{$a} = \@elems;
105             } elsif ($type eq 'hash') {
106 2         4 $rargs->{$a} = {};
107 2         4 for my $j (0..$#elems) {
108 6         5 my $elem = $elems[$j];
109 6 50       21 unless ($elem =~ /(.*?)=(.*)/) {
110 0         0 return [400, "Invalid key=value pair in element #$j"];
111             }
112 6         13 $rargs->{$a}{$1} = $2;
113             }
114             } else {
115 1         5 $rargs->{$a} = join " ", @elems;
116             }
117             #$log->tracef("assign %s to arg->{$a}", $rargs->{$a});
118             } else {
119 8         23 $rargs->{$a} = splice(@$ary, $i, 1);
120             #$log->tracef("assign %s to arg->{$a}", $rargs->{$a});
121             }
122             }
123             }
124             }
125              
126 11 100 66     31 return [400, "There are extra, unassigned elements in array: [".
127             join(", ", @$ary)."]"] if @$ary && !$allow_extra_elems;
128              
129 10         47 [200, "OK", $rargs];
130             }
131              
132             1;
133             # ABSTRACT: Get subroutine arguments (%args) from array
134              
135             __END__
136              
137             =pod
138              
139             =encoding UTF-8
140              
141             =head1 NAME
142              
143             Perinci::Sub::GetArgs::Array - Get subroutine arguments (%args) from array
144              
145             =head1 VERSION
146              
147             This document describes version 0.16 of Perinci::Sub::GetArgs::Array (from Perl distribution Perinci-Sub-GetArgs-Array), released on 2016-12-10.
148              
149             =head1 SYNOPSIS
150              
151             use Perinci::Sub::GetArgs::Array;
152              
153             my $res = get_args_from_array(array=>\@ary, meta=>$meta, ...);
154              
155             =head1 DESCRIPTION
156              
157             This module provides get_args_from_array(). This module is used by, among
158             others, L<Perinci::Sub::GetArgs::Argv>.
159              
160             =head1 FUNCTIONS
161              
162              
163             =head2 get_args_from_array(%args) -> [status, msg, result, meta]
164              
165             Get subroutine arguments (%args) from array.
166              
167             Using information in metadata's C<args> property (particularly the C<pos> and
168             C<greedy> arg type clauses), extract arguments from an array into a hash
169             C<\%args>, suitable for passing into subs.
170              
171             Example:
172              
173             my $meta = {
174             v => 1.1,
175             summary => 'Multiply 2 numbers (a & b)',
176             args => {
177             a => {schema=>'num*', pos=>0},
178             b => {schema=>'num*', pos=>1},
179             }
180             }
181              
182             then C<< get_args_from_array(array=E<gt>[2, 3], meta=E<gt>$meta) >> will produce:
183              
184             [200, "OK", {a=>2, b=>3}]
185              
186             This function is not exported by default, but exportable.
187              
188             Arguments ('*' denotes required arguments):
189              
190             =over 4
191              
192             =item * B<allow_extra_elems> => I<bool> (default: 0)
193              
194             Allow extra/unassigned elements in array.
195              
196             If set to 1, then if there are array elements unassigned to one of the arguments
197             (due to missing C<pos>, for example), instead of generating an error, the
198             function will just ignore them.
199              
200             =item * B<array>* => I<array>
201              
202             NOTE: array will be modified/emptied (elements will be taken from the array as
203             they are put into the resulting args). Copy your array first if you want to
204             preserve its content.
205              
206             =item * B<meta>* => I<hash>
207              
208             =item * B<meta_is_normalized> => I<bool> (default: 0)
209              
210             Can be set to 1 if your metadata is normalized, to avoid duplicate effort.
211              
212             =back
213              
214             Returns an enveloped result (an array).
215              
216             First element (status) is an integer containing HTTP status code
217             (200 means OK, 4xx caller error, 5xx function error). Second element
218             (msg) is a string containing error message, or 'OK' if status is
219             200. Third element (result) is optional, the actual result. Fourth
220             element (meta) is called result metadata and is optional, a hash
221             that contains extra information.
222              
223             Return value: (any)
224              
225             =head1 HOMEPAGE
226              
227             Please visit the project's homepage at L<https://metacpan.org/release/Perinci-Sub-GetArgs-Array>.
228              
229             =head1 SOURCE
230              
231             Source repository is at L<https://github.com/sharyanto/perl-Perinci-Sub-GetArgs-Array>.
232              
233             =head1 BUGS
234              
235             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Perinci-Sub-GetArgs-Array>
236              
237             When submitting a bug or request, please include a test-file or a
238             patch to an existing test-file that illustrates the bug or desired
239             feature.
240              
241             =head1 SEE ALSO
242              
243             L<Perinci>
244              
245             =head1 AUTHOR
246              
247             perlancar <perlancar@cpan.org>
248              
249             =head1 COPYRIGHT AND LICENSE
250              
251             This software is copyright (c) 2016 by perlancar@cpan.org.
252              
253             This is free software; you can redistribute it and/or modify it under
254             the same terms as the Perl 5 programming language system itself.
255              
256             =cut