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