File Coverage

lib/Types/Standard/ArrayRef.pm
Criterion Covered Total %
statement 109 119 92.4
branch 53 64 82.8
condition 21 38 55.2
subroutine 19 20 95.0
pod n/a
total 202 241 84.2


line stmt bran cond sub pod time code
1             # INTERNAL MODULE: guts for ArrayRef type from Types::Standard.
2              
3             package Types::Standard::ArrayRef;
4              
5 89     89   2080 use 5.008001;
  89         367  
6 89     89   531 use strict;
  89         242  
  89         2014  
7 89     89   467 use warnings;
  89         203  
  89         4286  
8              
9             BEGIN {
10 89     89   358 $Types::Standard::ArrayRef::AUTHORITY = 'cpan:TOBYINK';
11 89         3133 $Types::Standard::ArrayRef::VERSION = '2.003_000';
12             }
13              
14             $Types::Standard::ArrayRef::VERSION =~ tr/_//d;
15              
16 89     89   612 use Type::Tiny ();
  89         224  
  89         1686  
17 89     89   520 use Types::Standard ();
  89         227  
  89         1584  
18 89     89   515 use Types::TypeTiny ();
  89         246  
  89         5232  
19              
20 2     2   44 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  2         14  
21              
22 89     89   573 no warnings;
  89         233  
  89         117303  
