File Coverage

blib/lib/Data/Sah/DefaultValueCommon.pm
Criterion Covered Total %
statement 42 45 93.3
branch 10 12 83.3
condition 3 6 50.0
subroutine 3 3 100.0
pod 1 1 100.0
total 59 67 88.0


line stmt bran cond sub pod time code
1             package Data::Sah::DefaultValueCommon;
2              
3 4     4   352090 use 5.010001;
  4         15  
4 4     4   23 use strict 'subs', 'vars';
  4         7  
  4         4950  
5              
6             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
7             our $DATE = '2024-01-17'; # DATE
8             our $DIST = 'Data-Sah-DefaultValue'; # DIST
9             our $VERSION = '0.005'; # VERSION
10              
11             our %common_args = (
12             default_value_rules => {
13             summary => 'A specification of default-value rules to use (or avoid)',
14             schema => ['array*', of=>'str*'],
15             description => <<'_',
16              
17             This setting is used to specify which default-value rules to use (or avoid) in a
18             flexible way. Each element is a string, in the form of either `NAME` to mean
19             specifically include a rule, or `!NAME` to exclude a rule.
20              
21             To use the default-value rules R1 and R2:
22              
23             ['R1', 'R2']
24             _
25             },
26             );
27              
28             our %gen_default_value_code_args = (
29             %common_args,
30             source => {
31             summary => 'If set to true, will return coercer source code string'.
32             ' instead of compiled code',
33             schema => 'bool',
34             },
35             );
36              
37             our %SPEC;
38              
39             $SPEC{get_default_value_rules} = {
40             v => 1.1,
41             summary => 'Get default-value rules',
42             description => <<'_',
43              
44             This routine determines default-value rule modules to use (based on the
45             `default_value_rules` specified), loads them, filters out modules with
46             old/incompatible metadata version, and return the list of rules.
47              
48             This common routine is used by compilers, as well as
49             and .
50              
51             _
52             args => {
53             %common_args,
54             compiler => {
55             schema => 'str*',
56             req => 1,
57             },
58             extra_args => {
59             summary => 'Extra arguments to pass to value() subroutine',
60             schema => 'hash*',
61             description => <<'MARKDOWN',
62              
63             This is used, for example, by when generating validation code
64             from Sah schema. Sometimes the default value rule needs to know additional
65             information like what a date type should be coerced to (DateTime object, or
66             epoch) so it can generate the appropriate default value.
67              
68             MARKDOWN
69             },
70             },
71             };
72             sub get_default_value_rules {
73 5     5 1 13372 my %args = @_;
74              
75 5         9 my $compiler = $args{compiler};
76              
77 5         9 my $prefix = "Data::Sah::Value::$compiler\::";
78              
79 5         7 my @rules0;
80 5   50     7 for my $item (@{ $args{default_value_rules} // [] }) {
  5         25  
81 6 100       15 my $rule_name = ref $item eq 'ARRAY' ? $item->[0] : $item;
82 6         18 my $is_exclude = $rule_name =~ s/\A!//;
83 6 100       11 if ($is_exclude) {
84 2         4 @rules0 = grep { $_ ne $rule_name } @rules0;
  1         5  
85             } else {
86 4 50       14 push @rules0, $item unless grep { $_ eq $rule_name } @rules0;
  0         0  
87             }
88             }
89              
90 5         8 my @rules;
91 5         10 for my $item (@rules0) {
92 4         6 my ($rule_name, $rule_gen_args);
93 4 100       10 if (ref $item eq 'ARRAY') {
94 1         2 $rule_name = $item->[0];
95 1         2 $rule_gen_args = $item->[1];
96             } else {
97 3 100       14 if ($item =~ /(.*?)=(.*)/) {
98 1         3 $rule_name = $1;
99 1         4 $rule_gen_args = {split /,/, $2};
100             } else {
101 2         3 $rule_name = $item;
102 2         4 $rule_gen_args = undef;
103             }
104             }
105              
106 4         6 my $mod = $prefix . $rule_name;
107 4         22 (my $mod_pm = "$mod.pm") =~ s!::!/!g;
108 4         1379 require $mod_pm;
109 3         6 my $rule_meta = &{"$mod\::meta"};
  3         14  
110 3   50     11 my $rule_v = ($rule_meta->{v} // 1);
111 3 50       9 if ($rule_v != 1) {
112 0         0 warn "Only value rule module following metadata version 1 is ".
113             "supported, this rule module '$mod' follows metadata version ".
114             "$rule_v and will not be used";
115 0         0 next;
116             }
117 3         25 my $rule = &{"$mod\::value"}(
118             (args => $rule_gen_args) x !!$rule_gen_args,
119 3   50     9 %{ $args{extra_args} // {} },
  3         19  
120             );
121 3         8 $rule->{name} = $rule_name;
122 3         5 $rule->{meta} = $rule_meta;
123 3         10 push @rules, $rule;
124             }
125              
126 4         14 \@rules;
127             }
128              
129             1;
130             # ABSTRACT: Common stuffs for Data::Sah::DefaultValue and Data::Sah::DefaultValueJS
131              
132             __END__