File Coverage

blib/lib/JSON/Schema/Modern/Vocabulary/FormatAnnotation.pm
Criterion Covered Total %
statement 102 103 99.0
branch 16 18 88.8
condition 12 15 80.0
subroutine 26 26 100.0
pod 0 3 0.0
total 156 165 94.5


line stmt bran cond sub pod time code
1 38     38   1839 use strict;
  38         106  
  38         2022  
2 38     38   234 use warnings;
  38         86  
  38         4223  
3             package JSON::Schema::Modern::Vocabulary::FormatAnnotation;
4             # vim: set ts=8 sts=2 sw=2 tw=100 et :
5             # ABSTRACT: Implementation of the JSON Schema Format-Annotation vocabulary
6              
7             our $VERSION = '0.632';
8              
9 38     38   945 use 5.020;
  38         163  
10 38     38   265 use Moo;
  38         91  
  38         397  
11 38     38   25783 use strictures 2;
  38         421  
  38         1871  
12 38     38   20720 use stable 0.031 'postderef';
  38         831  
  38         331  
13 38     38   9959 use experimental 'signatures';
  38         103  
  38         221  
14 38     38   2884 no autovivification warn => qw(fetch store exists delete);
  38         88  
  38         605  
15 38     38   3745 use if "$]" >= 5.022, experimental => 're_strict';
  38         133  
  38         1277  
16 38     38   3994 no if "$]" >= 5.031009, feature => 'indirect';
  38         105  
  38         3189  
17 38     38   287 no if "$]" >= 5.033001, feature => 'multidimensional';
  38         159  
  38         2929  
18 38     38   249 no if "$]" >= 5.033006, feature => 'bareword_filehandles';
  38         91  
  38         2466  
19 38     38   305 no if "$]" >= 5.041009, feature => 'smartmatch';
  38         94  
  38         2140  
20 38     38   249 no feature 'switch';
  38         107  
  38         1574  
21 38     38   232 use Feature::Compat::Try;
  38         96  
  38         524  
22 38     38   2921 use JSON::Schema::Modern::Utilities qw(A E assert_keyword_type get_type);
  38         88  
  38         4085  
23 38     38   26162 use JSON::Schema::Modern::Vocabulary::FormatAssertion;
  38         158  
  38         2939  
24 38     38   361 use if "$]" < 5.041010, 'List::Util' => 'any';
  38         94  
  38         2257  
25 38     38   236 use if "$]" >= 5.041010, experimental => 'keyword_any';
  38         121  
  38         760  
26 38     38   3848 use Scalar::Util 'looks_like_number';
  38         95  
  38         2726  
27 38     38   279 use namespace::clean;
  38         89  
  38         252  
28              
29             with 'JSON::Schema::Modern::Vocabulary';
30              
31 22     22 0 52 sub vocabulary ($class) {
  22         94  
  22         50  
32 22         126 'https://json-schema.org/draft/2019-09/vocab/format' => 'draft2019-09',
33             'https://json-schema.org/draft/2020-12/vocab/format-annotation' => 'draft2020-12';
34             }
35              
36 1     1 0 2 sub evaluation_order ($class) { 2 }
  1         2  
  1         2  
  1         6  
37              
38 160     160 0 5665 sub keywords ($class, $spec_version) {
  160         369  
  160         381  
  160         280  
39 160         2271 qw(format);
40             }
41              
42 1449     1449   3462 sub _traverse_keyword_format ($class, $schema, $state) {
  1449         3354  
  1449         3166  
  1449         2872  
  1449         2740  
43 1449 50       7155 return if not assert_keyword_type($state, $schema, 'string');
44 1449         6401 return 1;
45             }
46              
47 1975     1975   5096 sub _eval_keyword_format ($class, $data, $schema, $state) {
  1975         5060  
  1975         4423  
  1975         4440  
  1975         4315  
  1975         4273  
48 1975         13539 A($state, $schema->{format});
49 1975 100       12173 return 1 if not $state->{validate_formats};
50              
51             # { type => .., sub => .. }
52             my $spec = $state->{evaluator}->_get_format_validation($schema->{format})
53 926   100     6100 // JSON::Schema::Modern::Vocabulary::FormatAssertion->_get_default_format_validation($state, $schema->{format});
54              
55             # §7.2.1 (draft2020-12) "Specifying the Format-Annotation vocabulary and enabling validation in an
56             # implementation should not be viewed as being equivalent to specifying the Format-Assertion
57             # vocabulary since implementations are not required to provide full validation support when the
58             # Format-Assertion vocabulary is not specified."
59             # §7.2.3 (draft2019-09) "An implementation MUST NOT fail validation or cease processing due to an
60             # unknown format attribute."
61 926 100       3252 return 1 if not $spec;
62              
63 769         2930 my $type = get_type($data);
64 769 100       2475 $type = 'number' if $type eq 'integer';
65              
66             return 1 if
67 67         288 not ref $spec->{type} eq 'ARRAY' ? any { $type eq $_ } $spec->{type}->@* : $type eq $spec->{type}
68             and not ($state->{stringy_numbers} and $type eq 'string'
69 769 100 66     5937 and ref $spec->{type} eq 'ARRAY' ? any { $_ eq 'number' } $spec->{type}->@* : $spec->{type} eq 'number'
  0 50 66     0  
    100 66        
      100        
70             and looks_like_number($data));
71              
72 417         931 my $valid;
73 417         1173 try {
74 417         1872 $valid = $spec->{sub}->($data);
75             }
76             catch ($e) {
77             # we treat a missing optional prereq as if the format is not implemented, therefore it is valid
78 37         1596 $valid = 1;
79             }
80              
81             return E($state, 'not a valid %s %s', $schema->{format},
82             ref $spec->{type} eq 'ARRAY' ? join(', ', $spec->{type}->@*) : $spec->{type})
83 417 100       20622 if not $valid;
    100          
84 236         1426 return 1;
85             }
86              
87             1;
88              
89             __END__