File Coverage

blib/lib/Smart/Args/TypeTiny/Check.pm
Criterion Covered Total %
statement 68 68 100.0
branch 35 36 97.2
condition 3 3 100.0
subroutine 11 11 100.0
pod 0 4 0.0
total 117 122 95.9


line stmt bran cond sub pod time code
1             package Smart::Args::TypeTiny::Check;
2 17     17   137128 use strict;
  17         40  
  17         449  
3 17     17   84 use warnings;
  17         31  
  17         365  
4 17     17   72 use Carp ();
  17         32  
  17         267  
5 17     17   76 use Scalar::Util qw/blessed/;
  17         33  
  17         805  
6 17     17   4732 use Type::Registry;
  17         125004  
  17         145  
7 17     17   7196 use Type::Utils;
  17         133173  
  17         144  
8              
9 17     17   22884 use Exporter 'import';
  17         53  
  17         8098  
10             our @EXPORT_OK = qw/check_rule check_type type type_role/;
11              
12             $Carp::CarpInternal{+__PACKAGE__}++;
13              
14             my $reg = Type::Registry->for_class(__PACKAGE__);
15              
16             sub check_rule {
17 98     98 0 5647 my ($rule, $value, $exists, $name) = @_;
18              
19 98 100       255 if (ref $rule eq 'HASH') {
20 39         132 my %check = map { ($_ => undef) } keys %$rule;
  58         156  
21 39         166 delete $check{$_} for qw/isa does optional default/;
22 39 100       115 if (%check) {
23 1         109 Carp::croak("Malformed rule for '$name' (isa, does, optional, default)");
24             }
25             } else {
26 59         156 $rule = {isa => $rule};
27             }
28              
29 97 100       191 if ($exists) {
30 79 100 100     223 return $value if !defined $value && $rule->{optional};
31             } else {
32 18 100       62 if (exists $rule->{default}) {
    100          
33 8         16 my $default = $rule->{default};
34 8 100       26 $value = ref $default eq 'CODE' ? scalar $default->() : $default;
35             } elsif (!$rule->{optional}) {
36 6         527 Carp::confess("Required parameter '$name' not passed");
37             } else {
38 4         16 return $value;
39             }
40             }
41              
42 84         122 my $type;
43 84 100       183 if (exists $rule->{isa}) {
    50          
44 82         194 $type = type($rule->{isa});
45             } elsif (exists $rule->{does}) {
46 2         8 $type = type_role($rule->{does});
47             }
48              
49 84         199 ($value, my $ok) = check_type($type, $value, $name);
50 84 100       2499 unless ($ok) {
51 20         96 Carp::confess("Type check failed in binding to parameter '\$$name'; " . $type->get_message($value));
52             }
53              
54 64         254 return $value;
55             }
56              
57             sub check_type {
58 88     88 0 2878 my ($type, $value) = @_;
59 88 100       537 return ($value, 1) unless $type;
60 87 100       618 return ($value, 1) if $type->check($value);
61              
62 23 100       303 if ($type->has_coercion) {
63 3         35 my $coerced_value = $type->coerce($value);
64 3 100       1526 if ($type->check($coerced_value)) {
65 2         26 return ($coerced_value, 1);
66             }
67             }
68              
69 21         431 return ($value, 0);
70             }
71              
72             sub type {
73 86     86 0 4803 my ($type_name) = @_;
74 86 100       339 return $type_name if blessed($type_name);
75 23 100       84 if (my $type = $reg->simple_lookup($type_name)) {
76 10         163 return $type;
77             } else {
78 13         230 my $type = Type::Utils::dwim_type(
79             $type_name,
80             fallback => ['lookup_via_mouse', 'make_class_type'],
81             );
82 13         89111 $type->{display_name} = $type_name;
83 13         56 $reg->add_type($type, $type_name);
84 13         247 return $type;
85             }
86             }
87              
88             sub type_role {
89 4     4 0 3168 my ($type_name) = @_;
90 4 100       20 return $type_name if blessed($type_name);
91 3 100       13 if (my $type = $reg->simple_lookup($type_name)) {
92 1         20 return $type;
93             } else {
94 2         42 my $type = Type::Utils::dwim_type(
95             $type_name,
96             fallback => ['make_role_type'],
97             );
98 2         3094 $type->{display_name} = $type_name;
99 2         10 $reg->add_type($type, $type_name);
100 2         44 return $type;
101             }
102             }
103              
104             1;