File Coverage

blib/lib/Coat/Meta/TypeConstraint.pm
Criterion Covered Total %
statement 40 40 100.0
branch 13 14 92.8
condition 7 12 58.3
subroutine 13 13 100.0
pod 4 10 40.0
total 77 89 86.5


line stmt bran cond sub pod time code
1             package Coat::Meta::TypeConstraint;
2              
3 44     44   249 use strict;
  44         77  
  44         3147  
4 44     44   229 use warnings;
  44         80  
  44         1165  
5 44     44   247 use Carp 'confess';
  44         113  
  44         51352  
6              
7             sub new {
8 937     937 1 7858 my ($class, %values) = @_;
9 937         9911 my $self = { %values };
10 937         4991 return bless $self, $class;
11             }
12              
13             # accessors
14 1877   33 1877 0 9153 sub name { $_[0]->{name} ||= $_[1] }
15 873   66 873 0 25977 sub validation { $_[0]->{validation} ||= $_[1] }
16 65   66 65 0 528 sub message { $_[0]->{message} ||= $_[1] }
17 1454   66 1454 0 8631 sub parent { $_[0]->{parent} ||= $_[1] }
18              
19             sub coercion_map {
20 25     25 0 38 my ($self, $map) = @_;
21 25 100       70 if (@_ == 1) {
22 20         117 return $self->{coercion_map};
23             }
24             else {
25 5         22 return $self->{coercion_map} = $map;
26             }
27             }
28              
29             # coerce the given value with the first matching type
30             sub coerce {
31 7     7 1 15 my ($self, $value) = @_;
32              
33             # for each source registered, try coercion if the source is a valid type
34 7         11 local $_ = $value;
35 7         10 foreach my $source (keys %{ $self->coercion_map }) {
  7         18  
36             # if current value passes the current source check, coercing
37 8         30 my $tc = Coat::Types::find_type_constraint($source);
38 8 100       24 return $self->{coercion_map}{$source}->($value)
39             if $tc->silent_validate($value);
40             }
41 2         17 return $value;
42             }
43              
44             # check the value through the type constraints
45             sub silent_validate {
46 832     832 0 1069 my ($self, $value) = @_;
47 832         1018 local $_ = $value;
48              
49             # validates the parent's type-constraint if exists
50 832 100       1376 if (defined $self->parent) {
51 621 100       1970 Coat::Types::find_type_constraint( $self->parent )->silent_validate( $value )
52             or return 0;
53             }
54 814         1810 return $self->validation->($value);
55             }
56              
57             sub validate {
58 203     203 1 382 my ($self, $value) = @_;
59 203 100       469 unless ($self->silent_validate($value)) {
60 40         108 local $_ = $value;
61 40 50       107 my $msg = (defined $self->message)
    100          
62             ? $self->message->()
63             : "Value '" .(defined $value ? $value : 'undef')
64             ."' does not validate type constraint '".$self->name."'";
65 40         8222 confess $msg;
66             }
67 163         467 return 1;
68             }
69              
70             sub has_coercion {
71 12     12 1 25 my ($self) = @_;
72 12         35 return defined $self->coercion_map;
73             }
74              
75             1;
76             __END__