Data::Sah::Coerce - Coercion rules for Data::Sah
This document describes version 0.049 of Data::Sah::Coerce (from Perl distribution Data-Sah-Coerce), released on 2020-05-24.
use Data::Sah::Coerce qw(gen_coercer); # a utility routine: gen_coercer my $c = gen_coercer( type => 'date', coerce_to => 'DateTime', coerce_rules => ['From_str::natural'], # explicitly enable a rule, etc # return_type => 'str+val', # default is 'val' ); my $val = $c->(123); # unchanged, 123 my $val = $c->(1463307881); # becomes a DateTime object my $val = $c->("2016-05-15"); # becomes a DateTime object my $val = $c->("2016foo"); # unchanged, "2016foo"
This distribution contains a standard set of coercion rules for Data::Sah. It is separated from the Data-Sah distribution and can be used independently.
Data-Sah
A coercion rule is put in Data::Sah::Coerce::$COMPILER::To_$TARGET_TYPE::From_$SOURCE_TYPE::DESCRIPTION module, for example: Data::Sah::Coerce::perl::To_date::From_float::epoch for converting date from integer (Unix epoch) or Data::Sah::Coerce::perl::To_date::From_str::iso8601 for converting date from ISO8601 strings like "2016-05-15".
Data::Sah::Coerce::$COMPILER::To_$TARGET_TYPE::From_$SOURCE_TYPE::DESCRIPTION
Basically, a coercion rule will provide an expression (expr_match) that evaluates to true when data can be coerced, and an expression (expr_coerce) to actually coerce/convert data to the target type. This rule can be combined with other rules to form the final coercion code.
expr_match
expr_coerce
The module must contain meta subroutine which must return a hashref that has the following keys (* marks that the key is required):
meta
*
v* => int (default: 1)
Metadata specification version. From DefHash. Currently at 4.
History: bumped from 3 to 4 to remove enable_by_default property. Now the list of standard (enabled-by-default) coercion rules is maintained in Data::Sah::Coerce itself. This allows us to skip scanning all Data::Sah::Coerce::* coercion modules installed on the system. Data::Sah::Coerce still accepts version 3; it just ignores the enable_by_default property.
enable_by_default
History: bumped from 2 to 3 to allow coercion expression to return error message explaining why coercion fails. The might_die metadata property is replaced with might_fail. When might_fail is set to true, expr_coerce must return array containing error message and coerced data, instead of just coerced data.
might_die
might_fail
History: Bumped from 1 to 2 to exclude old module names.
summary => str
From DefHash.
might_fail => bool (default: 0)
Whether coercion might fail, e.g. because of invalid input. If set to 1, expr_coerce key that the coerce() routine returns must be an expression that returns an array (envelope) of (error_msg, data) instead of just coerced data. Error message should be a string that is set when coercion fails and explains why. Otherwise, if coercion succeeds, the error message string should be set to undefined value.
coerce()
(error_msg, data)
An example of a rule like this is coercing from string in the form of "YYYY-MM-DD" to a DateTime object. The rule might match any string in the form of /\A(\d{4})-(\d{2})-(\d{2})\z/ while it might not be a valid date.
/\A(\d{4})-(\d{2})-(\d{2})\z/
This is used for coercion rules that act as a data checker.
prio => int (0-100, default: 50)
This is to regulate the ordering of rules. The higher the number, the lower the priority (meaning the rule will be put further back). Rules that are computationally more expensive and/or match more broadly in general should be put further back (lower priority, higher number).
precludes => array of (str|re)
List the other rules or rule patterns that are precluded by this rule. Rules that are mutually exclusive or pure alternatives to one another (e.g. date coercien rules From_str::natural vs From_str::flexible both parse natural language date string; there is usually little to none of usefulness in using both; besides, both rules match all string and dies when failing to parse the string. So in From_str::natural rule, you'll find this metadata:
From_str::natural
precludes => [qr/\A(From_str::alami(_.+)?|From_str::natural)\z/]
and in From_str::flexible rule you'll find this metadata:
From_str::flexible
precludes => [qr/\A(From_str::alami(_.+)?|From_str::flexible)\z/]
Also note that rules which are specifically requested to be used (e.g. using x.perl.coerce_rules attribute in Sah schema) will still be precluded.
x.perl.coerce_rules
The module must also contain coerce subroutine which must generate the code for coercion. The subroutine must accept a hash of arguments (* indicates required arguments):
coerce
data_term => str
coerce_to => str
Some Sah types are "abstract" and can be represented using a choice of several actual types in the target programming language. For example, "date" can be represented in Perl as an integer (Unix epoch value), or a DateTime object, or a Time::Moment object.
Not all target Sah types will need this argument.
The coerce subroutine must return a hashref with the following keys (* indicates required keys):
expr_match => str
Expression in the target language to test whether the data can be coerced. For example, in Data::Sah::Coerce::perl::To_date::From_float::epoch, only integers ranging from 10^8 to 2^31 are converted into date. Non-integers or integers outside this range are not coerced.
Data::Sah::Coerce::perl::To_date::From_float::epoch
expr_coerce => str
Expression in the target language to actually convert data to the target type.
modules => hash
A list of modules required by the expressions.
Basically, the coerce subroutine must generates a code that accepts a non-undef data and must convert this data to the desired type/format under the right condition. The code to match the right condition must be put in expr_match and the code to convert data must be put in expr_coerce.
Program/library that uses Data::Sah::Coerce can collect rules from the rule modules then compose them into the final code, something like (in pseudocode):
if (data is undef) { return undef; } elsif (data matches expr-match-from-rule1) { return expr-coerce-from-rule1; } elsif (data matches expr-match-from-rule2) { return expr-coerce-from-rule1; ... } else { # does not match any expr-match return original data; }
If set to true, will log the generated coercer code (currently using Log::ger at trace level). To see the log message, e.g. to the screen, you can use something like:
% TRACE=1 perl -MLog::ger::LevelFromEnv -MLog::ger::Output=Screen \ -MData::Sah::Coerce=gen_coercer -E'my $c = gen_coercer(...)'
Usage:
gen_coercer() -> any
Generate coercer code.
This is mostly for testing. Normally the coercion rules will be used from Data::Sah.
This function is not exported by default, but exportable.
No arguments.
Return value: (any)
Set default for $Log_Coercer_Code.
$Log_Coercer_Code
Please visit the project's homepage at https://metacpan.org/release/Data-Sah-Coerce.
Source repository is at https://github.com/perlancar/perl-Data-Sah-Coerce.
Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Data-Sah-Coerce
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.
Data::Sah
Data::Sah::CoerceJS
App::SahUtils, including coerce-with-sah to conveniently test coercion from the command-line.
perlancar <perlancar@cpan.org>
This software is copyright (c) 2020, 2019, 2018, 2017, 2016 by perlancar@cpan.org.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Data::Sah::Coerce, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Data::Sah::Coerce
CPAN shell
perl -MCPAN -e shell install Data::Sah::Coerce
For more information on module installation, please visit the detailed CPAN module installation guide.