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   461 use 5.008001;
  20         81  
6 20     20   132 use strict;
  20         49  
  20         741  
7 20     20   106 use warnings;
  20         42  
  20         1044  
8              
9             BEGIN {
10 20     20   88 $Types::Standard::HashRef::AUTHORITY = 'cpan:TOBYINK';
11 20         846 $Types::Standard::HashRef::VERSION = '2.002001';
12             }
13              
14             $Types::Standard::HashRef::VERSION =~ tr/_//d;
15              
16 20     20   147 use Type::Tiny ();
  20         54  
  20         419  
17 20     20   125 use Types::Standard ();
  20         49  
  20         376  
18 20     20   108 use Types::TypeTiny ();
  20         44  
  20         1245  
19              
20 3     3   711 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  3         48  
21              
22 20     20   137 no warnings;
  20         39  
  20         24016  
23              
24             sub __constraint_generator {
25 39 50   39   181 return Types::Standard::HashRef unless @_;
26            
27 39         92 my $param = shift;
28 39 100       834 Types::TypeTiny::is_TypeTiny( $param )
29             or _croak(
30             "Parameter to HashRef[`a] expected to be a type constraint; got $param" );
31            
32 36         148 my $param_compiled_check = $param->compiled_check;
33 36         76 my $xsub;
34 36         71 if ( Type::Tiny::_USE_XS ) {
35 36         136 my $paramname = Type::Tiny::XS::is_known( $param_compiled_check );
36 36 100       601 $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   194 my $hash = shift;
48 116   100     339 $param->check( $_ ) || return for values %$hash;
49 99         342 return !!1;
50             },
51 36         1569 $xsub,
52             );
53             } #/ sub __constraint_generator
54              
55             sub __inline_generator {
56 36     36   90 my $param = shift;
57            
58 36         113 my $compiled = $param->compiled_check;
59 36         80 my $xsubname;
60 36 100       118 if ( Type::Tiny::_USE_XS and not $Type::Tiny::AvoidCallbacks ) {
61 33         138 my $paramname = Type::Tiny::XS::is_known( $compiled );
62 33         295 $xsubname = Type::Tiny::XS::get_subname_for( "HashRef[$paramname]" );
63             }
64            
65 36 100       499 return unless $param->can_be_inlined;
66             return sub {
67 283     283   519 my $v = $_[1];
68 283 100 100     1373 return "$xsubname\($v\)" if $xsubname && !$Type::Tiny::AvoidCallbacks;
69 102         304 my $p = Types::Standard::HashRef->inline_check( $v );
70 102         299 my $param_check = $param->inline_check( '$i' );
71            
72 102         573 "$p and do { "
73             . "my \$ok = 1; "
74             . "for my \$i (values \%{$v}) { "
75             . "(\$ok = 0, last) unless $param_check " . "}; " . "\$ok " . "}";
76 34         233 };
77             } #/ sub __inline_generator
78              
79             sub __deep_explanation {
80 2     2   19 require B;
81 2         7 my ( $type, $value, $varname ) = @_;
82 2         9 my $param = $type->parameters->[0];
83            
84 2         12 for my $k ( sort keys %$value ) {
85 4         9 my $item = $value->{$k};
86 4 100       9 next if $param->check( $item );
87             return [
88             sprintf( '"%s" constrains each value in the hash with "%s"', $type, $param ),
89             @{
90 2         12 $param->validate_explain(
  2         18  
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   81 my ( $parent, $child, $param ) = @_;
103 26 100       95 return unless $param->has_coercion;
104            
105 12         53 my $coercable_item = $param->coercion->_source_type_union;
106 12         56 my $C = "Type::Coercion"->new( type_constraint => $child );
107            
108 12 100 66     52 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   21 my @code;
112 6         19 push @code, 'do { my ($orig, $return_orig, %new) = ($_, 0);';
113 6         14 push @code, 'for (keys %$orig) {';
114 6         32 push @code,
115             sprintf(
116             '$return_orig++ && last unless (%s);',
117             $coercable_item->inline_check( '$orig->{$_}' )
118             );
119 6         35 push @code,
120             sprintf(
121             '$new{$_} = (%s);',
122             $param->coercion->inline_coercion( '$orig->{$_}' )
123             );
124 6         23 push @code, '}';
125 6         15 push @code, '$return_orig ? $orig : \\%new';
126 6         17 push @code, '}';
127 6         83 "@code";
128             }
129 6         56 );
130             } #/ if ( $param->coercion->...)
131             else {
132             $C->add_type_coercions(
133             $parent => sub {
134 12 50   12   4211 my $value = @_ ? $_[0] : $_;
135 12         29 my %new;
136 12         44 for my $k ( keys %$value ) {
137 32 100       361 return $value unless $coercable_item->check( $value->{$k} );
138 31         328 $new{$k} = $param->coerce( $value->{$k} );
139             }
140 11         189 return \%new;
141             },
142 6         50 );
143             } #/ else [ if ( $param->coercion->...)]
144            
145 12         53 return $C;
146             } #/ sub __coercion_generator
147              
148             sub __hashref_allows_key {
149 19     19   32 my $self = shift;
150 19         126 Types::Standard::is_Str( $_[0] );
151             }
152              
153             sub __hashref_allows_value {
154 6     6   14 my $self = shift;
155 6         15 my ( $key, $value ) = @_;
156            
157 6 100       35 return !!0 unless $self->my_hashref_allows_key( $key );
158 5 100       23 return !!1 if $self == Types::Standard::HashRef();
159            
160             my $href = $self->find_parent(
161 3 50   3   30 sub { $_->has_parent && $_->parent == Types::Standard::HashRef() } );
  3         11  
162 3         19 my $param = $href->type_parameter;
163            
164 3 50       20 Types::Standard::is_Str( $key ) and $param->check( $value );
165             } #/ sub __hashref_allows_value
166              
167             1;