Perinci-Sub-Wrapper

 view release on metacpan or  search on metacpan

lib/Perinci/Sub/Wrapper.pm  view on Meta::CPAN

                exists($sch->[1]{default}) ? 1:0;
            if ($opt_va) {

                $self->push_lines("if (exists($argterm)) {");
                $self->indent;

                if ($argspec->{stream}) {
                    die "Error in schema for argument '$argname': must be str/buf/array if stream=1"
                        unless $sch->[0] =~ /\A(str|buf|array)\z/; # XXX allow 'any' if all of its 'of' values are str/buf/array
                    die "Error in schema for argument '$argname': must specify 'of' array clause if stream=1"
                        if $sch->[0] eq 'array' && !$sch->[1]{of};

                    $self->_errif(
                        400,
                        qq["Argument '$prefix$argname' (stream) fails validation: must be coderef"],
                        "!(ref($argterm) eq 'CODE')",
                    );
                    $self->push_lines('{ ## introduce scope because we want to declare a generic variable $i');
                    $self->indent;
                    $self->push_lines(
                        'my $i = -1;',
                        "my \$origsub = $argterm;",
                        '# arg coderef wrapper for validation',
                        "$argterm = sub {",
                    );
                    $self->indent;
                    $self->push_lines(
                        '$i++;',
                        "my \$rec = \$origsub->();",
                        'return undef unless defined $rec;',
                    );
                }

                my $dn = $argname; $dn =~ s/\W+/_/g;
                my $cd = $self->_plc->compile(
                    data_name            => $dn,
                    data_term            => $argspec->{stream} ? '$rec' : $argterm,
                    schema               => $argspec->{stream} && $sch->[0] eq 'array' ? $sch->[1]{of} : $sch,
                    schema_is_normalized => $opt_sin,
                    return_type          => 'str',
                    indent_level         => $self->get_indent_level + 1,
                    core                 => $self->{_args}{core},
                    core_or_pp           => $self->{_args}{core_or_pp},
                    pp                   => $self->{_args}{pp},
                    %{ $self->{_args}{_extra_sah_compiler_args} // {}},
                );
                die "Incompatible Data::Sah version (cd v=$cd->{v}, expected 2)" unless $cd->{v} == 2;
                for my $mod_rec (@{ $cd->{modules} }) {
                    next unless $mod_rec->{phase} eq 'runtime';
                    $self->_add_module($mod_rec->{use_statement} // $mod_rec->{name});
                }
                $self->_add_var($_, $cd->{vars}{$_})
                    for sort keys %{ $cd->{vars} };
                $cd->{result} =~ s/\A\s+//;
                $self->push_lines(
                    "my \$err_$dn;",
                    "$cd->{result};",
                );
                if ($argspec->{stream}) {
                    $self->push_lines(
                        'if ('."\$err_$dn".') { die "Record #$i of streaming argument '."'$prefix$argname'".' ($rec) fails validation: '."\$err_$dn".'" }',
                        '$rec;',
                    );
                } else {
                    $self->_errif(
                        400, qq["Argument '$prefix$argname' fails validation: \$err_$dn"],
                        "\$err_$dn");
                }
                if ($argspec->{meta}) {
                    $self->push_lines("# check subargs of $prefix$argname");
                    $self->_handle_args(
                            %args,
                            v => $argspec->{meta}{args},
                            prefix => ($prefix ? "$prefix/" : "") . "$argname/",
                            argsterm => '%{'.$argterm.'}',
                        );
                }
                if ($argspec->{element_meta}) {
                    $self->push_lines("# check element subargs of $prefix$argname");
                    my $indexterm = "$prefix$argname";
                    $indexterm =~ s/\W+/_/g;
                    $indexterm = '$i_' . $indexterm;
                    $self->push_lines('for my '.$indexterm.' (0..$#{ '.$argterm.' }) {');
                    $self->indent;
                    $self->_errif(
                        400, qq("Argument '$prefix$argname\[).qq($indexterm]' fails validation: must be hash"),
                        "ref($argterm\->[$indexterm]) ne 'HASH'");
                    $self->_handle_args(
                        %args,
                        v => $argspec->{element_meta}{args},
                        prefix => ($prefix ? "$prefix/" : "") . "$argname\[$indexterm]/",
                        argsterm => '%{'.$argterm.'->['.$indexterm.']}',
                    );
                    $self->unindent;
                    $self->push_lines('}');
                }
                $self->unindent;
                if ($argspec->{stream}) {
                    $self->push_lines('}; ## arg coderef wrapper');
                    $self->unindent;
                    $self->push_lines('} ## close scope');
                    $self->unindent;
                }
                if ($has_default_prop) {
                    $self->push_lines(
                        '} else {',
                        "    $argterm //= ".dmp($argspec->{default}).";");
                } elsif ($has_sch_default) {
                    $self->push_lines(
                        '} else {',
                        "    $argterm //= ".dmp($sch->[1]{default}).";");
                }
                $self->push_lines("} ## if exists arg $prefix$argname");
            } # if opt_va

        } elsif ($has_default_prop) {
            # doesn't have schema but have 'default' property, we still need to
            # set default here
            $self->push_lines("$argterm = ".dmp($argspec->{default}).
                                  " if !exists($argterm);");
        }



( run in 0.995 second using v1.01-cache-2.11-cpan-140bd7fdf52 )