Validate: Normalize num/int/uint to Perl numeric types + add 64bit limit to int/uint

Normalization may be undone by later validations, but this should work
in most cases.
This commit is contained in:
Yorhel 2025-03-30 13:51:14 +02:00
parent 2f50736782
commit 13661b46f9
2 changed files with 10 additions and 9 deletions

View file

@ -81,9 +81,9 @@ our %default_validations = (
bool => { type => 'any', func => sub { my $r = to_bool $_[0]; return {} if !defined $r; $_[0] = $r; 1 } }, bool => { type => 'any', func => sub { my $r = to_bool $_[0]; return {} if !defined $r; $_[0] = $r; 1 } },
anybool => { type => 'any', default => false, func => sub { $_[0] = $_[0] ? true : false; 1 } }, anybool => { type => 'any', default => false, func => sub { $_[0] = $_[0] ? true : false; 1 } },
num => { _reg $re_num }, num => [ _reg($re_num), func => sub { $_[0] = $_[0]*1; 1 } ],
int => { _reg $re_int }, # implies num int => [ _reg($re_int), func => sub { return { message => 'integer out of range' } if $_[0] < -9223372036854775808 || $_[0] > 9223372036854775807; $_[0] = int $_[0]; 1 } ],
uint => { _reg $re_uint }, # implies num uint => [ _reg($re_uint), func => sub { return { message => 'integer out of range' } if $_[0] > 18446744073709551615; $_[0] = int $_[0]; 1 } ],
min => sub($min) { +{ num => 1, func => sub { $_[0] >= $min ? 1 : { expected => $min, got => $_[0] } } } }, 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] } } } }, 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] ] },
@ -780,17 +780,18 @@ Require the input to be a boolean type as per C<to_bool()> in L<FU::Util>.
Implies C<< type => 'scalar' >>. Require the input to be a number formatted Implies C<< type => 'scalar' >>. Require the input to be a number formatted
using the format permitted by JSON. Note that this is slightly more restrictive using the format permitted by JSON. Note that this is slightly more restrictive
from Perl's number formatting, in that 'NaN', 'Inf' and thousand separators are from Perl's number formatting, in that 'NaN', 'Inf' and thousand separators are
not permitted. not permitted. The value is normalized to a Perl integer or floating point
value, which means precision for large numbers may be lost.
=item int => 1 =item int => 1
Implies C<< type => 'scalar' >>. Require the input to be an (arbitrarily large) Implies C<< type => 'scalar' >>. Require the input to be an (at most) 64-bit
integer. integer.
=item uint => 1 =item uint => 1
Implies C<< type => 'scalar' >>. Require the input to be an (arbitrarily large) Implies C<< type => 'scalar' >>. Require the input to be an (at most) 64-bit
positive integer. unsigned integer.
=item min => $num =item min => $num

View file

@ -209,8 +209,8 @@ t { num => 1 }, '1', '1';
f { num => 1 }, '1.1.', nerr '1.1.'; f { num => 1 }, '1.1.', nerr '1.1.';
f { num => 1 }, '1.-1', nerr '1.-1'; f { num => 1 }, '1.-1', nerr '1.-1';
f { num => 1 }, '.1', nerr '.1'; f { num => 1 }, '.1', nerr '.1';
t { num => 1 }, '0.1e5', '0.1e5'; t { num => 1 }, '0.1e5', 10000;
t { num => 1 }, '0.1e+5', '0.1e+5'; t { num => 1 }, '0.1e+5', 10000;
f { num => 1 }, '0.1e5.1', nerr '0.1e5.1'; f { num => 1 }, '0.1e5.1', nerr '0.1e5.1';
t { int => 1 }, 0, 0; t { int => 1 }, 0, 0;
t { int => 1 }, -123, -123; t { int => 1 }, -123, -123;