File Coverage

blib/lib/Perinci/Sub/GetArgs/Array.pm
Criterion Covered Total %
statement 38 39 97.4
branch 14 18 77.7
condition 10 13 76.9
subroutine 5 5 100.0
pod 1 1 100.0
total 68 76 89.4


line stmt bran cond sub pod time code
1             package Perinci::Sub::GetArgs::Array;
2              
3             our $DATE = '2019-04-15'; # DATE
4             our $VERSION = '0.170'; # VERSION
5              
6 1     1   137404 use 5.010001;
  1         6  
7 1     1   4 use strict;
  1         2  
  1         18  
8 1     1   4 use warnings;
  1         1  
  1         22  
9             #use Log::Any '$log';
10              
11 1     1   4 use Exporter;
  1         2  
  1         469  
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             `slurpy` 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 47616 my %fargs = @_;
83 11 50       34 my $ary = $fargs{array} or return [400, "Please specify array"];
84 11 50       25 my $meta = $fargs{meta} or return [400, "Please specify meta"];
85 11 50       24 unless ($fargs{meta_is_normalized}) {
86 11         482 require Perinci::Sub::Normalize;
87 11         1015 $meta = Perinci::Sub::Normalize::normalize_function_metadata(
88             $meta);
89             }
90 11   100     5403 my $allow_extra_elems = $fargs{allow_extra_elems} // 0;
91              
92 11         21 my $rargs = {};
93              
94 11   50     23 my $args_p = $meta->{args} // {};
95 11         26 for my $i (reverse 0..@$ary-1) {
96             #$log->tracef("i=$i");
97 24         61 while (my ($a, $as) = each %$args_p) {
98 41         52 my $o = $as->{pos};
99 41 100 100     134 if (defined($o) && $o == $i) {
100 13 100 66     46 if ($as->{slurpy} // $as->{greedy}) {
101 5         16 my $type = $as->{schema}[0];
102 5         14 my @elems = splice(@$ary, $i);
103 5 100       12 if ($type eq 'array') {
    100          
104 2         7 $rargs->{$a} = \@elems;
105             } elsif ($type eq 'hash') {
106 2         5 $rargs->{$a} = {};
107 2         4 for my $j (0..$#elems) {
108 6         9 my $elem = $elems[$j];
109 6 50       22 unless ($elem =~ /(.*?)=(.*)/) {
110 0         0 return [400, "Invalid key=value pair in element #$j"];
111             }
112 6         18 $rargs->{$a}{$1} = $2;
113             }
114             } else {
115 1         7 $rargs->{$a} = join " ", @elems;
116             }
117             #$log->tracef("assign %s to arg->{$a}", $rargs->{$a});
118             } else {
119 8         28 $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     32 return [400, "There are extra, unassigned elements in array: [".
127             join(", ", @$ary)."]"] if @$ary && !$allow_extra_elems;
128              
129 10         51 [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.170 of Perinci::Sub::GetArgs::Array (from Perl distribution Perinci-Sub-GetArgs-Array), released on 2019-04-15.
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
164              
165             Usage:
166              
167             get_args_from_array(%args) -> [status, msg, payload, meta]
168              
169             Get subroutine arguments (%args) from array.
170              
171             Using information in metadata's C<args> property (particularly the C<pos> and
172             C<slurpy> arg type clauses), extract arguments from an array into a hash
173             C<\%args>, suitable for passing into subs.
174              
175             Example:
176              
177             my $meta = {
178             v => 1.1,
179             summary => 'Multiply 2 numbers (a & b)',
180             args => {
181             a => {schema=>'num*', pos=>0},
182             b => {schema=>'num*', pos=>1},
183             }
184             }
185              
186             then C<< get_args_from_array(array=E<gt>[2, 3], meta=E<gt>$meta) >> will produce:
187              
188             [200, "OK", {a=>2, b=>3}]
189              
190             This function is not exported by default, but exportable.
191              
192             Arguments ('*' denotes required arguments):
193              
194             =over 4
195              
196             =item * B<allow_extra_elems> => I<bool> (default: 0)
197              
198             Allow extra/unassigned elements in array.
199              
200             If set to 1, then if there are array elements unassigned to one of the arguments
201             (due to missing C<pos>, for example), instead of generating an error, the
202             function will just ignore them.
203              
204             =item * B<array>* => I<array>
205              
206             NOTE: array will be modified/emptied (elements will be taken from the array as
207             they are put into the resulting args). Copy your array first if you want to
208             preserve its content.
209              
210             =item * B<meta>* => I<hash>
211              
212             =item * B<meta_is_normalized> => I<bool> (default: 0)
213              
214             Can be set to 1 if your metadata is normalized, to avoid duplicate effort.
215              
216             =back
217              
218             Returns an enveloped result (an array).
219              
220             First element (status) is an integer containing HTTP status code
221             (200 means OK, 4xx caller error, 5xx function error). Second element
222             (msg) is a string containing error message, or 'OK' if status is
223             200. Third element (payload) is optional, the actual result. Fourth
224             element (meta) is called result metadata and is optional, a hash
225             that contains extra information.
226              
227             Return value: (any)
228              
229             =head1 HOMEPAGE
230              
231             Please visit the project's homepage at L<https://metacpan.org/release/Perinci-Sub-GetArgs-Array>.
232              
233             =head1 SOURCE
234              
235             Source repository is at L<https://github.com/perlancar/perl-Perinci-Sub-GetArgs-Array>.
236              
237             =head1 BUGS
238              
239             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>
240              
241             When submitting a bug or request, please include a test-file or a
242             patch to an existing test-file that illustrates the bug or desired
243             feature.
244              
245             =head1 SEE ALSO
246              
247             L<Perinci>
248              
249             =head1 AUTHOR
250              
251             perlancar <perlancar@cpan.org>
252              
253             =head1 COPYRIGHT AND LICENSE
254              
255             This software is copyright (c) 2019, 2016, 2015, 2014, 2013, 2012, 2011 by perlancar@cpan.org.
256              
257             This is free software; you can redistribute it and/or modify it under
258             the same terms as the Perl 5 programming language system itself.
259              
260             =cut