File Coverage

lib/Types/Standard/HashRef.pm
Criterion Covered Total %
statement 90 91 100.0
branch 26 30 86.6
condition 7 8 87.5
subroutine 20 20 100.0
pod n/a
total 143 149 96.6


line stmt bran cond sub pod time code
1             # INTERNAL MODULE: guts for HashRef type from Types::Standard.
2              
3             package Types::Standard::HashRef;
4              
5 20     20   441 use 5.008001;
  20         70  
6 20     20   110 use strict;
  20         65  
  20         435  
7 20     20   96 use warnings;
  20         42  
  20         963  
8              
9             BEGIN {
10 20     20   80 $Types::Standard::HashRef::AUTHORITY = 'cpan:TOBYINK';
11 20         747 $Types::Standard::HashRef::VERSION = '2.004000';
12             }
13              
14             $Types::Standard::HashRef::VERSION =~ tr/_//d;
15              
16 20     20   128 use Type::Tiny ();
  20         45  
  20         409  
17 20     20   106 use Types::Standard ();
  20         44  
  20         378  
18 20     20   116 use Types::TypeTiny ();
  20         41  
  20         1173  
19              
20 3     3   65 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  3         21  
21              
22 20     20   121 no warnings;
  20         42  
  20         22070  
23              
24             sub __constraint_generator {
25 39 50   39   189 return Types::Standard::HashRef unless @_;
26            
27 39         91 my $param = shift;
28 39 100       803 Types::TypeTiny::is_TypeTiny( $param )
29             or _croak(
30             "Parameter to HashRef[`a] expected to be a type constraint; got $param" );
31            
32 36         147 my $param_compiled_check = $param->compiled_check;
33 36         82 my $xsub;
34 36         70 if ( Type::Tiny::_USE_XS ) {
35 36         138 my $paramname = Type::Tiny::XS::is_known( $param_compiled_check );
36 36 100       413 $xsub = Type::Tiny::XS::get_coderef_for( "HashRef[$paramname]" )
37             if $paramname;
38             }
39             elsif ( Type::Tiny::_USE_MOUSE and $param->_has_xsub ) {
40             require Mouse::Util::TypeConstraints;
41             my $maker = "Mouse::Util::TypeConstraints"->can( "_parameterize_HashRef_for" );
42             $xsub = $maker->( $param ) if $maker;
43             }
44            
45             return (
46             sub {
47 116     116   185 my $hash = shift;
48 116   100     348 $param->check( $_ ) || return for values %$hash;
49 99         301 return !!1;
50             },
51 36         1413 $xsub,
52             );
53             } #/ sub __constraint_generator
54              
55             sub __inline_generator {
56 36     36   80 my $param = shift;
57            
58 36         112 my $compiled = $param->compiled_check;
59 36         75 my $xsubname;
60 36 100       125 if ( Type::Tiny::_USE_XS and not $Type::Tiny::AvoidCallbacks ) {
61 33         113 my $paramname = Type::Tiny::XS::is_known( $compiled );
62 33         296 $xsubname = Type::Tiny::XS::get_subname_for( "HashRef[$paramname]" );
63             }
64            
65 36 100       518 return unless $param->can_be_inlined;
66             return sub {
67 299     299   561 my $v = $_[1];
68 299 100 100     1451 return "$xsubname\($v\)" if $xsubname && !$Type::Tiny::AvoidCallbacks;
69 118         312 my $p = Types::Standard::HashRef->inline_check( $v );
70 118         316 my $param_check = $param->inline_check( '$i' );
71            
72 118         564 "$p and do { "
73             . "my \$ok = 1; "
74             . "for my \$i (values \%{$v}) { "
75             . "(\$ok = 0, last) unless $param_check " . "}; " . "\$ok " . "}";
76 34         239 };
77             } #/ sub __inline_generator
78              
79             sub __deep_explanation {
80 2     2   12 require B;
81 2         7 my ( $type, $value, $varname ) = @_;
82 2         17 my $param = $type->parameters->[0];
83            
84 2         11 for my $k ( sort keys %$value ) {
85 4         8 my $item = $value->{$k};
86 4 100       10 next if $param->check( $item );
87             return [
88             sprintf( '"%s" constrains each value in the hash with "%s"', $type, $param ),
89             @{
90 2         32 $param->validate_explain(
  2         27  
91             $item, sprintf( '%s->{%s}', $varname, B::perlstring( $k ) )
92             )
93             },
94             ];
95             } #/ for my $k ( sort keys %$value)
96            
97             # This should never happen...
98 0         0 return; # uncoverable statement
99             } #/ sub __deep_explanation
100              
101             sub __coercion_generator {
102 26     26   87 my ( $parent, $child, $param ) = @_;
103 26 100       98 return unless $param->has_coercion;
104            
105 12         54 my $coercable_item = $param->coercion->_source_type_union;
106 12         86 my $C = "Type::Coercion"->new( type_constraint => $child );
107            
108 12 100 66     43 if ( $param->coercion->can_be_inlined and $coercable_item->can_be_inlined ) {
109             $C->add_type_coercions(
110             $parent => Types::Standard::Stringable {
111 6     6   15 my @code;
112 6         15 push @code, 'do { my ($orig, $return_orig, %new) = ($_, 0);';
113 6         28 push @code, 'for (keys %$orig) {';
114 6         31 push @code,
115             sprintf(
116             '$return_orig++ && last unless (%s);',
117             $coercable_item->inline_check( '$orig->{$_}' )
118             );
119 6         26 push @code,
120             sprintf(
121             '$new{$_} = (%s);',
122             $param->coercion->inline_coercion( '$orig->{$_}' )
123             );
124 6         30 push @code, '}';
125 6         19 push @code, '$return_orig ? $orig : \\%new';
126 6         17 push @code, '}';
127 6         96 "@code";
128             }
129 6         82 );
130             } #/ if ( $param->coercion->...)
131             else {
132             $C->add_type_coercions(
133             $parent => sub {
134 12 50   12   4204 my $value = @_ ? $_[0] : $_;
135 12         27 my %new;
136 12         44 for my $k ( keys %$value ) {
137 33 100       377 return $value unless $coercable_item->check( $value->{$k} );
138 32         331 $new{$k} = $param->coerce( $value->{$k} );
139             }
140 11         169 return \%new;
141             },
142 6         53 );
143             } #/ else [ if ( $param->coercion->...)]
144            
145 12         48 return $C;
146             } #/ sub __coercion_generator
147              
148             sub __hashref_allows_key {
149 19     19   34 my $self = shift;
150 19         178 Types::Standard::is_Str( $_[0] );
151             }
152              
153             sub __hashref_allows_value {
154 6     6   13 my $self = shift;
155 6         15 my ( $key, $value ) = @_;
156            
157 6 100       33 return !!0 unless $self->my_hashref_allows_key( $key );
158 5 100       18 return !!1 if $self == Types::Standard::HashRef();
159            
160             my $href = $self->find_parent(
161 3 50   3   37 sub { $_->has_parent && $_->parent == Types::Standard::HashRef() } );
  3         11  
162 3         29 my $param = $href->type_parameter;
163            
164 3 50       25 Types::Standard::is_Str( $key ) and $param->check( $value );
165             } #/ sub __hashref_allows_value
166              
167             1;