File Coverage

lib/Types/Standard/ScalarRef.pm
Criterion Covered Total %
statement 79 80 100.0
branch 25 32 78.1
condition 4 9 44.4
subroutine 18 18 100.0
pod n/a
total 126 139 91.3


line stmt bran cond sub pod time code
1             # INTERNAL MODULE: guts for ScalarRef type from Types::Standard.
2              
3             package Types::Standard::ScalarRef;
4              
5 8     8   767 use 5.008001;
  8         31  
6 8     8   42 use strict;
  8         16  
  8         236  
7 8     8   36 use warnings;
  8         13  
  8         762  
8              
9             BEGIN {
10 8     8   30 $Types::Standard::ScalarRef::AUTHORITY = 'cpan:TOBYINK';
11 8         337 $Types::Standard::ScalarRef::VERSION = '2.010001';
12             }
13              
14             $Types::Standard::ScalarRef::VERSION =~ tr/_//d;
15              
16 8     8   585 use Types::Standard ();
  8         17  
  8         219  
17 8     8   36 use Types::TypeTiny ();
  8         15  
  8         502  
18              
19 2     2   34 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  2         19  
20              
21 8     8   35 no warnings;
  8         22  
  8         449  
22              
23 8     8   44 use Exporter::Tiny 1.004001 ();
  8         146  
  8         8442  
24             our @ISA = qw( Exporter::Tiny );
25              
26             sub _exporter_fail {
27 2     2   278 my ( $class, $type_name, $values, $globals ) = @_;
28 2         4 my $caller = $globals->{into};
29            
30 2 100       6 my $of = exists( $values->{of} ) ? $values->{of} : $values->{type};
31 2 50       6 defined $of or _croak( qq{Expected option "of" for type "$type_name"} );
32 2 100       48 if ( not Types::TypeTiny::is_TypeTiny($of) ) {
33 1         499 require Type::Utils;
34 1         4 $of = Type::Utils::dwim_type( $of, for => $caller );
35             }
36            
37 2         10 my $type = Types::Standard::ScalarRef->of( $of );
38             $type = $type->create_child_type(
39             name => $type_name,
40             $type->has_coercion ? ( coercion => 1 ) : (),
41 2 50       7 exists( $values->{where} ) ? ( constraint => $values->{where} ) : (),
    50          
42             );
43            
44             $INC{'Type/Registry.pm'}
45             ? 'Type::Registry'->for_class( $caller )->add_type( $type, $type_name )
46             : ( $Type::Registry::DELAYED{$caller}{$type_name} = $type )
47 2 100 33     31 unless( ref($caller) or $caller eq '-lexical' or $globals->{'lexical'} );
    50 33        
48 2         3 return map +( $_->{name} => $_->{code} ), @{ $type->exportables };
  2         6  
49             }
50              
51             sub __constraint_generator {
52 16 100   16   69 return Types::Standard::ScalarRef unless @_;
53            
54 15         87 Type::Tiny::check_parameter_count_for_parameterized_type( 'Types::Standard', 'ScalarRef', \@_, 1 );
55 15         38 my $param = shift;
56 15 100       446 Types::TypeTiny::is_TypeTiny( $param )
57             or _croak(
58             "Parameter to ScalarRef[`a] expected to be a type constraint; got $param" );
59            
60             return sub {
61 19     19   44 my $ref = shift;
62 19 100       68 $param->check( $$ref ) || return;
63 10         70 return !!1;
64 13         103 };
65             } #/ sub __constraint_generator
66              
67             sub __inline_generator {
68 13     13   29 my $param = shift;
69 13 50       62 return unless $param->can_be_inlined;
70             return sub {
71 76     76   170 my $v = $_[1];
72 76         326 my $param_check = $param->inline_check( "\${$v}" );
73 76         288 "(ref($v) eq 'SCALAR' or ref($v) eq 'REF') and $param_check";
74 13         118 };
75             }
76              
77             sub __deep_explanation {
78 1     1   3 my ( $type, $value, $varname ) = @_;
79 1         4 my $param = $type->parameters->[0];
80            
81 1         2 for my $item ( $$value ) {
82 1 50       5 next if $param->check( $item );
83             return [
84             sprintf(
85             '"%s" constrains the referenced scalar value with "%s"', $type, $param
86             ),
87 1         5 @{ $param->validate_explain( $item, sprintf( '${%s}', $varname ) ) },
  1         6  
88             ];
89             }
90            
91             # This should never happen...
92 0         0 return; # uncoverable statement
93             } #/ sub __deep_explanation
94              
95             sub __coercion_generator {
96 8     8   23 my ( $parent, $child, $param ) = @_;
97 8 100       35 return unless $param->has_coercion;
98            
99 4         14 my $coercable_item = $param->coercion->_source_type_union;
100 4         27 my $C = "Type::Coercion"->new( type_constraint => $child );
101            
102 4 100 66     14 if ( $param->coercion->can_be_inlined and $coercable_item->can_be_inlined ) {
103             $C->add_type_coercions(
104             $parent => Types::Standard::Stringable {
105 3     3   8 my @code;
106 3         11 push @code, 'do { my ($orig, $return_orig, $new) = ($_, 0);';
107 3         7 push @code, 'for ($$orig) {';
108 3         23 push @code,
109             sprintf(
110             '++$return_orig && last unless (%s);',
111             $coercable_item->inline_check( '$_' )
112             );
113 3         12 push @code,
114             sprintf(
115             '$new = (%s);',
116             $param->coercion->inline_coercion( '$_' )
117             );
118 3         8 push @code, '}';
119 3         9 push @code, '$return_orig ? $orig : \\$new';
120 3         9 push @code, '}';
121 3         26 "@code";
122             }
123 3         39 );
124             } #/ if ( $param->coercion->...)
125             else {
126             $C->add_type_coercions(
127             $parent => sub {
128 2 50   2   32 my $value = @_ ? $_[0] : $_;
129 2         2 my $new;
130 2         4 for my $item ( $$value ) {
131 2 100       7 return $value unless $coercable_item->check( $item );
132 1         15 $new = $param->coerce( $item );
133             }
134 1         25 return \$new;
135             },
136 1         7 );
137             } #/ else [ if ( $param->coercion->...)]
138            
139 4         15 return $C;
140             } #/ sub __coercion_generator
141              
142             1;
143              
144             __END__