File Coverage

blib/lib/Perinci/Sub/GetArgs/Array.pm
Criterion Covered Total %
statement 33 33 100.0
branch 11 14 78.5
condition 8 10 80.0
subroutine 5 5 100.0
pod 1 1 100.0
total 58 63 92.0


line stmt bran cond sub pod time code
1             package Perinci::Sub::GetArgs::Array;
2              
3             our $DATE = '2015-09-04'; # DATE
4             our $VERSION = '0.15'; # VERSION
5              
6 1     1   19430 use 5.010001;
  1         3  
7 1     1   4 use strict;
  1         2  
  1         20  
8 1     1   4 use warnings;
  1         2  
  1         30  
9             #use Log::Any '$log';
10              
11 1     1   4 use Exporter;
  1         1  
  1         498  
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 9     9 1 23032 my %fargs = @_;
83 9 50       33 my $ary = $fargs{array} or return [400, "Please specify array"];
84 9 50       24 my $meta = $fargs{meta} or return [400, "Please specify meta"];
85 9 50       29 unless ($fargs{meta_is_normalized}) {
86 9         1066 require Perinci::Sub::Normalize;
87 9         2522 $meta = Perinci::Sub::Normalize::normalize_function_metadata(
88             $meta);
89             }
90 9   100     4065 my $allow_extra_elems = $fargs{allow_extra_elems} // 0;
91              
92 9         19 my $rargs = {};
93              
94 9   50     24 my $args_p = $meta->{args} // {};
95 9         23 for my $i (reverse 0..@$ary-1) {
96             #$log->tracef("i=$i");
97 17         60 while (my ($a, $as) = each %$args_p) {
98 30         40 my $o = $as->{pos};
99 30 100 100     165 if (defined($o) && $o == $i) {
100 10 100       24 if ($as->{greedy}) {
101 3         5 my $type = $as->{schema}[0];
102 3         9 my @elems = splice(@$ary, $i);
103 3 100       7 if ($type eq 'array') {
104 2         11 $rargs->{$a} = \@elems;
105             } else {
106 1         8 $rargs->{$a} = join " ", @elems;
107             }
108             #$log->tracef("assign %s to arg->{$a}", $rargs->{$a});
109             } else {
110 7         35 $rargs->{$a} = splice(@$ary, $i, 1);
111             #$log->tracef("assign %s to arg->{$a}", $rargs->{$a});
112             }
113             }
114             }
115             }
116              
117 9 100 66     39 return [400, "There are extra, unassigned elements in array: [".
118             join(", ", @$ary)."]"] if @$ary && !$allow_extra_elems;
119              
120 8         52 [200, "OK", $rargs];
121             }
122              
123             1;
124             # ABSTRACT: Get subroutine arguments (%args) from array
125              
126             __END__