23              
24             sub __constraint_generator {
25 204 100   204   889 return Types::Standard::ArrayRef unless @_;
26            
27 202         480 my $param = shift;
28 202 100       4557 Types::TypeTiny::is_TypeTiny( $param )
29             or _croak(
30             "Parameter to ArrayRef[`a] expected to be a type constraint; got $param" );
31            
32 200         853 my ( $min, $max ) = ( 0, -1 );
33 200 100       752 $min = Types::Standard::assert_Int( shift ) if @_;
34 200 100       827 $max = Types::Standard::assert_Int( shift ) if @_;
35            
36 200         757 my $param_compiled_check = $param->compiled_check;
37 200         466 my $xsub;
38 200 100 66     1357 if ( Type::Tiny::_USE_XS and $min == 0 and $max == -1 ) {
    50 33        
      33        
      0        
39 192         845 my $paramname = Type::Tiny::XS::is_known( $param_compiled_check );
40 192 100       2408 $xsub = Type::Tiny::XS::get_coderef_for( "ArrayRef[$paramname]" )
41             if $paramname;
42             }
43             elsif ( Type::Tiny::_USE_MOUSE
44             and $param->_has_xsub
45             and $min == 0
46             and $max == -1 )
47             {
48 0         0 require Mouse::Util::TypeConstraints;
49 0         0 my $maker = "Mouse::Util::TypeConstraints"->can( "_parameterize_ArrayRef_for" );
50 0 0       0 $xsub = $maker->( $param ) if $maker;
51             }
52            
53             return (
54             sub {
55 294     294   558 my $array = shift;
56 294   100     930 $param->check( $_ ) || return for @$array;
57 203         627 return !!1;
58             },
59 200 100 66     11176 $xsub,
60             ) if $min == 0 and $max == -1;
61            
62             return sub {
63 22     22   44 my $array = shift;
64 22 100       100 return if @$array < $min;
65 12   100     46 $param->check( $_ ) || return for @$array;
66 9         26 return !!1;
67             }
68 8 100       49 if $max == -1;
69            
70             return sub {
71 0     0   0 my $array = shift;
72 0 0       0 return if @$array > $max;
73 0   0     0 $param->check( $_ ) || return for @$array;
74 0         0 return !!1;
75             }
76 4 50       11 if $min == 0;
77            
78             return sub {
79 10     10   17 my $array = shift;
80 10 100       38 return if @$array < $min;
81 8 100       33 return if @$array > $max;
82 5   100     14 $param->check( $_ ) || return for @$array;
83 3         9 return !!1;
84 4         29 };
85             } #/ sub __constraint_generator
86              
87             sub __inline_generator {
88 200     200   570 my $param = shift;
89 200         547 my ( $min, $max ) = ( 0, -1 );
90 200 100       675 $min = shift if @_;
91 200 100       740 $max = shift if @_;
92            
93 200         667 my $param_compiled_check = $param->compiled_check;
94 200         422 my $xsubname;
95 200 100 66     1160 if ( Type::Tiny::_USE_XS and $min == 0 and $max == -1 ) {
96 192         681 my $paramname = Type::Tiny::XS::is_known( $param_compiled_check );
97 192         1951 $xsubname = Type::Tiny::XS::get_subname_for( "ArrayRef[$paramname]" );
98             }
99            
100 200 100       3003 return unless $param->can_be_inlined;
101            
102             return sub {
103 1312     1312   2397 my $v = $_[1];
104 1312 100 100     6103 return "$xsubname\($v\)" if $xsubname && !$Type::Tiny::AvoidCallbacks;
105 431         1217 my $p = Types::Standard::ArrayRef->inline_check( $v );
106            
107 431 100       1189 if ( $min != 0 ) {
108 88         359 $p .= sprintf( ' and @{%s} >= %d', $v, $min );
109             }
110 431 100       968 if ( $max > 0 ) {
111 36         79 $p .= sprintf( ' and @{%s} <= %d', $v, $max );
112             }
113            
114 431         1138 my $param_check = $param->inline_check( '$i' );
115 431 100       1734 return $p if $param->{uniq} eq Types::Standard::Any->{uniq};
116            
117 427         3612 "$p and do { "
118             . "my \$ok = 1; "
119             . "for my \$i (\@{$v}) { "
120             . "(\$ok = 0, last) unless $param_check " . "}; " . "\$ok " . "}";
121 184         1868 };
122             } #/ sub __inline_generator
123              
124             sub __deep_explanation {
125 2     2   11 my ( $type, $value, $varname ) = @_;
126 2         7 my $param = $type->parameters->[0];
127 2         6 my ( $min, $max ) = ( 0, -1 );
128 2 50       5 $min = $type->parameters->[1] if @{ $type->parameters } > 1;
  2         6  
129 2 50       7 $max = $type->parameters->[2] if @{ $type->parameters } > 2;
  2         6  
130            
131 2 50 33     9 if ( $min != 0 and @$value < $min ) {
132             return [
133 0         0 sprintf( '"%s" constrains array length at least %s', $type, $min ),
134             sprintf( '@{%s} is %d', $varname, scalar @$value ),
135             ];
136             }
137            
138 2 50 33     70 if ( $max > 0 and @$value > $max ) {
139             return [
140 0         0 sprintf( '"%s" constrains array length at most %d', $type, $max ),
141             sprintf( '@{%s} is %d', $varname, scalar @$value ),
142             ];
143             }
144            
145 2         21 for my $i ( 0 .. $#$value ) {
146 5         10 my $item = $value->[$i];
147 5 100       13 next if $param->check( $item );
148             return [
149             sprintf( '"%s" constrains each value in the array with "%s"', $type, $param ),
150 2         12 @{ $param->validate_explain( $item, sprintf( '%s->[%d]', $varname, $i ) ) },
  2         15  
151             ];
152             }
153            
154             # This should never happen...
155 0         0 return; # uncoverable statement
156             } #/ sub __deep_explanation
157              
158             # XXX: min and max need to be handled by coercion?
159             sub __coercion_generator {
160 101     101   378 my ( $parent, $child, $param ) = @_;
161 101 100       386 return unless $param->has_coercion;
162            
163 29         196 my $coercable_item = $param->coercion->_source_type_union;
164 29         204 my $C = "Type::Coercion"->new( type_constraint => $child );
165            
166 29 100 66     152 if ( $param->coercion->can_be_inlined and $coercable_item->can_be_inlined ) {
167             $C->add_type_coercions(
168             $parent => Types::Standard::Stringable {
169 14     14   32 my @code;
170 14         41 push @code, 'do { my ($orig, $return_orig, @new) = ($_, 0);';
171 14         44 push @code, 'for (@$orig) {';
172 14         90 push @code,
173             sprintf(
174             '++$return_orig && last unless (%s);',
175             $coercable_item->inline_check( '$_' )
176             );
177 14         90 push @code,
178             sprintf(
179             'push @new, (%s);',
180             $param->coercion->inline_coercion( '$_' )
181             );
182 14         59 push @code, '}';
183 14         56 push @code, '$return_orig ? $orig : \\@new';
184 14         48 push @code, '}';
185 14         169 "@code";
186             }
187 14         154 );
188             } #/ if ( $param->coercion->...)
189             else {
190             $C->add_type_coercions(
191             $parent => sub {
192 74 50   74   60942 my $value = @_ ? $_[0] : $_;
193 74         521 my @new;
194 74         177 for my $item ( @$value ) {
195 287 100       2149 return $value unless $coercable_item->check( $item );
196 285         2128 push @new, $param->coerce( $item );
197             }
198 72         1256 return \@new;
199             },
200 15         161 );
201             } #/ else [ if ( $param->coercion->...)]
202            
203 29         129 return $C;
204             } #/ sub __coercion_generator
205              
206             1;