File Coverage

blib/lib/Smart/Args/TypeTiny/Check.pm
Criterion Covered Total %
statement 68 68 100.0
branch 34 36 94.4
condition 3 3 100.0
subroutine 11 11 100.0
pod 0 4 0.0
total 116 122 95.0


line stmt bran cond sub pod time code
1             package Smart::Args::TypeTiny::Check;
2 17     17   186166 use strict;
  17         39  
  17         410  
3 17     17   71 use warnings;
  17         26  
  17         305  
4 17     17   73 use Carp ();
  17         27  
  17         244  
5 17     17   66 use Scalar::Util qw/blessed/;
  17         27  
  17         875  
6 17     17   8326 use Type::Registry;
  17         139685  
  17         144  
7 17     17   10292 use Type::Utils;
  17         154798  
  17         143  
8              
9 17     17   21589 use Exporter 'import';
  17         34  
  17         7740  
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 6995 my ($rule, $value, $exists, $name) = @_;
18              
19 98 100       232 if (ref $rule eq 'HASH') {
20 39         108 my %check = map { ($_ => undef) } keys %$rule;
  58         149  
21 39         156 delete $check{$_} for qw/isa does optional default/;
22 39 100       100 if (%check) {
23 1         155 Carp::croak("Malformed rule for '$name' (isa, does, optional, default)");
24             }
25             } else {
26 59         132 $rule = {isa => $rule};
27             }
28              
29 97 100       169 if ($exists) {
30 79 100 100     210 return $value if !defined $value && $rule->{optional};
31             } else {
32 18 100       64 if (exists $rule->{default}) {
    100          
33 8         16 my $default = $rule->{default};
34 8 100       30 $value = ref $default eq 'CODE' ? scalar $default->() : $default;
35             } elsif (!$rule->{optional}) {
36 6         521 Carp::confess("Required parameter '$name' not passed");
37             } else {
38 4         16 return $value;
39             }
40             }
41              
42 84         115 my $type;
43 84 100       180 if (exists $rule->{isa}) {
    50          
44 82         165 $type = type($rule->{isa});
45             } elsif (exists $rule->{does}) {
46 2         10 $type = type_role($rule->{does});
47             }
48              
49 84         187 ($value, my $ok) = check_type($type, $value, $name);
50 84 100       2751 unless ($ok) {
51 20         88 Carp::confess("Type check failed in binding to parameter '\$$name'; " . $type->get_message($value));
52             }
53              
54 64         241 return $value;
55             }
56              
57             sub check_type {
58 88     88 0 2991 my ($type, $value) = @_;
59 88 100       446 return ($value, 1) unless $type;
60 87 100       600 return ($value, 1) if $type->check($value);
61              
62 23 100       347 if ($type->has_coercion) {
63 3         39 my $coerced_value = $type->coerce($value);
64 3 100       1528 if ($type->check($coerced_value)) {
65 2         30 return ($coerced_value, 1);
66             }
67             }
68              
69 21         426 return ($value, 0);
70             }
71              
72             sub type {
73 87     87 0 5590 my ($type_name) = @_;
74 87 100       329 return $type_name if blessed($type_name);
75 23 100       73 if (my $type = $reg->simple_lookup($type_name)) {
76 10         150 return $type;
77             } else {
78 13         218 my $type = Type::Utils::dwim_type(
79             $type_name,
80             fallback => ['lookup_via_mouse', 'make_class_type'],
81             );
82 13         94425 $type->{display_name} = $type_name;
83 13         66 $reg->add_type($type, $type_name);
84 13         263 return $type;
85             }
86             }
87              
88             sub type_role {
89 3     3 0 2015 my ($type_name) = @_;
90 3 50       16 return $type_name if blessed($type_name);
91 3 100       19 if (my $type = $reg->simple_lookup($type_name)) {
92 1         29 return $type;
93             } else {
94 2         50 my $type = Type::Utils::dwim_type(
95             $type_name,
96             fallback => ['make_role_type'],
97             );
98 2         5106 $type->{display_name} = $type_name;
99 2         17 $reg->add_type($type, $type_name);
100 2         49 return $type;
101             }
102             }
103              
104             1;