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