Validate: rename rmwhitespace to trim and use builtin::trim()

This commit is contained in:
Yorhel 2025-03-05 15:39:46 +01:00
parent cbebc3a21e
commit e4b6b77e1b
2 changed files with 25 additions and 30 deletions

View file

@ -2,7 +2,7 @@ package FU::Validate 0.2;
use v5.36; use v5.36;
use experimental 'builtin', 'for_list'; use experimental 'builtin', 'for_list';
use builtin qw/true false blessed/; use builtin qw/true false blessed trim/;
use Carp 'confess'; use Carp 'confess';
use FU::Util 'to_bool'; use FU::Util 'to_bool';
@ -12,7 +12,7 @@ my %builtin = map +($_,1), qw/
type type
default default
onerror onerror
rmwhitespace trim
values scalar sort unique values scalar sort unique
keys unknown missing keys unknown missing
func func
@ -130,7 +130,7 @@ sub _compile($schema, $validations, $rec) {
confess "Incompatible types, '$t->[0]' requires '$t->{schema}{type}', but another validation requires '$top{type}'"; confess "Incompatible types, '$t->[0]' requires '$t->{schema}{type}', but another validation requires '$top{type}'";
} }
exists $t->{schema}{$_} and !exists $top{$_} and $top{$_} = delete $t->{schema}{$_} exists $t->{schema}{$_} and !exists $top{$_} and $top{$_} = delete $t->{schema}{$_}
for qw/default onerror rmwhitespace type scalar unknown missing sort unique/; for qw/default onerror trim type scalar unknown missing sort unique/;
push @keys, keys %{ delete $t->{known_keys} }; push @keys, keys %{ delete $t->{known_keys} };
push @keys, keys %{ $t->{schema}{keys} } if $t->{schema}{keys}; push @keys, keys %{ $t->{schema}{keys} } if $t->{schema}{keys};
@ -155,7 +155,7 @@ sub compile($pkg, $schema, $validations={}) {
$c->{schema}{type} //= 'scalar'; $c->{schema}{type} //= 'scalar';
$c->{schema}{missing} //= 'create'; $c->{schema}{missing} //= 'create';
$c->{schema}{rmwhitespace} //= 1 if $c->{schema}{type} eq 'scalar'; $c->{schema}{trim} //= 1 if $c->{schema}{type} eq 'scalar';
$c->{schema}{unknown} //= 'remove' if $c->{schema}{type} eq 'hash'; $c->{schema}{unknown} //= 'remove' if $c->{schema}{type} eq 'hash';
confess "Invalid value for 'type': $c->{schema}{type}" if !$type_vals{$c->{schema}{type}}; confess "Invalid value for 'type': $c->{schema}{type}" if !$type_vals{$c->{schema}{type}};
@ -262,12 +262,8 @@ sub _validate_array {
sub _validate_input { sub _validate_input {
my $c = $_[0]; my $c = $_[0];
# rmwhitespace (needs to be done before the 'default' test) # trim (needs to be done before the 'default' test)
if (defined $_[1] && !ref $_[1] && $c->{schema}{type} eq 'scalar' && $c->{schema}{rmwhitespace}) { $_[1] = trim $_[1] =~ s/\r//rg if defined $_[1] && !ref $_[1] && $c->{schema}{type} eq 'scalar' && $c->{schema}{trim};
$_[1] =~ s/\r//g;
$_[1] =~ s/^\s*//;
$_[1] =~ s/\s*$//;
}
# default # default
if (!defined $_[1] || (!ref $_[1] && $_[1] eq '')) { if (!defined $_[1] || (!ref $_[1] && $_[1] eq '')) {
@ -410,10 +406,10 @@ 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<{}> but some built-ins have default values. This means that the empty schema C<{}>
is actually equivalent to: is actually equivalent to:
{ type => 'scalar', { type => 'scalar',
rmwhitespace => 1, trim => 1,
default => \'required', default => \'required',
missing => 'create', missing => 'create',
} }
=head2 Built-in options =head2 Built-in options
@ -444,12 +440,11 @@ C<$val> is returned instead. If C<$val> is a CODE reference, the subroutine is
called with the original value (which is either no argument, undef or an empty called with the original value (which is either no argument, undef or an empty
string) and the return value of the subroutine is used as value instead. string) and the return value of the subroutine is used as value instead.
The empty check is performed after I<rmwhitespace> and before any other The empty check is performed after I<trim> and before any other validations. So
validations. So a string containing only whitespace is considered an empty a string containing only whitespace is considered an empty string and will be
string and will be treated according to this I<default> option. As an treated according to this I<default> option. As an additional side effect,
additional side effect, other validations will never get to validate undef or other validations will never get to validate undef or an empty string, as these
an empty string, as these values are either rejected or substituted with a values are either rejected or substituted with a default.
default.
=item onerror => $val =item onerror => $val
@ -461,11 +456,11 @@ If C<$val> is a CODE reference, the subroutine is called with the (partially
normalized) input as first argument and error object as second argument. The normalized) input as first argument and error object as second argument. The
return value of the subroutine is then returned for this validation. return value of the subroutine is then returned for this validation.
=item rmwhitespace => 0/1 =item trim => 0/1
By default, any whitespace around scalar-type input is removed before testing By default, any whitespace around scalar-type input is removed before testing
any other validations. Setting I<rmwhitespace> to a false value will disable any other validations. Setting I<trim> to a false value will disable this
this behavior. behavior.
=item keys => $hashref =item keys => $hashref
@ -818,8 +813,8 @@ schema that contains the I<func> built-in option to do the actual validation.
Custom validations can also set built-in options, but the semantics differ a Custom validations can also set built-in options, but the semantics differ a
little depending on the option. First, be aware that many of the built-in little depending on the option. First, be aware that many of the built-in
options apply to the whole schema and not just to the custom validation. For options apply to the whole schema and not just to the custom validation. For
example, if the top-level schema sets C<< rmwhitespace => 0 >>, then all example, if the top-level schema sets C<< trim => 0 >>, then all validations
validations used in that schema may get input with whitespace around it. used in that schema may get input with whitespace around it.
All validations used in a schema need to agree upon a single I<type> option. All validations used in a schema need to agree upon a single I<type> option.
If a custom validation does not specify a I<type> option (and no type is If a custom validation does not specify a I<type> option (and no type is

View file

@ -15,7 +15,7 @@ my %validations = (
defaultsub1 => { default => sub { 2 } }, defaultsub1 => { default => sub { 2 } },
defaultsub2 => { default => sub { defined $_[0] } }, defaultsub2 => { default => sub { defined $_[0] } },
onerrorsub => { onerror => sub { ref $_[1] } }, onerrorsub => { onerror => sub { ref $_[1] } },
collapsews => { rmwhitespace => 0, func => sub { $_[0] =~ s/\s+/ /g; 1 } }, collapsews => { trim => 0, func => sub { $_[0] =~ s/\s+/ /g; 1 } },
neverfails => { onerror => 'err' }, neverfails => { onerror => 'err' },
revnum => { type => 'array', sort => sub($x,$y) { $y <=> $x } }, revnum => { type => 'array', sort => sub($x,$y) { $y <=> $x } },
uniquelength => { type => 'array', values => { type => 'array' }, unique => sub { scalar @{$_[0]} } }, uniquelength => { type => 'array', values => { type => 'array' }, unique => sub { scalar @{$_[0]} } },
@ -68,11 +68,11 @@ t { defaultsub2 => 1 }, undef, '';
t { defaultsub2 => 1 }, '', 1; t { defaultsub2 => 1 }, '', 1;
t { onerrorsub => 1 }, undef, 'FU::Validate::err'; t { onerrorsub => 1 }, undef, 'FU::Validate::err';
# rmwhitespace # trim
t {}, " Va\rl id \n ", 'Val id'; t {}, " Va\rl id \n ", 'Val id';
t { rmwhitespace => 0 }, " Va\rl id \n ", " Va\rl id \n "; t { trim => 0 }, " Va\rl id \n ", " Va\rl id \n ";
f {}, ' ', { validation => 'required' }; f {}, ' ', { validation => 'required' };
t { rmwhitespace => 0 }, ' ', ' '; t { trim => 0 }, ' ', ' ';
# arrays # arrays
f {}, [], { validation => 'type', expected => 'scalar', got => 'array' }; f {}, [], { validation => 'type', expected => 'scalar', got => 'array' };
@ -161,7 +161,7 @@ t { mybool => 1 }, undef, 0;
t { mybool => 1 }, '', 0; t { mybool => 1 }, '', 0;
t { collapsews => 1 }, " \t\n ", ' '; t { collapsews => 1 }, " \t\n ", ' ';
t { collapsews => 1 }, ' x ', ' x '; t { collapsews => 1 }, ' x ', ' x ';
t { collapsews => 1, rmwhitespace => 1 }, ' x ', 'x'; t { collapsews => 1, trim => 1 }, ' x ', 'x';
f { person => 1 }, 1, { validation => 'type', expected => 'hash', got => 'scalar' }; f { person => 1 }, 1, { validation => 'type', expected => 'hash', got => 'scalar' };
t { person => 1, default => 1 }, undef, 1; t { person => 1, default => 1 }, undef, 1;
f { person => 1 }, { sex => 1 }, { validation => 'person', error => { validation => 'keys', errors => [{ key => 'name', validation => 'required' }] } }; f { person => 1 }, { sex => 1 }, { validation => 'person', error => { validation => 'keys', errors => [{ key => 'name', validation => 'required' }] } };