Validate: allow array schemas + defer known_keys hash creation
Doesn't allow multiple 'func' options yet, needs work.
This commit is contained in:
parent
64a105e013
commit
1363e11269
2 changed files with 33 additions and 16 deletions
|
|
@ -76,7 +76,7 @@ our %default_validations = (
|
|||
uint => { _reg $re_uint }, # implies num
|
||||
min => sub($min) { +{ num => 1, func => sub { $_[0] >= $min ? 1 : { expected => $min, got => $_[0] } } } },
|
||||
max => sub($max) { +{ num => 1, func => sub { $_[0] <= $max ? 1 : { expected => $max, got => $_[0] } } } },
|
||||
range => sub { +{ min => $_[0][0], max => $_[0][1] } },
|
||||
range => sub { [ min => $_[0][0], max => $_[0][1] ] },
|
||||
|
||||
ascii => { _reg qr/^[\x20-\x7E]*$/ },
|
||||
sl => { _reg qr/^[^\t\r\n]+$/ },
|
||||
|
|
@ -99,10 +99,12 @@ our %default_validations = (
|
|||
#
|
||||
sub _compile($schema, $validations, $rec) {
|
||||
my(%top, @val);
|
||||
my @keys = keys $schema->{keys}->%* if $schema->{keys};
|
||||
|
||||
for my($name, $val) (%$schema) {
|
||||
for my($name, $val) (ref $schema eq 'ARRAY' ? @$schema : %$schema) {
|
||||
if ($builtin{$name}) {
|
||||
confess "Invalid value for 'type': $val" if $name eq 'type' && !$type_vals{$val};
|
||||
confess "Invalid value for 'missing': $val" if $name eq 'missing' && !$missing_vals{$val};
|
||||
confess "Invalid value for 'unknown': $val" if $name eq 'unknown' && !$unknown_vals{$val};
|
||||
$top{$name} = $schema->{$name};
|
||||
next;
|
||||
}
|
||||
|
|
@ -117,6 +119,8 @@ sub _compile($schema, $validations, $rec) {
|
|||
push @val, $v;
|
||||
}
|
||||
|
||||
my @keys = keys $top{keys}->%* if $top{keys};
|
||||
|
||||
for my ($n,$t) (qw/keys hash unknown hash values array sort array unique array/) {
|
||||
next if !exists $top{$n};
|
||||
confess "Incompatible types, the schema specifies '$top{type}' but the '$n' validation implies '$t'" if $top{type} && $top{type} ne $t;
|
||||
|
|
@ -132,8 +136,8 @@ sub _compile($schema, $validations, $rec) {
|
|||
exists $t->{$_} and !exists $top{$_} and $top{$_} = delete $t->{$_}
|
||||
for qw/default onerror trim type scalar unknown missing sort unique/;
|
||||
|
||||
push @keys, keys %{ delete $t->{known_keys} };
|
||||
push @keys, keys %{ $t->{keys} } if $t->{keys};
|
||||
push @keys, delete($t->{known_keys})->@* if $t->{known_keys};
|
||||
push @keys, keys $t->{keys}->%* if $t->{keys};
|
||||
}
|
||||
|
||||
# Compile sub-schemas
|
||||
|
|
@ -141,24 +145,20 @@ sub _compile($schema, $validations, $rec) {
|
|||
$top{values} = __PACKAGE__->compile($top{values}, $validations) if $top{values};
|
||||
|
||||
$top{validations} = \@val;
|
||||
$top{known_keys} = { map +($_,1), @keys };
|
||||
$top{known_keys} = \@keys;
|
||||
\%top;
|
||||
}
|
||||
|
||||
|
||||
sub compile($pkg, $schema, $validations={}) {
|
||||
return $schema if $schema isa __PACKAGE__;
|
||||
|
||||
my $c = _compile $schema, $validations, 64;
|
||||
|
||||
$c->{type} //= 'scalar';
|
||||
$c->{missing} //= 'create';
|
||||
$c->{trim} //= 1 if $c->{type} eq 'scalar';
|
||||
$c->{unknown} //= 'remove' if $c->{type} eq 'hash';
|
||||
|
||||
confess "Invalid value for 'type': $c->{type}" if !$type_vals{$c->{type}};
|
||||
confess "Invalid value for 'missing': $c->{missing}" if !$missing_vals{$c->{missing}};
|
||||
confess "Invalid value for 'unknown': $c->{unknown}" if exists $c->{unknown} && !$unknown_vals{$c->{unknown}};
|
||||
$c->{known_keys} = { map +($_,1), $c->{known_keys}->@* } if $c->{known_keys};
|
||||
|
||||
delete $c->{default} if ref $c->{default} eq 'SCALAR' && ${$c->{default}} eq 'required';
|
||||
|
||||
|
|
@ -420,10 +420,11 @@ validation. These are documented in L</SCHEMA DEFINITION> below.
|
|||
|
||||
=head1 SCHEMA DEFINITION
|
||||
|
||||
A schema is a hashref, each key is the name of a built-in option or of a
|
||||
validation to be performed. None of the options or validations are required,
|
||||
but some built-ins have default values. This means that the empty schema C<{}>
|
||||
is actually equivalent to:
|
||||
A schema is an arrayref or hashref, where each key is the name of a built-in
|
||||
option or of a validation to be performed and the values are the arguments to
|
||||
those validations. None of the options or validations are required, but some
|
||||
built-ins have default values. This means that the empty schema C<{}> is
|
||||
actually equivalent to:
|
||||
|
||||
{ type => 'scalar',
|
||||
trim => 1,
|
||||
|
|
@ -431,6 +432,19 @@ is actually equivalent to:
|
|||
missing => 'create',
|
||||
}
|
||||
|
||||
Built-in options are always validated in a fixed order, but the order in which
|
||||
standard and custom validations are performed is random when the schema is
|
||||
given as a hashref. This is rarely a problem, but it can in some cases affect
|
||||
the returned error message or whether a later validation will receive data
|
||||
normalized by a previous validation. An arrayref can be used to enforce a
|
||||
validation order:
|
||||
|
||||
[ enum => [1, 2, 'a'], int => 1 ]
|
||||
|
||||
Or to use the same validation multiple times:
|
||||
|
||||
[ regex => qr/^a/, regex => qr/z$/ ]
|
||||
|
||||
=head2 Built-in options
|
||||
|
||||
=over
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue