File Coverage

blib/lib/Data/Sah/Util/Type.pm
Criterion Covered Total %
statement 59 64 92.1
branch 27 40 67.5
condition 24 37 64.8
subroutine 13 15 86.6
pod 6 6 100.0
total 129 162 79.6


line stmt bran cond sub pod time code
1             package Data::Sah::Util::Type;
2              
3             our $DATE = '2016-07-19'; # DATE
4             our $VERSION = '0.44'; # VERSION
5              
6 1     1   462 use 5.010001;
  1         2  
7 1     1   3 use strict;
  1         1  
  1         13  
8 1     1   3 use warnings;
  1         1  
  1         584  
9              
10             require Exporter;
11             our @ISA = qw(Exporter);
12             our @EXPORT_OK = qw(get_type is_type is_simple is_numeric is_collection is_ref);
13              
14             # XXX absorb and use metadata from Data::Sah::Type::*
15             my $type_metas = {
16             all => {scalar=>0, numeric=>0, ref=>0},
17             any => {scalar=>0, numeric=>0, ref=>0},
18             array => {scalar=>0, numeric=>0, ref=>1},
19             bool => {scalar=>1, numeric=>0, ref=>0},
20             buf => {scalar=>1, numeric=>0, ref=>0},
21             cistr => {scalar=>1, numeric=>0, ref=>0},
22             code => {scalar=>1, numeric=>0, ref=>1},
23             float => {scalar=>1, numeric=>1, ref=>0},
24             hash => {scalar=>0, numeric=>0, ref=>1},
25             int => {scalar=>1, numeric=>1, ref=>0},
26             num => {scalar=>1, numeric=>1, ref=>0},
27             obj => {scalar=>1, numeric=>0, ref=>1},
28             re => {scalar=>1, numeric=>0, ref=>1, simple=>1},
29             str => {scalar=>1, numeric=>0, ref=>0},
30             undef => {scalar=>1, numeric=>0, ref=>0},
31             date => {scalar=>1, numeric=>0, ref=>0},
32             duration => {scalar=>1, numeric=>0, ref=>0},
33             };
34              
35             sub get_type {
36 82     82 1 62 my $sch = shift;
37              
38 82 100       125 if (ref($sch) eq 'ARRAY') {
39 24         25 $sch = $sch->[0];
40             }
41              
42 82 50 33     216 if (defined($sch) && !ref($sch)) {
43 82         103 $sch =~ s/\*\z//;
44 82         151 return $sch;
45             } else {
46 0         0 return undef;
47             }
48             }
49              
50             sub _normalize {
51 24     24   603 require Data::Sah::Normalize;
52              
53 24         1183 my ($sch, $opts) = @_;
54 24 50       32 return $sch if $opts->{schema_is_normalized};
55 24         46 return Data::Sah::Normalize::normalize_schema($sch);
56             }
57              
58             # for any|all to pass a criteria, we assume that all of the schemas in the 'of'
59             # clause must also pass (and there must not be '!of', 'of&', or that kind of
60             # thing.
61             sub _handle_any_all {
62 24     24   23 my ($sch, $opts, $crit) = @_;
63 24         26 $sch = _normalize($sch, $opts);
64 24 100       963 return 0 if $sch->[1]{'of.op'};
65 16         15 my $of = $sch->[1]{of};
66 16 100 66     97 return 0 unless $of && ref($of) eq 'ARRAY' && @$of;
      100        
67 8         11 for (@$of) {
68 14 100       15 return 0 unless $crit->($_);
69             }
70 4         13 1;
71             }
72              
73             sub is_type {
74 3     3 1 493 my ($sch, $opts) = @_;
75 3   50     12 $opts //= {};
76              
77 3 50       7 my $type = get_type($sch) or return undef;
78 3 100       10 my $tmeta = $type_metas->{$type} or return undef;
79 2         8 1;
80             }
81              
82             sub is_simple {
83 33     33 1 850 my ($sch, $opts) = @_;
84 33   50     102 $opts //= {};
85              
86 33 50       36 my $type = get_type($sch) or return undef;
87 33 50       62 my $tmeta = $type_metas->{$type} or return undef;
88 33 100 100     87 if ($type eq 'any' || $type eq 'all') {
89 12     8   37 return _handle_any_all($sch, $opts, sub { is_simple(shift) });
  8         10  
90             }
91 21   100     117 return $tmeta->{simple} // ($tmeta->{scalar} && !$tmeta->{ref});
      66        
92             }
93              
94             sub is_collection {
95 31     31 1 891 my ($sch, $opts) = @_;
96 31   50     94 $opts //= {};
97              
98 31 50       36 my $type = get_type($sch) or return undef;
99 31 50       56 my $tmeta = $type_metas->{$type} or return undef;
100 31 100 100     73 if ($type eq 'any' || $type eq 'all') {
101 12     6   35 return _handle_any_all($sch, $opts, sub { is_collection(shift) });
  6         10  
102             }
103 19         67 return !$tmeta->{scalar};
104             }
105              
106             sub is_numeric {
107 9     9 1 772 my ($sch, $opts) = @_;
108 9   50     30 $opts //= {};
109              
110 9 50       11 my $type = get_type($sch) or return undef;
111 9 50       17 my $tmeta = $type_metas->{$type} or return undef;
112 9 50 33     24 if ($type eq 'any' || $type eq 'all') {
113 0     0   0 return _handle_any_all($sch, $opts, sub { is_numeric(shift) });
  0         0  
114             }
115 9         28 return $tmeta->{numeric};
116             }
117              
118             sub is_ref {
119 6     6 1 747 my ($sch, $opts) = @_;
120 6   50     22 $opts //= {};
121              
122 6 50       8 my $type = get_type($sch) or return undef;
123 6 50       11 my $tmeta = $type_metas->{$type} or return undef;
124 6 50 33     21 if ($type eq 'any' || $type eq 'all') {
125 0     0   0 return _handle_any_all($sch, $opts, sub { is_ref(shift) });
  0         0  
126             }
127 6         17 return $tmeta->{ref};
128             }
129              
130             1;
131             # ABSTRACT: Utility functions related to types
132              
133             __END__