SYNOPSIS

     #IFUNBUILT
     use Perinci::Sub::ValidateArgs;
     #END IFUNBUILT
    
     our %SPEC;
     $SPEC{foo} = {
         v => 1.1,
         args => {
             a1 => {
                schema => 'int*',
                req => 1,
             },
             a2 => {
                 schema => [array => of=>'int*'],
                 default => 'peach',
             },
         },
         'x.func.validate_args' => 1,
     };
     sub foo {
         my %args = @_; # VALIDATE_ARGS
         # IFUNBUILT
         if (my $err = validate_args(\%args)) { return $err }
         # END IFUNBUILT
    
         ...
     }

DESCRIPTION

    This module (PSV for short) can be used to validate function arguments
    using schema information in Rinci function metadata. Schemas will be
    checked using Data::Sah validators which are generated on-demand and
    then cached.

    An alternative to this module is Dist::Zilla::Plugin::Rinci::Validate
    (DZP:RV), where during build, the # VALIDATE_ARGS directive will be
    filled with generated validator code.

    Using DZP:RV is faster (see/run the benchmark in
    Bencher::Scenario::PerinciSubValidateArgs::Overhead), but you need to
    build the distribution first and use the built version. Using PSV is
    slower (up to several times, plus there is a startup overhead of
    compiling the Data::Sah validators the first time the function is
    called), but is more flexible because you don't have to build the
    distribution first.

    A strategy can be made using Dist::Zilla::Plugin::IfBuilt. You mark the
    PSV parts with #IFUNBUILT and #END IFUNBUILT directives so the PSV part
    is only used in the unbuilt version, while the built/production version
    uses the faster DZP:RV.

    BTW, yet another alternative is to use Perinci::CmdLine::Lite or
    Perinci::CmdLine::Inline. These two frameworks can generate the
    argument validator code for you. But this only works if you access your
    function via CLI using the frameworks.

    And yet another alternative is Perinci::Sub::Wrapper (PSW) which wraps
    your function with code to validate arguments (among others). PSW is
    used by Perinci::CmdLine::Classic, for example.

    If you use DZP:RV and/or PSV, you might want to set Rinci metadata
    attribute x.func.validate_args to true to express that your function
    body performs argument validation. This hint is used by PSW or the
    Perinci::CmdLine::* frameworks to skip (duplicate) argument validation.

FUNCTIONS

    All the functions are exported by default.

 validate_args(\%args) => $err

    Get Rinci function metadata from caller's %SPEC package variable. Then
    create (and cache) a set of Data::Sah validators to check the value of
    each argument in %args. If there is an error, will return an error
    response $err (or die, if result_naked metadata property is true).
    Otherwise will return undef.

    Arguments in %args will have their default values/coercions/filters
    applied, so they are ready for use.

    Currently only support args_as => 'hash' (the default).

SEE ALSO

    Rinci, Data::Sah

    Dist::Zilla::Plugin::IfBuilt

    Dist::Zilla::Plugin::Rinci::Validate

