File Coverage

blib/lib/Smart/Args/TypeTiny/Check.pm
Criterion Covered Total %
statement 66 67 98.5
branch 33 34 97.0
condition 3 3 100.0
subroutine 11 11 100.0
pod 0 4 0.0
total 113 119 94.9


line stmt bran cond sub pod time code
1             package Smart::Args::TypeTiny::Check;
2 17     17   192114 use strict;
  17         40  
  17         471  
3 17     17   83 use warnings;
  17         37  
  17         441  
4 17     17   86 use Carp ();
  17         34  
  17         317  
5 17     17   92 use Scalar::Util qw/blessed/;
  17         36  
  17         881  
6 17     17   7989 use Type::Registry;
  17         151823  
  17         178  
7 17     17   8915 use Type::Utils;
  17         186519  
  17         160  
8              
9 17     17   42004 use Exporter 'import';
  17         45  
  17         8890  
10             our @EXPORT_OK = qw/check_rule check_type/;
11              
12             $Carp::CarpInternal{+__PACKAGE__}++;
13              
14             my $reg = Type::Registry->for_class(__PACKAGE__);
15              
16             sub check_rule {
17 95     95 0 4373 my ($rule, $value, $exists, $name) = @_;
18              
19 95         271 $rule = parameter_rule($rule, $name);
20              
21 95         270 my $type = rule_to_type($rule);
22 95 100       252 if ($exists) {
23 77 100 100     256 return $value if !defined $value && $rule->{optional};
24 75         241 return check_type($type, $value, $name);
25             } else {
26 18 100       72 if (exists $rule->{default}) {
    100          
27 8         16 my $default = $rule->{default};
28 8 100       34 return check_type($type, ref $default eq 'CODE' ? scalar $default->() : $default, $name);
29             } elsif (!$rule->{optional}) {
30 6         533 Carp::confess("Required parameter '$name' not passed");
31             }
32             }
33 4         20 return $value;
34             }
35              
36             sub check_type {
37 87     87 0 3842 my ($type, $value, $name) = @_;
38 87 100       679 return $value unless $type;
39 86 100       774 return $value if $type->check($value);
40              
41 22 100       407 if ($type->has_coercion) {
42 3         70 $value = $type->coerce($value);
43 3 100       2778 if ($type->check($value)) {
44 2         48 return $value;
45             }
46             }
47              
48 20         636 Carp::confess("Type check failed in binding to parameter '\$$name'; " . $type->get_message($value));
49             }
50              
51             sub parameter_rule {
52 106     106 0 17310 my ($rule, $name) = @_;
53              
54 106 100       480 return {isa => $rule} unless ref $rule eq 'HASH';
55              
56 46         166 my %check = map { ($_ => undef) } keys %$rule;
  64         208  
57 46         220 delete $check{$_} for qw/isa does optional default/;
58              
59 46 100       125 if (%check) {
60 1         149 Carp::croak("Malformed rule for '$name' (isa, does, optional, default)");
61             }
62              
63 45         137 return $rule;
64             }
65              
66             sub rule_to_type {
67 100     100 0 8304 my ($rule) = @_;
68              
69 100 100       277 if (exists $rule->{isa}) {
    50          
70 96         213 my $isa = $rule->{isa};
71 96 100       446 return $isa if blessed($isa);
72 23 100       121 if (my $type = $reg->simple_lookup($isa)) {
73 10         268 return $type;
74             } else {
75 13         331 my $type = Type::Utils::dwim_type(
76             $isa,
77             fallback => ['lookup_via_mouse', 'make_class_type'],
78             );
79 13         155868 $type->{display_name} = $isa;
80 13         81 $reg->add_type($type, $isa);
81 13         479 return $type;
82             }
83             } elsif (exists $rule->{does}) {
84 4         11 my $does = $rule->{does};
85 4 100       18 return $does if blessed($does);
86 3 100       18 if (my $type = $reg->simple_lookup($does)) {
87 1         22 return $type;
88             } else {
89 2         50 my $type = Type::Utils::dwim_type(
90             $does,
91             fallback => ['make_role_type'],
92             );
93 2         2117 $type->{display_name} = $does;
94 2         11 $reg->add_type($type, $does);
95 2         46 return $type;
96             }
97             }
98 0           return undef;
99             }
100              
101             1;