diff --git a/FU/MultipartFormData.pm b/FU/MultipartFormData.pm index e19d7bc..a777823 100644 --- a/FU/MultipartFormData.pm +++ b/FU/MultipartFormData.pm @@ -123,7 +123,9 @@ module makes an attempt to avoid any further copies of data values. =head2 Parsing -=over FU::MultipartFormData->parse($header, $body) +=over + +=item FU::MultipartFormData->parse($header, $body) Returns an array of field objects from the given C<$header>, which must be a valid value for the C request header, and the given C<$body>, diff --git a/FU/Pg.pm b/FU/Pg.pm index ba574d6..5d8c2a7 100644 --- a/FU/Pg.pm +++ b/FU/Pg.pm @@ -806,7 +806,7 @@ error if something went wrong. It is possible to close a read-copy operation before all data has been consumed, but that causes all data to still be read and discarded during C. If you really want to interrupt a large read operation, a more -efficient approach is to call C<< $conn->close >> and discard the entire +efficient approach is to call C<< $conn->disconnect >> and discard the entire connection. It is not I to call this method, simply letting the C<$copy> object diff --git a/FU/Validate.pm b/FU/Validate.pm index 4b93eb9..fd180b8 100644 --- a/FU/Validate.pm +++ b/FU/Validate.pm @@ -94,8 +94,8 @@ our %default_validations = ( # # name => $name_or_undef, # validations => [ $recursive_compiled_object, .. ], -# schema => $builtin_validations, # known_keys => { $key => 1, .. } # Extracted from 'keys', Used for the 'unknown' validation +# %builtin_validations # sub _compile($schema, $validations, $rec) { my(%top, @val); @@ -125,26 +125,24 @@ sub _compile($schema, $validations, $rec) { # Inherit some builtin options from validations for my $t (@val) { - if ($top{type} && $t->{schema}{type} && $top{type} ne $t->{schema}{type}) { - confess "Incompatible types, the schema specifies '$top{type}' but validation '$t->{name}' requires '$t->{schema}{type}'" if $schema->{type}; - confess "Incompatible types, '$t->[0]' requires '$t->{schema}{type}', but another validation requires '$top{type}'"; + if ($top{type} && $t->{type} && $top{type} ne $t->{type}) { + confess "Incompatible types, the schema specifies '$top{type}' but validation '$t->{name}' requires '$t->{type}'" if $schema->{type}; + confess "Incompatible types, '$t->[0]' requires '$t->{type}', but another validation requires '$top{type}'"; } - exists $t->{schema}{$_} and !exists $top{$_} and $top{$_} = delete $t->{schema}{$_} + 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->{schema}{keys} } if $t->{schema}{keys}; + push @keys, keys %{ $t->{keys} } if $t->{keys}; } # Compile sub-schemas $top{keys} = { map +($_, __PACKAGE__->compile($top{keys}{$_}, $validations)), keys $top{keys}->%* } if $top{keys}; $top{values} = __PACKAGE__->compile($top{values}, $validations) if $top{values}; - return { - validations => \@val, - schema => \%top, - known_keys => { map +($_,1), @keys }, - }; + $top{validations} = \@val; + $top{known_keys} = { map +($_,1), @keys }; + \%top; } @@ -153,26 +151,26 @@ sub compile($pkg, $schema, $validations={}) { my $c = _compile $schema, $validations, 64; - $c->{schema}{type} //= 'scalar'; - $c->{schema}{missing} //= 'create'; - $c->{schema}{trim} //= 1 if $c->{schema}{type} eq 'scalar'; - $c->{schema}{unknown} //= 'remove' if $c->{schema}{type} eq 'hash'; + $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->{schema}{type}" if !$type_vals{$c->{schema}{type}}; - confess "Invalid value for 'missing': $c->{schema}{missing}" if !$missing_vals{$c->{schema}{missing}}; - confess "Invalid value for 'unknown': $c->{schema}{unknown}" if exists $c->{schema}{unknown} && !$unknown_vals{$c->{schema}{unknown}}; + 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}}; - delete $c->{schema}{default} if ref $c->{schema}{default} eq 'SCALAR' && ${$c->{schema}{default}} eq 'required'; + delete $c->{default} if ref $c->{default} eq 'SCALAR' && ${$c->{default}} eq 'required'; - if (exists $c->{schema}{sort}) { - my $s = $c->{schema}{sort}; - $c->{schema}{sort} = + if (exists $c->{sort}) { + my $s = $c->{sort}; + $c->{sort} = ref $s eq 'CODE' ? $s : $s eq 'str' ? sub($x,$y) { $x cmp $y } : $s eq 'num' ? sub($x,$y) { $x <=> $y } - : confess "Unknown value for 'sort': $c->{schema}{sort}"; + : confess "Unknown value for 'sort': $c->{sort}"; } - $c->{schema}{unique} = sub { $_[0] } if $c->{schema}{unique} && !ref $c->{schema}{unique} && !$c->{schema}{sort}; + $c->{unique} = sub { $_[0] } if $c->{unique} && !ref $c->{unique} && !$c->{sort}; bless $c, $pkg; } @@ -182,14 +180,14 @@ sub _validate_rec { my $c = $_[0]; # hash keys - if ($c->{schema}{keys}) { + if ($c->{keys}) { my @err; - for my ($k, $s) ($c->{schema}{keys}->%*) { + for my ($k, $s) ($c->{keys}->%*) { if (!exists $_[1]{$k}) { - next if $s->{schema}{missing} eq 'ignore'; - return { validation => 'missing', key => $k } if $s->{schema}{missing} eq 'reject'; - $_[1]{$k} = ref $s->{schema}{default} eq 'CODE' ? $s->{schema}{default}->() : $s->{schema}{default} // undef; - next if exists $s->{schema}{default}; + next if $s->{missing} eq 'ignore'; + return { validation => 'missing', key => $k } if $s->{missing} eq 'reject'; + $_[1]{$k} = ref $s->{default} eq 'CODE' ? $s->{default}->() : $s->{default} // undef; + next if exists $s->{default}; } my $r = _validate($s, $_[1]{$k}); @@ -202,10 +200,10 @@ sub _validate_rec { } # array values - if ($c->{schema}{values}) { + if ($c->{values}) { my @err; for my $i (0..$#{$_[1]}) { - my $r = _validate($c->{schema}{values}, $_[1][$i]); + my $r = _validate($c->{values}, $_[1][$i]); if ($r) { $r->{index} = $i; push @err, $r; @@ -226,8 +224,8 @@ sub _validate_rec { } # func - if ($c->{schema}{func}) { - my $r = $c->{schema}{func}->($_[1]); + if ($c->{func}) { + my $r = $c->{func}->($_[1]); return { %$r, validation => 'func' } if ref $r eq 'HASH'; return { validation => 'func', result => $r } if !$r; } @@ -236,24 +234,24 @@ sub _validate_rec { sub _validate_array { my $c = $_[0]; - return if $c->{schema}{type} ne 'array'; + return if $c->{type} ne 'array'; - $_[1] = [sort { $c->{schema}{sort}->($a, $b) } $_[1]->@* ] if $c->{schema}{sort}; + $_[1] = [sort { $c->{sort}->($a, $b) } $_[1]->@* ] if $c->{sort}; # Key-based uniqueness - if ($c->{schema}{unique} && ref $c->{schema}{unique} eq 'CODE') { + if ($c->{unique} && ref $c->{unique} eq 'CODE') { my %h; for my $i (0..$#{$_[1]}) { - my $k = $c->{schema}{unique}->($_[1][$i]); + my $k = $c->{unique}->($_[1][$i]); return { validation => 'unique', index_a => $h{$k}, value_a => $_[1][$h{$k}], index_b => $i, value_b => $_[1][$i], key => $k } if exists $h{$k}; $h{$k} = $i; } # Comparison-based uniqueness - } elsif ($c->{schema}{unique}) { + } elsif ($c->{unique}) { for my $i (0..$#{$_[1]}-1) { return { validation => 'unique', index_a => $i, value_a => $_[1][$i], index_b => $i+1, value_b => $_[1][$i+1] } - if $c->{schema}{sort}->($_[1][$i], $_[1][$i+1]) == 0 + if $c->{sort}->($_[1][$i], $_[1][$i+1]) == 0 } } } @@ -263,29 +261,29 @@ sub _validate_input { my $c = $_[0]; # trim (needs to be done before the 'default' test) - $_[1] = trim $_[1] =~ s/\r//rg if defined $_[1] && !ref $_[1] && $c->{schema}{type} eq 'scalar' && $c->{schema}{trim}; + $_[1] = trim $_[1] =~ s/\r//rg if defined $_[1] && !ref $_[1] && $c->{type} eq 'scalar' && $c->{trim}; # default if (!defined $_[1] || (!ref $_[1] && $_[1] eq '')) { - if (exists $c->{schema}{default}) { - $_[1] = ref $c->{schema}{default} eq 'CODE' ? $c->{schema}{default}->($_[1]) : $c->{schema}{default}; + if (exists $c->{default}) { + $_[1] = ref $c->{default} eq 'CODE' ? $c->{default}->($_[1]) : $c->{default}; return; } return { validation => 'required' }; } - if ($c->{schema}{type} eq 'scalar') { + if ($c->{type} eq 'scalar') { return { validation => 'type', expected => 'scalar', got => lc ref $_[1] } if ref $_[1]; - } elsif ($c->{schema}{type} eq 'hash') { + } elsif ($c->{type} eq 'hash') { return { validation => 'type', expected => 'hash', got => lc ref $_[1] || 'scalar' } if ref $_[1] ne 'HASH'; # Each branch below makes a shallow copy of the hash, so that further # validations can perform in-place modifications without affecting the # input. - if ($c->{schema}{unknown} eq 'remove') { + if ($c->{unknown} eq 'remove') { $_[1] = { map +($_, $_[1]{$_}), grep $c->{known_keys}{$_}, keys $_[1]->%* }; - } elsif ($c->{schema}{unknown} eq 'reject') { + } elsif ($c->{unknown} eq 'reject') { my @err = grep !$c->{known_keys}{$_}, keys $_[1]->%*; return { validation => 'unknown', keys => \@err, expected => [ sort keys %{$c->{known_keys}} ] } if @err; $_[1] = { $_[1]->%* }; @@ -293,16 +291,16 @@ sub _validate_input { $_[1] = { $_[1]->%* }; } - } elsif ($c->{schema}{type} eq 'array') { - $_[1] = [$_[1]] if $c->{schema}{scalar} && !ref $_[1]; - return { validation => 'type', expected => $c->{schema}{scalar} ? 'array or scalar' : 'array', got => lc ref $_[1] || 'scalar' } if ref $_[1] ne 'ARRAY'; + } elsif ($c->{type} eq 'array') { + $_[1] = [$_[1]] if $c->{scalar} && !ref $_[1]; + return { validation => 'type', expected => $c->{scalar} ? 'array or scalar' : 'array', got => lc ref $_[1] || 'scalar' } if ref $_[1] ne 'ARRAY'; $_[1] = [$_[1]->@*]; # Create a shallow copy to prevent in-place modification. - } elsif ($c->{schema}{type} eq 'any') { + } elsif ($c->{type} eq 'any') { # No need to do anything here. } else { - confess "Unknown type '$c->{schema}{type}'"; # Already checked in compile(), but be extra safe + confess "Unknown type '$c->{type}'"; # Already checked in compile(), but be extra safe } &_validate_rec || &_validate_array; @@ -312,8 +310,8 @@ sub _validate_input { sub _validate { my $c = $_[0]; my $r = &_validate_input; - ($r, $_[1]) = (undef, ref $c->{schema}{onerror} eq 'CODE' ? $c->{schema}{onerror}->($_[0], bless $r, 'FU::Validate::err') : $c->{schema}{onerror}) - if $r && exists $c->{schema}{onerror}; + ($r, $_[1]) = (undef, ref $c->{onerror} eq 'CODE' ? $c->{onerror}->($_[0], bless $r, 'FU::Validate::err') : $c->{onerror}) + if $r && exists $c->{onerror}; $r }