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 23     23   541 use 5.008001;
  23         95  
6 23     23   144 use strict;
  23         56  
  23         558  
7 23     23   139 use warnings;
  23         52  
  23         1114  
8              
9             BEGIN {
10 23     23   105 $Types::Standard::HashRef::AUTHORITY = 'cpan:TOBYINK';
11 23         991 $Types::Standard::HashRef::VERSION = '2.003_000';
12             }
13              
14             $Types::Standard::HashRef::VERSION =~ tr/_//d;
15              
16 23     23   196 use Type::Tiny ();
  23         71  
  23         497  
17 23     23   213 use Types::Standard ();
  23         55  
  23         401  
18 23     23   127 use Types::TypeTiny ();
  23         51  
  23         1459  
19              
20 3     3   52 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  3         16  
21              
22 23     23   149 no warnings;
  23         71  
  23         26719  
23              
24             sub __constraint_generator {
25 43 50   43   202 return Types::Standard::HashRef unless @_;
26            
27 43         102 my $param = shift;
28 43 100       948 Types::TypeTiny::is_TypeTiny( $param )
29             or _croak(
30             "Parameter to HashRef[`a] expected to be a type constraint; got $param" );
31            
32 40         178 my $param_compiled_check = $param->compiled_check;
33 40         124 my $xsub;
34 40         87 if ( Type::Tiny::_USE_XS ) {
35 40         161 my $paramname = Type::Tiny::XS::is_known( $param_compiled_check );
36 40 100       436 $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     367 $param->check( $_ ) || return for values %$hash;
49 99         290 return !!1;
50             },
51 40         1694 $xsub,
52             );
53             } #/ sub __constraint_generator
54              
55             sub __inline_generator {
56 40     40   113 my $param = shift;
57            
58 40         147 my $compiled = $param->compiled_check;
59 40         97 my $xsubname;
60 40 100       140 if ( Type::Tiny::_USE_XS and not $Type::Tiny::AvoidCallbacks ) {
61 37         117 my $paramname = Type::Tiny::XS::is_known( $compiled );
62 37         335 $xsubname = Type::Tiny::XS::get_subname_for( "HashRef[$paramname]" );
63             }
64            
65 40 100       609 return unless $param->can_be_inlined;
66             return sub {
67 318     318   582 my $v = $_[1];
68 318 100 100     1585 return "$xsubname\($v\)" if $xsubname && !$Type::Tiny::AvoidCallbacks;
69 118         341 my $p = Types::Standard::HashRef->inline_check( $v );
70 118         341 my $param_check = $param->inline_check( '$i' );
71            
72 118         570 "$p and do { "
73             . "my \$ok = 1; "
74             . "for my \$i (values \%{$v}) { "
75             . "(\$ok = 0, last) unless $param_check " . "}; " . "\$ok " . "}";
76 38         329 };
77             } #/ sub __inline_generator
78              
79             sub __deep_explanation {
80 2     2   9 require B;
81 2         10 my ( $type, $value, $varname ) = @_;
82 2         15 my $param = $type->parameters->[0];
83            
84 2         11 for my $k ( sort keys %$value ) {
85 4         7 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         22 $param->validate_explain(
  2         13  
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 29     29   98 my ( $parent, $child, $param ) = @_;
103 29 100       170 return unless $param->has_coercion;
104            
105 13         68 my $coercable_item = $param->coercion->_source_type_union;
106 13         82 my $C = "Type::Coercion"->new( type_constraint => $child );
107            
108 13 100 66     62 if ( $param->coercion->can_be_inlined and $coercable_item->can_be_inlined ) {
109             $C->add_type_coercions(
110             $parent => Types::Standard::Stringable {
111 7     7   34 my @code;
112 7         37 push @code, 'do { my ($orig, $return_orig, %new) = ($_, 0);';
113 7         17 push @code, 'for (keys %$orig) {';
114 7         41 push @code,
115             sprintf(
116             '$return_orig++ && last unless (%s);',
117             $coercable_item->inline_check( '$orig->{$_}' )
118             );
119 7         41 push @code,
120             sprintf(
121             '$new{$_} = (%s);',
122             $param->coercion->inline_coercion( '$orig->{$_}' )
123             );
124 7         31 push @code, '}';
125 7         18 push @code, '$return_orig ? $orig : \\%new';
126 7         25 push @code, '}';
127 7         107 "@code";
128             }
129 7         136 );
130             } #/ if ( $param->coercion->...)
131             else {
132             $C->add_type_coercions(
133             $parent => sub {
134 12 50   12   4052 my $value = @_ ? $_[0] : $_;
135 12         25 my %new;
136 12         35 for my $k ( keys %$value ) {
137 34 100       409 return $value unless $coercable_item->check( $value->{$k} );
138 33         341 $new{$k} = $param->coerce( $value->{$k} );
139             }
140 11         174 return \%new;
141             },
142 6         55 );
143             } #/ else [ if ( $param->coercion->...)]
144            
145 13         53 return $C;
146             } #/ sub __coercion_generator
147              
148             sub __hashref_allows_key {
149 19     19   37 my $self = shift;
150 19         143 Types::Standard::is_Str( $_[0] );
151             }
152              
153             sub __hashref_allows_value {
154 6     6   12 my $self = shift;
155 6         15 my ( $key, $value ) = @_;
156            
157 6 100       32 return !!0 unless $self->my_hashref_allows_key( $key );
158 5 100       29 return !!1 if $self == Types::Standard::HashRef();
159            
160             my $href = $self->find_parent(
161 3 50   3   24 sub { $_->has_parent && $_->parent == Types::Standard::HashRef() } );
  3         10  
162 3         20 my $param = $href->type_parameter;
163            
164 3 50       21 Types::Standard::is_Str( $key ) and $param->check( $value );
165             } #/ sub __hashref_allows_value
166              
167             1;