File Coverage

lib/Types/Standard/StrMatch.pm
Criterion Covered Total %
statement 77 77 100.0
branch 31 40 77.5
condition 9 15 60.0
subroutine 19 19 100.0
pod n/a
total 136 151 90.0


line stmt bran cond sub pod time code
1             # INTERNAL MODULE: guts for StrMatch type from Types::Standard.
2              
3             package Types::Standard::StrMatch;
4              
5 12     12   1194 use 5.008001;
  12         56  
6 12     12   90 use strict;
  12         26  
  12         447  
7 12     12   64 use warnings;
  12         25  
  12         1315  
8              
9             BEGIN {
10 12     12   51 $Types::Standard::StrMatch::AUTHORITY = 'cpan:TOBYINK';
11 12         605 $Types::Standard::StrMatch::VERSION = '2.010001';
12             }
13              
14             $Types::Standard::StrMatch::VERSION =~ tr/_//d;
15              
16 12     12   84 use Type::Tiny ();
  12         28  
  12         347  
17 12     12   69 use Types::Standard ();
  12         24  
  12         207  
18 12     12   57 use Types::TypeTiny ();
  12         42  
  12         969  
19              
20 2     2   65 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  2         14  
21              
22 12     12   79 use Exporter::Tiny 1.004001 ();
  12         294  
  12         4327  
23             our @ISA = qw( Exporter::Tiny );
24              
25             sub _exporter_fail {
26 2     2   485 my ( $class, $type_name, $values, $globals ) = @_;
27 2         6 my $caller = $globals->{into};
28            
29 2 100       9 my $of = exists( $values->{of} ) ? $values->{of} : $values->{re};
30 2         10 Types::Standard::RegexpRef->assert_valid( $of );
31            
32 2         27 my $type = Types::Standard::StrMatch->of( $of );
33             $type = $type->create_child_type(
34             name => $type_name,
35             $type->has_coercion ? ( coercion => 1 ) : (),
36 2 50       10 exists( $values->{where} ) ? ( constraint => $values->{where} ) : (),
    50          
37             );
38            
39             $INC{'Type/Registry.pm'}
40             ? 'Type::Registry'->for_class( $caller )->add_type( $type, $type_name )
41             : ( $Type::Registry::DELAYED{$caller}{$type_name} = $type )
42 2 50 33     25 unless( ref($caller) or $caller eq '-lexical' or $globals->{'lexical'} );
    50 33        
43 2         5 return map +( $_->{name} => $_->{code} ), @{ $type->exportables };
  2         8  
44             }
45              
46 12     12   100 no warnings;
  12         250  
  12         16503  
47              
48             our %expressions;
49             my $has_regexp_util;
50             my $serialize_regexp = sub {
51             $has_regexp_util = eval {
52             require Regexp::Util;
53             Regexp::Util->VERSION( '0.003' );
54             1;
55             } || 0 unless defined $has_regexp_util;
56            
57             my $re = shift;
58             my $serialized;
59             if ( $has_regexp_util ) {
60             $serialized = eval { Regexp::Util::serialize_regexp( $re ) };
61             }
62            
63             unless ( defined $serialized ) {
64             my $key = sprintf( '%s|%s', ref( $re ), $re );
65             $expressions{$key} = $re;
66             $serialized = sprintf(
67             '$Types::Standard::StrMatch::expressions{%s}',
68             B::perlstring( $key )
69             );
70             }
71            
72             return $serialized;
73             };
74              
75             sub __constraint_generator {
76 36 50   36   147 return Types::Standard->meta->get_type( 'StrMatch' ) unless @_;
77            
78 36         246 Type::Tiny::check_parameter_count_for_parameterized_type( 'Types::Standard', 'StrMatch', \@_, 2, 1 );
79 36         122 my ( $regexp, $checker ) = @_;
80            
81 36 100       184 Types::Standard::is_RegexpRef( $regexp )
82             or _croak(
83             "First parameter to StrMatch[`a] expected to be a Regexp; got $regexp" );
84            
85 35 100       397 if ( @_ > 1 ) {
86 5         24 $checker = Types::TypeTiny::to_TypeTiny( $checker );
87 5 100       198 Types::TypeTiny::is_TypeTiny( $checker )
88             or _croak(
89             "Second parameter to StrMatch[`a] expected to be a type constraint; got $checker"
90             );
91             }
92            
93             $checker
94             ? sub {
95 24     24   58 my $value = shift;
96 24 50       72 return if !defined ( $value );
97 24 50       73 return if ref( $value );
98 24         243 my @m = ( $value =~ $regexp );
99 24         102 $checker->check( \@m );
100             }
101             : sub {
102 30     30   71 my $value = shift;
103 30 50 33     637 defined( $value ) and !ref( $value ) and !!( $value =~ $regexp );
104 34 100       316 };
105             } #/ sub __constraint_generator
106              
107             sub __inline_generator {
108 34     34   258 require B;
109 34         115 my ( $regexp, $checker ) = @_;
110 34 50       168 my $serialized_re = $regexp->$serialize_regexp or return;
111            
112 34 100       134 if ( $checker ) {
113 4 100       23 return unless $checker->can_be_inlined;
114            
115             return sub {
116 24     24   56 my $v = $_[1];
117 24 100 100     164 if ( $Type::Tiny::AvoidCallbacks
118             and $serialized_re =~ /Types::Standard::StrMatch::expressions/ )
119             {
120 1         13 require Carp;
121 1         196 Carp::carp(
122             "Cannot serialize regexp without callbacks; serializing using callbacks" );
123             }
124             sprintf
125 24         124 "defined($v) and !ref($v) and do { my \$m = [$v =~ %s]; %s }",
126             $serialized_re,
127             $checker->inline_check( '$m' ),
128             ;
129 3         30 };
130             } #/ if ( $checker )
131             else {
132 30         88 my $regexp_string = "$regexp";
133 30 100       145 if ( $regexp_string =~ /\A\(\?\^u?:\\A(\.+)\)\z/ ) {
134 1         4 my $length = length $1;
135 1     7   8 return sub { "defined($_) and !ref($_) and length($_)>=$length" };
  7         32  
136             }
137            
138 29 100       102 if ( $regexp_string =~ /\A\(\?\^u?:\\A(\.+)\\z\)\z/ ) {
139 1         4 my $length = length $1;
140 1     7   11 return sub { "defined($_) and !ref($_) and length($_)==$length" };
  7         49  
141             }
142            
143             return sub {
144 177     177   460 my $v = $_[1];
145 177 100 100     645 if ( $Type::Tiny::AvoidCallbacks
146             and $serialized_re =~ /Types::Standard::StrMatch::expressions/ )
147             {
148 6         77 require Carp;
149 6         1103 Carp::carp(
150             "Cannot serialize regexp without callbacks; serializing using callbacks" );
151             }
152 177         813 "defined($v) and !ref($v) and !!( $v =~ $serialized_re )";
153 28         262 };
154             } #/ else [ if ( $checker ) ]
155             } #/ sub __inline_generator
156              
157             1;
158              
159             __END__