File Coverage

blib/lib/Data/Rx/Failure.pm
Criterion Covered Total %
statement 48 68 70.5
branch 7 18 38.8
condition n/a
subroutine 13 17 76.4
pod 0 13 0.0
total 68 116 58.6


line stmt bran cond sub pod time code
1 1     1   11 use v5.12.0;
  1         4  
2 1     1   5 use warnings;
  1         2  
  1         50  
3             package Data::Rx::Failure 0.200008;
4             # ABSTRACT: structured failure report from an Rx checker
5              
6             #pod =head1 SYNOPSIS
7             #pod
8             #pod This is part of a L, which is what is thrown when a
9             #pod schema's C method finds a problem with the input. For more
10             #pod information on it, look at the documentation for L.
11             #pod
12             #pod =cut
13              
14 1     1   17 use overload '""' => \&stringify;
  1         2  
  1         10  
15              
16             sub new {
17 1507     1507 0 2781 my ($class, $arg) = @_;
18              
19             my $guts = {
20             rx => $arg->{rx},
21 1507         3820 struct => [ $arg->{struct} ],
22             };
23              
24 1507         6260 bless $guts => $class;
25             }
26              
27 4780     4780 0 13632 sub struct { $_[0]->{struct} }
28              
29             sub contextualize {
30 253     253 0 391 my ($self, $struct) = @_;
31              
32 253         317 push @{ $self->struct }, $struct;
  253         415  
33              
34 253 50       449 if (my $failures = $self->struct->[0]{failures}) {
35 0         0 $_->contextualize($struct) foreach @$failures;
36             }
37              
38 253         554 return $self;
39             }
40              
41             sub value {
42 0     0 0 0 my ($self) = @_;
43              
44 0         0 return $self->struct->[0]{value};
45             }
46              
47             sub error_types {
48 1488     1488 0 2625 my ($self) = @_;
49              
50 1488         1882 return @{ $self->struct->[0]{error} };
  1488         2721  
51             }
52              
53             sub error_string {
54 47     47 0 86 my ($self) = @_;
55              
56 47         89 join ', ', $self->error_types;
57             }
58              
59             sub keys {
60 0     0 0 0 my ($self) = @_;
61              
62 0 0       0 return @{ $self->struct->[0]{keys} || [] };
  0         0  
63             }
64              
65             sub size {
66 0     0 0 0 my ($self) = @_;
67              
68 0         0 return $self->struct->[0]{size};
69             }
70              
71             sub data_path {
72 1347     1347 0 30055 my ($self) = @_;
73              
74 1452 100       1876 map {; map { $_->[0] } @{ $_->{data_path} || [] } }
  38         100  
  1452         8736  
75 1347         2001 reverse @{ $self->struct };
  1347         2390  
76             }
77              
78             sub data_string {
79 47     47 0 88 my ($self) = @_;
80              
81 47         105 return $self->_path_string('$data', 'data_path');
82             }
83              
84             sub check_path {
85 1345     1345 0 2430 my ($self) = @_;
86              
87 1450 100       2045 map {; map { $_->[0] } @{ $_->{check_path} || [] } }
  177         415  
  1450         7870  
88 1345         1858 reverse @{ $self->struct };
  1345         2680  
89             }
90              
91             sub check_string {
92 0     0 0 0 my ($self) = @_;
93              
94 0         0 return $self->_path_string('$schema', 'check_path');
95             }
96              
97             sub _path_string {
98 47     47   104 my ($self, $base, $key) = @_;
99              
100 47         67 my $str = $base;
101              
102 47 50       68 for my $frame (reverse @{ $self->struct || [] }) {
  47         76  
103 47         83 my $hunk = $frame->{ $key };
104 47         172 for my $entry (@$hunk) {
105 0 0       0 if ($entry->[1] eq 'key') { $str .= "->{$entry->[0]}"; }
  0 0       0  
    0          
106 0         0 elsif ($entry->[1] eq 'index') { $str .= "->[$entry->[0]]"; }
107 0         0 elsif ($entry->[2]) { $str = $entry->[2]->($str, @$entry) }
108 0         0 else { $str .= "->? $entry->[0] ?"; }
109             }
110             }
111              
112 47         242 return $str;
113             }
114              
115             sub stringify {
116 47     47 0 496 my ($self) = @_;
117              
118 47         86 my $struct = $self->struct;
119              
120             my $str = sprintf "Failed %s: %s (error: %s at %s)",
121             $struct->[0]{type},
122             $struct->[0]{message},
123 47         135 $self->error_string,
124             $self->data_string;
125              
126             # also stringify failures under the current failure (as for //any),
127             # with indentation
128 47 50       143 if (my $failures = $struct->[0]{failures}) {
129 0         0 foreach my $fail (@$failures) {
130 0         0 my $tmp = "$fail";
131 0         0 $tmp =~ s/\A/ - /;
132 0         0 $tmp =~ s/(?<=\n)^/ /mg;
133 0         0 $str .= "\n$tmp";
134             }
135             }
136              
137 47         163 return $str;
138             }
139              
140             1;
141              
142             __END__