File Coverage

blib/lib/Data/Rx/Failure.pm
Criterion Covered Total %
statement 49 69 71.0
branch 7 18 38.8
condition n/a
subroutine 13 17 76.4
pod 0 13 0.0
total 69 117 58.9


line stmt bran cond sub pod time code
1 1     1   4 use strict;
  1         1  
  1         24  
2 1     1   3 use warnings;
  1         1  
  1         41  
3             package Data::Rx::Failure;
4             # ABSTRACT: structured failure report from an Rx checker
5             $Data::Rx::Failure::VERSION = '0.200007';
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   4 use overload '""' => \&stringify;
  1         1  
  1         8  
15              
16             sub new {
17 1507     1507 0 1401 my ($class, $arg) = @_;
18              
19 1507         2939 my $guts = {
20             rx => $arg->{rx},
21             struct => [ $arg->{struct} ],
22             };
23              
24 1507         6702 bless $guts => $class;
25             }
26              
27 4780     4780 0 10878 sub struct { $_[0]->{struct} }
28              
29             sub contextualize {
30 253     253 0 243 my ($self, $struct) = @_;
31              
32 253         173 push @{ $self->struct }, $struct;
  253         310  
33              
34 253 50       328 if (my $failures = $self->struct->[0]{failures}) {
35 0         0 $_->contextualize($struct) foreach @$failures;
36             }
37              
38 253         544 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 1281 my ($self) = @_;
49              
50 1488         1025 return @{ $self->struct->[0]{error} };
  1488         1851  
51             }
52              
53             sub error_string {
54 47     47 0 36 my ($self) = @_;
55              
56 47         71 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 19301 my ($self) = @_;
73              
74 1452 100       961 map {; map { $_->[0] } @{ $_->{data_path} || [] } }
  38         95  
  1452         7400  
  1347         1743  
75 1347         1113 reverse @{ $self->struct };
76             }
77              
78             sub data_string {
79 47     47 0 44 my ($self) = @_;
80              
81 47         90 return $self->_path_string('$data', 'data_path');
82             }
83              
84             sub check_path {
85 1345     1345 0 1277 my ($self) = @_;
86              
87 1450 100       1029 map {; map { $_->[0] } @{ $_->{check_path} || [] } }
  177         297  
  1450         7302  
  1345         1911  
88 1345         1078 reverse @{ $self->struct };
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   56 my ($self, $base, $key) = @_;
99              
100 47         43 my $str = $base;
101              
102 47 50       43 for my $frame (reverse @{ $self->struct || [] }) {
  47         67  
103 47         52 my $hunk = $frame->{ $key };
104 47         103 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         201 return $str;
113             }
114              
115             sub stringify {
116 47     47 0 342 my ($self) = @_;
117              
118 47         74 my $struct = $self->struct;
119              
120 47         113 my $str = sprintf "Failed %s: %s (error: %s at %s)",
121             $struct->[0]{type},
122             $struct->[0]{message},
123             $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       117 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         113 return $str;
138             }
139              
140             1;
141              
142             __END__