File Coverage

blib/lib/Params/ValidationCompiler.pm
Criterion Covered Total %
statement 17 17 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 26 26 100.0


line stmt bran cond sub pod time code
1             package Params::ValidationCompiler;
2              
3 17     17   4022955 use strict;
  17         138  
  17         476  
4 17     17   102 use warnings;
  17         35  
  17         664  
5              
6             our $VERSION = '0.31';
7              
8 17     17   8433 use Params::ValidationCompiler::Compiler;
  17         146  
  17         628  
9              
10 17     17   135 use Exporter qw( import );
  17         42  
  17         1277  
11              
12             our @EXPORT_OK = qw( compile source_for validation_for );
13              
14             sub validation_for {
15 57     57 1 177593 return Params::ValidationCompiler::Compiler->new(@_)->subref;
16             }
17              
18             ## no critic (TestingAndDebugging::ProhibitNoWarnings)
19 17     17   105 no warnings 'once';
  17         41  
  17         1524  
20             *compile = \&validation_for;
21             ## use critic
22              
23             sub source_for {
24 1     1 1 119 return Params::ValidationCompiler::Compiler->new(@_)->source;
25             }
26              
27             1;
28              
29             # ABSTRACT: Build an optimized subroutine parameter validator once, use it forever
30              
31             __END__
32              
33             =pod
34              
35             =encoding UTF-8
36              
37             =head1 NAME
38              
39             Params::ValidationCompiler - Build an optimized subroutine parameter validator once, use it forever
40              
41             =head1 VERSION
42              
43             version 0.31
44              
45             =head1 SYNOPSIS
46              
47             use Types::Standard qw( Int Str );
48             use Params::ValidationCompiler qw( validation_for );
49              
50             {
51             my $validator = validation_for(
52             params => {
53             foo => { type => Int },
54             bar => {
55             type => Str,
56             optional => 1,
57             },
58             baz => {
59             type => Int,
60             default => 42,
61             },
62             },
63             );
64              
65             sub foo {
66             my %args = $validator->(@_);
67             }
68             }
69              
70             {
71             my $validator = validation_for(
72             params => [
73             { type => Int },
74             {
75             type => Str,
76             optional => 1,
77             },
78             ],
79             );
80              
81             sub bar {
82             my ( $int, $str ) = $validator->(@_);
83             }
84             }
85              
86             {
87             my $validator = validation_for(
88             params => [
89             foo => { type => Int },
90             bar => {
91             type => Str,
92             optional => 1,
93             },
94             ],
95             named_to_list => 1,
96             );
97              
98             sub baz {
99             my ( $foo, $bar ) = $validator->(@_);
100             }
101             }
102              
103             =head1 DESCRIPTION
104              
105             This module creates a customized, highly efficient parameter checking
106             subroutine. It can handle named or positional parameters, and can return the
107             parameters as key/value pairs or a list of values.
108              
109             In addition to type checks, it also supports parameter defaults, optional
110             parameters, and extra "slurpy" parameters.
111              
112             =for Pod::Coverage compile
113              
114             =head1 PARAMETERS
115              
116             This module has two options exports, C<validation_for> and C<source_for>. Both
117             of these subs accept the same options:
118              
119             =head2 params
120              
121             An arrayref or hashref containing a parameter specification.
122              
123             If you pass a hashref then the generated validator sub will expect named
124             parameters. The C<params> value should be a hashref where the parameter names
125             are keys and the specs are the values.
126              
127             If you pass an arrayref and C<named_to_list> is false, the validator will
128             expect positional params. Each element of the C<params> arrayref should be a
129             parameter spec.
130              
131             If you pass an arrayref and C<named_to_list> is true, the validator will expect
132             named params, but will return a list of values. In this case the arrayref
133             should contain a I<list> of key/value pairs, where parameter names are the keys
134             and the specs are the values.
135              
136             Each spec can contain either a boolean or hashref. If the spec is a boolean,
137             this indicates required (true) or optional (false).
138              
139             The spec hashref accepts the following keys:
140              
141             =over 4
142              
143             =item * type
144              
145             A type object. This can be a L<Moose> type (from L<Moose> or L<MooseX::Types>),
146             a L<Type::Tiny> type, or a L<Specio> type.
147              
148             If the type has coercions, those will always be used.
149              
150             =item * default
151              
152             This can either be a simple (non-reference) scalar or a subroutine reference.
153             The sub ref will be called without any arguments (for now).
154              
155             =item * optional
156              
157             A boolean indicating whether or not the parameter is optional. By default,
158             parameters are required unless you provide a default.
159              
160             =back
161              
162             =head2 slurpy
163              
164             If this is a simple true value, then the generated subroutine accepts
165             additional arguments not specified in C<params>. By default, extra arguments
166             cause an exception.
167              
168             You can also pass a type constraint here, in which case all extra arguments
169             must be values of the specified type.
170              
171             =head2 named_to_list
172              
173             If this is true, the generated subroutine will expect a list of key-value pairs
174             or a hashref and it will return a list containing only values. The C<params>
175             you pass must be a arrayref of key-value pairs. The order of these pairs
176             determines the order in which values are returned.
177              
178             You cannot combine C<slurpy> with C<named_to_list> as there is no way to know
179             how to order the extra return values.
180              
181             =head2 return_object
182              
183             If this is true, the generated subroutine will return an object instead of a
184             hashref. You cannot set this option to true if you set either or C<slurpy> or
185             C<named_to_list>.
186              
187             The object's methods correspond to the parameter names passed to the
188             subroutine. While calling methods on an object is slower than accessing a
189             hashref, the advantage is that if you typo a parameter name you'll get a
190             helpful error.
191              
192             If you have L<Class::XSAccessor> installed then this will be used to create the
193             class's methods, which makes it fairly fast.
194              
195             The returned object is in a generated class. Do not rely on this class name
196             being anything in specific, and don't check this object using C<isa>, C<DOES>,
197             or anything similar.
198              
199             When C<return_object> is true, the parameter spec hashref also accepts to the
200             following additional keys:
201              
202             =over 4
203              
204             =item * getter
205              
206             Use this to set an explicit getter method name for the parameter. By default
207             the method name will be the same as the parameter name. Note that if the
208             parameter name is not a valid sub name, then you will get an error compiling
209             the validation sub unless you specify a getter for the parameter.
210              
211             =item * predicate
212              
213             Use this to ask for a predicate method to be created for this parameter. The
214             predicate method returns true if the parameter was passed and false if it
215             wasn't. Note that this is only useful for optional parameters, but you can ask
216             for a predicate for any parameter.
217              
218             =back
219              
220             =head1 EXPORTS
221              
222             The exported subs are:
223              
224             =head2 validation_for(...)
225              
226             This returns a subroutine that implements the specific parameter checking. This
227             subroutine expects to be given the parameters to validate in C<@_>. If all the
228             parameters are valid, it will return the validated parameters (with defaults as
229             appropriate), either as a list of key-value pairs or as a list of just values.
230             If any of the parameters are invalid it will throw an exception.
231              
232             For validators expected named params, the generated subroutine accepts either a
233             list of key-value pairs or a single hashref. Otherwise the validator expects a
234             list of values.
235              
236             For now, you must shift off the invocant yourself.
237              
238             This subroutine accepts the following additional parameters:
239              
240             =over 4
241              
242             =item * name
243              
244             If this is given, then the generated subroutine will be named using
245             L<Sub::Util>. This is strongly recommended as it makes it possible to
246             distinguish different check subroutines when profiling or in stack traces.
247              
248             This name will also be used in some exception messages, even if L<Sub::Util> is
249             not available.
250              
251             Note that you must install L<Sub::Util> yourself separately, as it is not
252             required by this distribution, in order to avoid requiring a compiler.
253              
254             =item * name_is_optional
255              
256             If this is true, then the name is ignored when C<Sub::Util> is not installed.
257             If this is false, then passing a name when L<Sub::Util> cannot be loaded causes
258             an exception.
259              
260             This is useful for CPAN modules where you want to set a name if you can, but
261             you do not want to add a prerequisite on L<Sub::Util>.
262              
263             =item * debug
264              
265             Sets the C<EVAL_CLOSURE_PRINT_SOURCE> environment variable to true before
266             calling C<Eval::Closure::eval_closure()>. This causes the source of the
267             subroutine to be printed before it's C<eval>'d.
268              
269             =back
270              
271             =head2 source_for(...)
272              
273             This returns a two element list. The first is a string containing the source
274             code for the generated sub. The second is a hashref of "environment" variables
275             to be used when generating the subroutine. These are the arguments that are
276             passed to L<Eval::Closure>.
277              
278             =head1 SUPPORT
279              
280             Bugs may be submitted at L<https://github.com/houseabsolute/Params-ValidationCompiler/issues>.
281              
282             =head1 SOURCE
283              
284             The source code repository for Params-ValidationCompiler can be found at L<https://github.com/houseabsolute/Params-ValidationCompiler>.
285              
286             =head1 DONATIONS
287              
288             If you'd like to thank me for the work I've done on this module, please
289             consider making a "donation" to me via PayPal. I spend a lot of free time
290             creating free software, and would appreciate any support you'd care to offer.
291              
292             Please note that B<I am not suggesting that you must do this> in order for me
293             to continue working on this particular software. I will continue to do so,
294             inasmuch as I have in the past, for as long as it interests me.
295              
296             Similarly, a donation made in this way will probably not make me work on this
297             software much more, unless I get so many donations that I can consider working
298             on free software full time (let's all have a chuckle at that together).
299              
300             To donate, log into PayPal and send money to autarch@urth.org, or use the
301             button at L<https://houseabsolute.com/foss-donations/>.
302              
303             =head1 AUTHOR
304              
305             Dave Rolsky <autarch@urth.org>
306              
307             =head1 CONTRIBUTORS
308              
309             =for stopwords Gregory Oschwald Tomasz Konojacki
310              
311             =over 4
312              
313             =item *
314              
315             Gregory Oschwald <goschwald@maxmind.com>
316              
317             =item *
318              
319             Gregory Oschwald <oschwald@gmail.com>
320              
321             =item *
322              
323             Tomasz Konojacki <me@xenu.pl>
324              
325             =back
326              
327             =head1 COPYRIGHT AND LICENSE
328              
329             This software is Copyright (c) 2016 - 2023 by Dave Rolsky.
330              
331             This is free software, licensed under:
332              
333             The Artistic License 2.0 (GPL Compatible)
334              
335             The full text of the license can be found in the
336             F<LICENSE> file included with this distribution.
337              
338             =cut