File Coverage

blib/lib/Valiemon.pm
Criterion Covered Total %
statement 52 53 98.1
branch 13 16 81.2
condition 5 9 55.5
subroutine 14 14 100.0
pod 0 5 0.0
total 84 97 86.6


line stmt bran cond sub pod time code
1             package Valiemon;
2 19     19   420539 use 5.012;
  19         67  
3 19     19   104 use strict;
  19         32  
  19         620  
4 19     19   99 use warnings;
  19         41  
  19         996  
5 19     19   15465 use utf8;
  19         205  
  19         98  
6              
7 19     19   762 use Carp qw(croak);
  19         34  
  19         1533  
8 19     19   10083 use Valiemon::Primitives;
  19         56  
  19         778  
9 19     19   9880 use Valiemon::Context;
  19         58  
  19         799  
10 19     19   10882 use Valiemon::Attributes qw(attr);
  19         58  
  19         1412  
11              
12             use Class::Accessor::Lite (
13 19         183 ro => [qw(schema options pos schema_cache)],
14 19     19   113 );
  19         26  
15              
16             our $VERSION = "0.03";
17              
18             sub new {
19 155     155 0 101665 my ($class, $schema, $options) = @_;
20              
21             # TODO should validate own schema
22 155 50       513 if ($options->{validate_schema}) {}
23 155 50       507 croak 'schema must be a hashref' unless ref $schema eq 'HASH';
24              
25 155         1100 return bless {
26             schema => $schema,
27             options => $options,
28             schema_cache => +{},
29             }, $class;
30             }
31              
32             sub validate {
33 224     224 0 68474 my ($self, $data, $context) = @_;
34 224         731 my $schema = $self->schema;
35              
36 224   66     2255 $context //= Valiemon::Context->new($self, $schema);
37              
38 224         295 for my $key (keys %{$schema}) {
  224         761  
39 364         1093 my $attr = attr($key);
40 364 100       17429 if ($attr) {
41 338         1667 my ($is_valid, $error) = $attr->is_valid($context, $schema, $data);
42 326 100       2325 unless ($is_valid) {
43 72         333 $error->set_detail(
44             expected => $schema,
45             actual => $data,
46             );
47 72         223 $context->push_error($error);
48 72         529 next;
49             }
50             }
51             }
52              
53 212         828 my $errors = $context->errors;
54 212 100       1194 my $is_valid = scalar @$errors ? 0 : 1;
55 212 100       1141 return wantarray ? ($is_valid, $errors->[0]) : $is_valid;
56             }
57              
58             sub prims {
59 262     262 0 1518 my ($self) = @_;
60 262   66     1473 return $self->{prims} //= Valiemon::Primitives->new(
61             $self->options
62             );
63             }
64              
65             sub ref_schema_cache {
66 50     50 0 80 my ($self, $ref, $schema) = @_;
67             return defined $schema
68             ? $self->schema_cache->{$ref} = $schema
69 50 100       224 : $self->{schema_cache}->{ref};
70             }
71              
72             sub resolve_ref {
73 25     25 0 184 my ($self, $ref) = @_;
74              
75             # TODO follow the standard referencing
76 25 50       254 unless ($ref =~ qr|^#/|) {
77 0         0 croak 'This package support only single scope and `#/` referencing';
78             }
79              
80 25   33     93 return $self->ref_schema_cache($ref) || do {
81             my $paths = do {
82             my @p = split '/', $ref;
83             [ splice @p, 1 ]; # remove '#'
84             };
85             my $sub_schema = $self->schema;
86             {
87             eval { $sub_schema = $sub_schema->{$_} for @$paths };
88             croak sprintf 'referencing `%s` cause error', $ref if $@;
89             croak sprintf 'schema `%s` not found', $ref unless $sub_schema;
90             }
91             $self->ref_schema_cache($ref, $sub_schema); # caching
92             $sub_schema;
93             };
94             }
95              
96              
97             1;
98              
99             __END__