File Coverage

blib/lib/Types/TypeTiny.pm
Criterion Covered Total %
statement 299 447 63.0
branch 122 226 53.9
condition 61 93 65.5
subroutine 77 108 64.8
pod 8 27 29.6
total 567 901 60.2


line stmt bran cond sub pod time code
1             package Types::TypeTiny;
2              
3 311     311   539743 use 5.008001;
  311         5127  
4 311     311   8086 use strict;
  311         2786  
  311         24550  
5 311     311   7117 use warnings;
  311         748  
  311         47027  
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '2.010001';
9              
10             $VERSION =~ tr/_//d;
11              
12 311     311   2116 use Scalar::Util qw< blessed refaddr weaken >;
  311         2816  
  311         71998  
13              
14             BEGIN {
15             *__XS = eval {
16 311         187893 require Type::Tiny::XS;
17 311         1323978 'Type::Tiny::XS'->VERSION( '0.022' );
18 311         34404 1;
19             }
20             ? eval "sub () { '$Type::Tiny::XS::VERSION' }"
21 311 50   311   1111 : sub () { !!0 };
22             }
23              
24             our @EXPORT_OK = (
25             map( @{ [ $_, "is_$_", "assert_$_" ] }, __PACKAGE__->type_names ),
26             qw/to_TypeTiny/
27             );
28             our %EXPORT_TAGS = (
29             types => [ __PACKAGE__->type_names ],
30             is => [ map "is_$_", __PACKAGE__->type_names ],
31             assert => [ map "assert_$_", __PACKAGE__->type_names ],
32             );
33              
34             my %cache;
35              
36             # This `import` method is designed to avoid loading Exporter::Tiny.
37             # This is so that if you stick to only using the purely OO parts of
38             # Type::Tiny, you can skip loading the exporter.
39             #
40             sub import {
41              
42             # If this sub succeeds, it will replace itself.
43             # uncoverable subroutine
44 40 100   40   3366 return unless @_ > 1; # uncoverable statement
45 311     311   2577 no warnings "redefine"; # uncoverable statement
  311         718  
  311         103754  
46 39         841 our @ISA = qw( Exporter::Tiny ); # uncoverable statement
47 39         238 require Exporter::Tiny; # uncoverable statement
48 39         186 my $next = \&Exporter::Tiny::import; # uncoverable statement
49 39         181 *import = $next; # uncoverable statement
50 39         136 my $class = shift; # uncoverable statement
51 39 100       440 my $opts = { ref( $_[0] ) ? %{ +shift } : () }; # uncoverable statement
  1         3  
52 39   100     434 $opts->{into} ||= scalar( caller ); # uncoverable statement
53 39         181 _mkall(); # uncoverable statement
54 39         311 return $class->$next( $opts, @_ ); # uncoverable statement
55             } #/ sub import
56              
57             for ( __PACKAGE__->type_names ) { # uncoverable statement
58 0     0 0 0 eval qq{ # uncoverable statement
  0     0 0 0  
  0     0 0 0  
  0     0 0 0  
  115081     115081 0 348463  
  0     0 0 0  
  3     3 0 19  
  174     174 0 897  
  6     6 0 33  
  0     0 0 0  
  16930     16930 0 54228  
  0     0 0 0  
  0     0 0    
59             sub is_$_ { $_()->check(shift) } # uncoverable statement
60             sub assert_$_ { $_()->assert_return(shift) } # uncoverable statement
61             }; # uncoverable statement
62             } # uncoverable statement
63              
64             sub _reinstall_subs {
65              
66             # uncoverable subroutine
67 782     782   1922 my $type = shift; # uncoverable statement
68 311     311   4152 no strict 'refs'; # uncoverable statement
  311         2151  
  311         18595  
69 311     311   1900 no warnings 'redefine'; # uncoverable statement
  311         2923  
  311         107907  
70 782         3210 *{ 'is_' . $type->name } = $type->compiled_check; # uncoverable statement
  782         2691  
71 782         3796 *{ 'assert_' . $type->name } = \&$type; # uncoverable statement
  782         3111  
72 782         5388 $type; # uncoverable statement
73             } # uncoverable statement
74              
75             sub _mkall {
76              
77             # uncoverable subroutine
78 161 100   161   1111 return unless $INC{'Type/Tiny.pm'}; # uncoverable statement
79 160         2233 __PACKAGE__->get_type( $_ ) for __PACKAGE__->type_names; # uncoverable statement
80             } # uncoverable statement
81              
82             sub meta {
83 57     57 1 397946 return $_[0];
84             }
85              
86             sub type_names {
87 3072     3072 1 24170 qw(
88             StringLike BoolLike
89             HashLike ArrayLike CodeLike
90             TypeTiny _ForeignTypeConstraint
91             );
92             }
93              
94             sub has_type {
95 1327     1327 1 3484 my %has = map +( $_ => 1 ), shift->type_names;
96 1327         7505 !!$has{ $_[0] };
97             }
98              
99             sub get_type {
100 1318     1318 1 2737 my $self = shift;
101 1318 100       3546 return unless $self->has_type( @_ );
102 311     311   2642 no strict qw(refs);
  311         830  
  311         61582  
103 1317         2387 &{ $_[0] }();
  1317         5914  
104             }
105              
106             sub coercion_names {
107 32     32 1 723 qw();
108             }
109              
110             sub has_coercion {
111 2     2 1 6 my %has = map +( $_ => 1 ), shift->coercion_names;
112 2         16 !!$has{ $_[0] };
113             }
114              
115             sub get_coercion {
116 1     1 1 2 my $self = shift;
117 1 50       4 return unless $self->has_coercion( @_ );
118 311     311   4112 no strict qw(refs);
  311         949  
  311         47924  
119 0         0 &{ $_[0] }(); # uncoverable statement
  0         0  
120             }
121              
122             my ( $__get_linear_isa_dfs, $tried_mro );
123             $__get_linear_isa_dfs = sub {
124             if ( !$tried_mro && eval { require mro } ) {
125             $__get_linear_isa_dfs = \&mro::get_linear_isa;
126             goto $__get_linear_isa_dfs;
127             }
128 311     311   2110 no strict 'refs';
  311         661  
  311         1870023  
129             my $classname = shift;
130             my @lin = ( $classname );
131             my %stored;
132             foreach my $parent ( @{"$classname\::ISA"} ) {
133             my $plin = $__get_linear_isa_dfs->( $parent );
134             foreach ( @$plin ) {
135             next if exists $stored{$_};
136             push( @lin, $_ );
137             $stored{$_} = 1;
138             }
139             }
140             return \@lin;
141             };
142              
143             sub _check_overload {
144 257     257   1128 my $package = shift;
145 257 50       859 if ( ref $package ) {
146 257         588 $package = blessed( $package );
147 257 50       788 return !!0 if !defined $package;
148             }
149 257         521 my $op = shift;
150 257         1279 my $mro = $__get_linear_isa_dfs->( $package );
151 257         659 foreach my $p ( @$mro ) {
152 315         716 my $fqmeth = $p . q{::(} . $op;
153 315 100       521 return !!1 if defined &{$fqmeth};
  315         2652  
154             }
155 208         2312 !!0;
156             } #/ sub _check_overload
157              
158             sub _get_check_overload_sub {
159 671 100   671   2079 if ( $Type::Tiny::AvoidCallbacks ) {
160             return
161 389         2228 '(sub { require overload; overload::Overloaded(ref $_[0] or $_[0]) and overload::Method((ref $_[0] or $_[0]), $_[1]) })->';
162             }
163 282         1235 return 'Types::TypeTiny::_check_overload';
164             }
165              
166             sub StringLike () {
167 477 100   477 0 657428 return $cache{StringLike} if defined $cache{StringLike};
168 288         3410 require Type::Tiny;
169             my %common = (
170             name => "StringLike",
171             library => __PACKAGE__,
172             constraint => sub {
173 61 100 100 61   725 defined( $_ ) && !ref( $_ )
      100        
174             or blessed( $_ ) && _check_overload( $_, q[""] );
175             },
176             inlined => sub {
177 61     61   132 qq/defined($_[1]) && !ref($_[1]) or Scalar::Util::blessed($_[1]) && ${\ +_get_check_overload_sub() }($_[1], q[""])/;
  61         208  
178             },
179 1     1   4 type_default => sub { return '' },
180 288         5082 );
181 288         772 if ( __XS ) {
182 288         1762 my $xsub = Type::Tiny::XS::get_coderef_for( 'StringLike' );
183 288         5020 my $xsubname = Type::Tiny::XS::get_subname_for( 'StringLike' );
184 288         2592 my $inlined = $common{inlined};
185             $cache{StringLike} = "Type::Tiny"->new(
186             %common,
187             compiled_type_constraint => $xsub,
188             inlined => sub {
189            
190             # uncoverable subroutine
191 411 100 66 411   7914 ( $Type::Tiny::AvoidCallbacks or not $xsubname )
192             ? goto( $inlined )
193             : qq/$xsubname($_[1])/ # uncoverable statement
194             },
195 288         3544 );
196 288         1778 _reinstall_subs $cache{StringLike};
197             } #/ if ( __XS )
198             else {
199             $cache{StringLike} = "Type::Tiny"->new( %common );
200             }
201             } #/ sub StringLike
202              
203             sub HashLike (;@) {
204 262 100 100 262 0 372163 return $cache{HashLike} if defined( $cache{HashLike} ) && !@_;
205 163         2892 require Type::Tiny;
206             my %common = (
207             name => "HashLike",
208             library => __PACKAGE__,
209             constraint => sub {
210 71 100 100 71   927 ref( $_ ) eq q[HASH]
211             or blessed( $_ ) && _check_overload( $_, q[%{}] );
212             },
213             inlined => sub {
214 71     71   183 qq/ref($_[1]) eq q[HASH] or Scalar::Util::blessed($_[1]) && ${\ +_get_check_overload_sub() }($_[1], q[\%{}])/;
  71         220  
215             },
216 1     1   5 type_default => sub { return {} },
217             constraint_generator => sub {
218 2     2   8 my $param = TypeTiny()->assert_coerce( shift );
219 2         7 my $check = $param->compiled_check;
220 2         7 if ( __XS ge '0.025' ) {
221 2         9 my $paramname = Type::Tiny::XS::is_known( $check );
222 2 50       26 my $xsub = defined($paramname)
223             ? Type::Tiny::XS::get_coderef_for( "HashLike[$paramname]" )
224             : undef;
225 2 50       107 return $xsub if $xsub;
226             }
227             sub {
228 0         0 my %hash = %$_;
229 0         0 for my $key ( sort keys %hash ) {
230 0 0       0 $check->( $hash{$key} ) or return 0;
231             }
232 0         0 return 1;
233 0         0 };
234             },
235             inline_generator => sub {
236 2     2   7 my $param = TypeTiny()->assert_coerce( shift );
237 2 50       9 return unless $param->can_be_inlined;
238 2         8 my $check = $param->compiled_check;
239 2         5 my $xsubname;
240 2         3 if ( __XS ge '0.025' ) {
241 2         8 my $paramname = Type::Tiny::XS::is_known( $check );
242 2 50       23 $xsubname = defined($paramname)
243             ? Type::Tiny::XS::get_subname_for( "HashLike[$paramname]" )
244             : undef;
245             }
246             sub {
247 23         75 my $var = pop;
248 23 100 66     169 return "$xsubname($var)" if $xsubname && !$Type::Tiny::AvoidCallbacks;
249 10         43 my $code = sprintf(
250             'do { my $ok=1; my %%h = %%{%s}; for my $k (sort keys %%h) { ($ok=0,next) unless (%s) }; $ok }',
251             $var,
252             $param->inline_check( '$h{$k}' ),
253             );
254 10         36 return ( undef, $code );
255 2         75 };
256             },
257             coercion_generator => sub {
258 1     1   4 my ( $parent, $child, $param ) = @_;
259 1 50       5 return unless $param->has_coercion;
260 1         6 my $coercible = $param->coercion->_source_type_union->compiled_check;
261 1         13 my $C = "Type::Coercion"->new( type_constraint => $child );
262             $C->add_type_coercions(
263             $parent => sub {
264 4 50       107 my $origref = @_ ? $_[0] : $_;
265 4         17 my %orig = %$origref;
266 4         18 my %new;
267 4         20 for my $k ( sort keys %orig ) {
268 8 100       96 return $origref unless $coercible->( $orig{$k} );
269 6         72 $new{$k} = $param->coerce( $orig{$k} );
270             }
271 2         38 \%new;
272             },
273 1         11 );
274 1         4 return $C;
275             },
276 163         4755 );
277 163         541 if ( __XS ) {
278 163         3749 my $xsub = Type::Tiny::XS::get_coderef_for( 'HashLike' );
279 163         3225 my $xsubname = Type::Tiny::XS::get_subname_for( 'HashLike' );
280 163         1466 my $inlined = $common{inlined};
281             $cache{HashLike} = "Type::Tiny"->new(
282             %common,
283             compiled_type_constraint => $xsub,
284             inlined => sub {
285            
286             # uncoverable subroutine
287 297 100 66 297   3360 ( $Type::Tiny::AvoidCallbacks or not $xsubname )
288             ? goto( $inlined )
289             : qq/$xsubname($_[1])/ # uncoverable statement
290             },
291 163         1922 );
292 163         1278 _reinstall_subs $cache{HashLike};
293             } #/ if ( __XS )
294             else {
295             $cache{HashLike} = "Type::Tiny"->new( %common );
296             }
297            
298 163 100       3972 @_ ? $cache{HashLike}->parameterize( @{ $_[0] } ) : $cache{HashLike};
  2         15  
299             } #/ sub HashLike (;@)
300              
301             sub ArrayLike (;@) {
302 267 100 100 267 0 294178 return $cache{ArrayLike} if defined( $cache{ArrayLike} ) && !@_;
303 164         2310 require Type::Tiny;
304             my %common = (
305             name => "ArrayLike",
306             library => __PACKAGE__,
307             constraint => sub {
308 71 100 100 71   826 ref( $_ ) eq q[ARRAY]
309             or blessed( $_ ) && _check_overload( $_, q[@{}] );
310             },
311             inlined => sub {
312 71     71   154 qq/ref($_[1]) eq q[ARRAY] or Scalar::Util::blessed($_[1]) && ${\ +_get_check_overload_sub() }($_[1], q[\@{}])/;
  71         251  
313             },
314 1     1   7 type_default => sub { return [] },
315             constraint_generator => sub {
316 2     2   5 my $param = TypeTiny()->assert_coerce( shift );
317 2         8 my $check = $param->compiled_check;
318 2         4 if ( __XS ge '0.025' ) {
319 2         9 my $paramname = Type::Tiny::XS::is_known( $check );
320 2 50       24 my $xsub = defined($paramname)
321             ? Type::Tiny::XS::get_coderef_for( "ArrayLike[$paramname]" )
322             : undef;
323 2 50       87 return $xsub if $xsub;
324             }
325             sub {
326 0         0 my @arr = @$_;
327 0         0 for my $val ( @arr ) {
328 0 0       0 $check->( $val ) or return 0;
329             }
330 0         0 return 1;
331 0         0 };
332             },
333             inline_generator => sub {
334 2     2   6 my $param = TypeTiny()->assert_coerce( shift );
335 2 50       7 return unless $param->can_be_inlined;
336 2         6 my $check = $param->compiled_check;
337 2         4 my $xsubname;
338 2         5 if ( __XS ge '0.025' ) {
339 2         7 my $paramname = Type::Tiny::XS::is_known( $check );
340 2 50       19 $xsubname = defined($paramname)
341             ? Type::Tiny::XS::get_subname_for( "ArrayLike[$paramname]" )
342             : undef;
343             }
344             sub {
345 23         67 my $var = pop;
346 23 100 66     232 return "$xsubname($var)" if $xsubname && !$Type::Tiny::AvoidCallbacks;
347 10         44 my $code = sprintf(
348             'do { my $ok=1; for my $v (@{%s}) { ($ok=0,next) unless (%s) }; $ok }',
349             $var,
350             $param->inline_check( '$v' ),
351             );
352 10         33 return ( undef, $code );
353 2         40 };
354             },
355             coercion_generator => sub {
356 1     1   3 my ( $parent, $child, $param ) = @_;
357 1 50       6 return unless $param->has_coercion;
358 1         5 my $coercible = $param->coercion->_source_type_union->compiled_check;
359 1         12 my $C = "Type::Coercion"->new( type_constraint => $child );
360             $C->add_type_coercions(
361             $parent => sub {
362 4 50       70 my $origref = @_ ? $_[0] : $_;
363 4         10 my @orig = @$origref;
364 4         10 my @new;
365 4         9 for my $v ( @orig ) {
366 10 100       62 return $origref unless $coercible->( $v );
367 8         71 push @new, $param->coerce( $v );
368             }
369 2         29 \@new;
370             },
371 1         18 );
372 1         4 return $C;
373             },
374 164         4323 );
375 164         480 if ( __XS ) {
376 164         774 my $xsub = Type::Tiny::XS::get_coderef_for( 'ArrayLike' );
377 164         2653 my $xsubname = Type::Tiny::XS::get_subname_for( 'ArrayLike' );
378 164         1414 my $inlined = $common{inlined};
379             $cache{ArrayLike} = "Type::Tiny"->new(
380             %common,
381             compiled_type_constraint => $xsub,
382             inlined => sub {
383            
384             # uncoverable subroutine
385 298 100 66 298   2957 ( $Type::Tiny::AvoidCallbacks or not $xsubname )
386             ? goto( $inlined )
387             : qq/$xsubname($_[1])/ # uncoverable statement
388             },
389 164         1727 );
390 164         917 _reinstall_subs $cache{ArrayLike};
391             } #/ if ( __XS )
392             else {
393             $cache{ArrayLike} = "Type::Tiny"->new( %common );
394             }
395            
396 164 100       2119 @_ ? $cache{ArrayLike}->parameterize( @{ $_[0] } ) : $cache{ArrayLike};
  2         14  
397             } #/ sub ArrayLike (;@)
398              
399             if ( $] ge '5.014' ) {
400             &Scalar::Util::set_prototype( $_, ';$' ) for \&HashLike, \&ArrayLike;
401             }
402              
403             sub CodeLike () {
404 268 100   268 0 430472 return $cache{CodeLike} if $cache{CodeLike};
405 167         1390 require Type::Tiny;
406             my %common = (
407             name => "CodeLike",
408             constraint => sub {
409 62 100 100 62   560 ref( $_ ) eq q[CODE]
410             or blessed( $_ ) && _check_overload( $_, q[&{}] );
411             },
412             inlined => sub {
413 62     62   124 qq/ref($_[1]) eq q[CODE] or Scalar::Util::blessed($_[1]) && ${\ +_get_check_overload_sub() }($_[1], q[\&{}])/;
  62         156  
414             },
415 1     1   25 type_default => sub { return sub {} },
416 167         5414 library => __PACKAGE__,
417             );
418 167         410 if ( __XS ) {
419 167         795 my $xsub = Type::Tiny::XS::get_coderef_for( 'CodeLike' );
420 167         3305 my $xsubname = Type::Tiny::XS::get_subname_for( 'CodeLike' );
421 167         1407 my $inlined = $common{inlined};
422             $cache{CodeLike} = "Type::Tiny"->new(
423             %common,
424             compiled_type_constraint => $xsub,
425             inlined => sub {
426            
427             # uncoverable subroutine
428 292 100 66 292   3285 ( $Type::Tiny::AvoidCallbacks or not $xsubname )
429             ? goto( $inlined )
430             : qq/$xsubname($_[1])/ # uncoverable statement
431             },
432 167         3688 );
433 167         866 _reinstall_subs $cache{CodeLike};
434             } #/ if ( __XS )
435             else {
436             $cache{CodeLike} = "Type::Tiny"->new( %common );
437             }
438             } #/ sub CodeLike
439              
440             sub BoolLike () {
441 497 100   497 0 392554 return $cache{BoolLike} if $cache{BoolLike};
442 160         1214 require Type::Tiny;
443             $cache{BoolLike} = "Type::Tiny"->new(
444             name => "BoolLike",
445             constraint => sub {
446             !defined( $_ )
447             or !ref( $_ ) && ( $_ eq '' || $_ eq '0' || $_ eq '1' )
448             or blessed( $_ ) && (
449             _check_overload( $_, q[bool] )
450             or _check_overload( $_, q[0+] ) && do { my $n = sprintf('%d', $_); $n==0 or $n==1 }
451 62 100 66 62   970 or do { my $d = $_->can('DOES') || $_->can('isa'); $_->$d('boolean') }
      66        
      100        
      100        
      100        
452             )
453             },
454             inlined => sub {
455 203     203   527 qq/do {
456             local \$_ = $_;
457             !defined()
458             or !ref() && ( \$_ eq '' || \$_ eq '0' || \$_ eq '1' )
459             or Scalar::Util::blessed(\$_) && (
460 203         670 ${\ +_get_check_overload_sub() }(\$_, q[bool])
461 203         490 or ${\ +_get_check_overload_sub() }(\$_, q[0+]) && do { my \$n = sprintf('%d', $_); \$n==0 or \$n==1 }
462             or do { my \$d = \$_->can('DOES') || \$_->can('isa'); \$_->\$d('boolean') }
463             )
464             }/;
465             },
466 1     1   6 type_default => sub { return !!0 },
467 160         3114 library => __PACKAGE__,
468             );
469             } #/ sub BoolLike
470              
471             sub TypeTiny () {
472 132280 100   132280 0 1079611 return $cache{TypeTiny} if defined $cache{TypeTiny};
473 289         1893 require Type::Tiny;
474             $cache{TypeTiny} = "Type::Tiny"->new(
475             name => "TypeTiny",
476 62 100   62   822 constraint => sub { blessed( $_ ) && $_->isa( q[Type::Tiny] ) },
477             inlined => sub {
478 467     467   1423 my $var = $_[1];
479 467         2317 "Scalar::Util::blessed($var) && $var\->isa(q[Type::Tiny])";
480             },
481 1     1   1526 type_default => sub { require Types::Standard; return Types::Standard::Any() },
  1         9  
482             library => __PACKAGE__,
483             _build_coercion => sub {
484 31     31   105 my $c = shift;
485 31         192 $c->add_type_coercions( _ForeignTypeConstraint(), \&to_TypeTiny );
486 31         199 $c->freeze;
487             },
488 289         4568 );
489             } #/ sub TypeTiny
490              
491             sub _ForeignTypeConstraint () {
492 288 100   288   374255 return $cache{_ForeignTypeConstraint} if defined $cache{_ForeignTypeConstraint};
493 160         1022 require Type::Tiny;
494             $cache{_ForeignTypeConstraint} = "Type::Tiny"->new(
495             name => "_ForeignTypeConstraint",
496             constraint => \&_is_ForeignTypeConstraint,
497             inlined => sub {
498 206     206   939 qq/ref($_[1]) && do { require Types::TypeTiny; Types::TypeTiny::_is_ForeignTypeConstraint($_[1]) }/;
499             },
500 160         1501 library => __PACKAGE__,
501             );
502             } #/ sub _ForeignTypeConstraint
503              
504             my %ttt_cache;
505              
506             sub _is_ForeignTypeConstraint {
507 222 50   222   1422 my $t = @_ ? $_[0] : $_;
508 222 100       794 return !!1 if ref $t eq 'CODE';
509 216 100       638 if ( my $class = blessed $t ) {
510 100 50       809 return !!0 if $class->isa( "Type::Tiny" );
511 100 50       427 return !!1 if $class->isa( "Moose::Meta::TypeConstraint" );
512 100 50       382 return !!1 if $class->isa( "MooseX::Types::TypeDecorator" );
513 100 50       520 return !!1 if $class->isa( "Validation::Class::Simple" );
514 100 50       377 return !!1 if $class->isa( "Validation::Class" );
515 100 100       459 return !!1 if $t->can( "check" );
516             }
517 211         1590 !!0;
518             } #/ sub _is_ForeignTypeConstraint
519              
520             sub to_TypeTiny {
521 157629 50   157629 1 712656 my $t = @_ ? $_[0] : $_;
522            
523 157629 100       420579 return $t unless ( my $ref = ref $t );
524 152625 100       592770 return $t if $ref =~ /^Type::Tiny\b/;
525            
526 40095 50       140603 return $ttt_cache{ refaddr( $t ) } if $ttt_cache{ refaddr( $t ) };
527            
528             #<<<
529 40095 100       107371 if ( my $class = blessed $t) {
530 53 50       7142 return $t if $class->isa( "Type::Tiny" );
531 53 50       268 return _TypeTinyFromMoose( $t ) if $class eq "MooseX::Types::TypeDecorator"; # needed before MooseX::Types 0.35.
532 53 50       501 return _TypeTinyFromMoose( $t ) if $class->isa( "Moose::Meta::TypeConstraint" );
533 53 50       409 return _TypeTinyFromMoose( $t ) if $class->isa( "MooseX::Types::TypeDecorator" );
534 53 50       479 return _TypeTinyFromMouse( $t ) if $class->isa( "Mouse::Meta::TypeConstraint" );
535 53 50       427 return _TypeTinyFromValidationClass( $t ) if $class->isa( "Validation::Class::Simple" );
536 53 50       314 return _TypeTinyFromValidationClass( $t ) if $class->isa( "Validation::Class" );
537 53 100 66     1188 return $t->to_TypeTiny if $t->can( "DOES" ) && $t->DOES( "Type::Library::Compiler::TypeConstraint" ) && $t->can( "to_TypeTiny" );
      66        
538 47 100       458 return _TypeTinyFromGeneric( $t ) if $t->can( "check" ); # i.e. Type::API::Constraint
539             } #/ if ( my $class = blessed...)
540             #>>>
541            
542 40086 100       146656 return _TypeTinyFromCodeRef( $t ) if $ref eq q(CODE);
543            
544 67         353 $t;
545             } #/ sub to_TypeTiny
546              
547             sub _TypeTinyFromMoose {
548 0     0   0 my $t = $_[0];
549            
550 0 0       0 if ( ref $t->{"Types::TypeTiny::to_TypeTiny"} ) {
551 0         0 return $t->{"Types::TypeTiny::to_TypeTiny"};
552             }
553            
554 0 0       0 if ( $t->name ne '__ANON__' ) {
555 0         0 require Types::Standard;
556 0         0 my $ts = 'Types::Standard'->get_type( $t->name );
557 0 0       0 return $ts if $ts->{_is_core};
558             }
559            
560             #<<<
561 0 0       0 my ( $tt_class, $tt_opts ) =
    0          
    0          
    0          
    0          
    0          
562             $t->can( 'parameterize' ) ? _TypeTinyFromMoose_parameterizable( $t ) :
563             $t->isa( 'Moose::Meta::TypeConstraint::Enum' ) ? _TypeTinyFromMoose_enum( $t ) :
564             $t->isa( 'Moose::Meta::TypeConstraint::Class' ) ? _TypeTinyFromMoose_class( $t ) :
565             $t->isa( 'Moose::Meta::TypeConstraint::Role' ) ? _TypeTinyFromMoose_role( $t ) :
566             $t->isa( 'Moose::Meta::TypeConstraint::Union' ) ? _TypeTinyFromMoose_union( $t ) :
567             $t->isa( 'Moose::Meta::TypeConstraint::DuckType' ) ? _TypeTinyFromMoose_ducktype( $t ) :
568             _TypeTinyFromMoose_baseclass( $t );
569             #>>>
570            
571             # Standard stuff to do with all type constraints from Moose,
572             # regardless of variety.
573 0         0 $tt_opts->{moose_type} = $t;
574 0         0 $tt_opts->{display_name} = $t->name;
575 0     0   0 $tt_opts->{message} = sub { $t->get_message( $_ ) }
576 0 0       0 if $t->has_message;
577            
578 0         0 my $new = $tt_class->new( %$tt_opts );
579 0         0 $ttt_cache{ refaddr( $t ) } = $new;
580 0         0 weaken( $ttt_cache{ refaddr( $t ) } );
581            
582 0 0       0 $new->{coercion} = do {
583 0         0 require Type::Coercion::FromMoose;
584 0         0 'Type::Coercion::FromMoose'->new(
585             type_constraint => $new,
586             moose_coercion => $t->coercion,
587             );
588             } if $t->has_coercion;
589            
590 0         0 return $new;
591             } #/ sub _TypeTinyFromMoose
592              
593             sub _TypeTinyFromMoose_baseclass {
594 0     0   0 my $t = shift;
595 0         0 my %opts;
596 0 0       0 $opts{parent} = to_TypeTiny( $t->parent ) if $t->has_parent;
597 0         0 $opts{constraint} = $t->constraint;
598 0     0   0 $opts{inlined} = sub { shift; $t->_inline_check( @_ ) }
  0         0  
599 0 0 0     0 if $t->can( "can_be_inlined" ) && $t->can_be_inlined;
600            
601             # Cowardly refuse to inline types that need to close over stuff
602 0 0       0 if ( $opts{inlined} ) {
603 0 0       0 my %env = %{ $t->inline_environment || {} };
  0         0  
604 0 0       0 delete( $opts{inlined} ) if keys %env;
605             }
606            
607 0         0 require Type::Tiny;
608 0         0 return 'Type::Tiny' => \%opts;
609             } #/ sub _TypeTinyFromMoose_baseclass
610              
611             sub _TypeTinyFromMoose_union {
612 0     0   0 my $t = shift;
613 0         0 my @mapped = map _TypeTinyFromMoose( $_ ), @{ $t->type_constraints };
  0         0  
614 0         0 require Type::Tiny::Union;
615 0         0 return 'Type::Tiny::Union' => { type_constraints => \@mapped };
616             }
617              
618             sub _TypeTinyFromMoose_enum {
619 0     0   0 my $t = shift;
620 0         0 require Type::Tiny::Enum;
621 0         0 return 'Type::Tiny::Enum' => { values => [ @{ $t->values } ] };
  0         0  
622             }
623              
624             sub _TypeTinyFromMoose_class {
625 0     0   0 my $t = shift;
626 0         0 require Type::Tiny::Class;
627 0         0 return 'Type::Tiny::Class' => { class => $t->class };
628             }
629              
630             sub _TypeTinyFromMoose_role {
631 0     0   0 my $t = shift;
632 0         0 require Type::Tiny::Role;
633 0         0 return 'Type::Tiny::Role' => { role => $t->role };
634             }
635              
636             sub _TypeTinyFromMoose_ducktype {
637 0     0   0 my $t = shift;
638 0         0 require Type::Tiny::Duck;
639 0         0 return 'Type::Tiny::Duck' => { methods => [ @{ $t->methods } ] };
  0         0  
640             }
641              
642             sub _TypeTinyFromMoose_parameterizable {
643 0     0   0 my $t = shift;
644 0         0 my ( $class, $opts ) = _TypeTinyFromMoose_baseclass( $t );
645             $opts->{constraint_generator} = sub {
646            
647             # convert args into Moose native types; not strictly necessary
648 0 0   0   0 my @args = map { is_TypeTiny( $_ ) ? $_->moose_type : $_ } @_;
  0         0  
649 0         0 _TypeTinyFromMoose( $t->parameterize( @args ) );
650 0         0 };
651 0         0 return ( $class, $opts );
652             } #/ sub _TypeTinyFromMoose_parameterizable
653              
654             sub _TypeTinyFromValidationClass {
655 0     0   0 my $t = $_[0];
656            
657 0         0 require Type::Tiny;
658 0         0 require Types::Standard;
659            
660 0         0 my %opts = (
661             parent => Types::Standard::HashRef(),
662             _validation_class => $t,
663             );
664            
665 0 0       0 if ( $t->VERSION >= "7.900048" ) {
666             $opts{constraint} = sub {
667 0     0   0 $t->params->clear;
668 0         0 $t->params->add( %$_ );
669 0         0 my $f = $t->filtering;
670 0         0 $t->filtering( 'off' );
671 0         0 my $r = eval { $t->validate };
  0         0  
672 0   0     0 $t->filtering( $f || 'pre' );
673 0         0 return $r;
674 0         0 };
675             $opts{message} = sub {
676 0     0   0 $t->params->clear;
677 0         0 $t->params->add( %$_ );
678 0         0 my $f = $t->filtering;
679 0         0 $t->filtering( 'off' );
680 0 0       0 my $r = ( eval { $t->validate } ? "OK" : $t->errors_to_string );
  0         0  
681 0   0     0 $t->filtering( $f || 'pre' );
682 0         0 return $r;
683 0         0 };
684             } #/ if ( $t->VERSION >= "7.900048")
685             else # need to use hackish method
686             {
687             $opts{constraint} = sub {
688 0     0   0 $t->params->clear;
689 0         0 $t->params->add( %$_ );
690 311     311   3807 no warnings "redefine";
  311         758  
  311         58045  
691 0         0 local *Validation::Class::Directive::Filters::execute_filtering = sub { $_[0] };
  0         0  
692 0         0 eval { $t->validate };
  0         0  
693 0         0 };
694             $opts{message} = sub {
695 0     0   0 $t->params->clear;
696 0         0 $t->params->add( %$_ );
697 311     311   3079 no warnings "redefine";
  311         1277  
  311         445791  
698 0         0 local *Validation::Class::Directive::Filters::execute_filtering = sub { $_[0] };
  0         0  
699 0 0       0 eval { $t->validate } ? "OK" : $t->errors_to_string;
  0         0  
700 0         0 };
701             } #/ else [ if ( $t->VERSION >= "7.900048")]
702            
703 0         0 require Type::Tiny;
704 0         0 my $new = "Type::Tiny"->new( %opts );
705            
706             $new->coercion->add_type_coercions(
707             Types::Standard::HashRef() => sub {
708 0     0   0 my %params = %$_;
709 0 0       0 for my $k ( keys %params ) { delete $params{$_} unless $t->get_fields( $k ) }
  0         0  
710 0         0 $t->params->clear;
711 0         0 $t->params->add( %params );
712 0         0 eval { $t->validate };
  0         0  
713 0         0 $t->get_hash;
714             },
715 0         0 );
716            
717 0         0 $ttt_cache{ refaddr( $t ) } = $new;
718 0         0 weaken( $ttt_cache{ refaddr( $t ) } );
719 0         0 return $new;
720             } #/ sub _TypeTinyFromValidationClass
721              
722             sub _TypeTinyFromGeneric {
723 3     3   6 my $t = $_[0];
724            
725             my %opts = (
726 30 50   30   131 constraint => sub { $t->check( @_ ? @_ : $_ ) },
727 3         29 );
728            
729 2 50   2   11 $opts{message} = sub { $t->get_message( @_ ? @_ : $_ ) }
730 3 50       27 if $t->can( "get_message" );
731            
732 3 50       19 $opts{display_name} = $t->name if $t->can( "name" );
733            
734 1 50   1   102 $opts{coercion} = sub { $t->coerce( @_ ? @_ : $_ ) }
735 3 50 66     23 if $t->can( "has_coercion" )
      66        
736             && $t->has_coercion
737             && $t->can( "coerce" );
738            
739 3 0 33     38 if ( $t->can( 'can_be_inlined' )
      33        
740             && $t->can_be_inlined
741             && $t->can( 'inline_check' ) )
742             {
743 0     0   0 $opts{inlined} = sub { $t->inline_check( $_[1] ) };
  0         0  
744             }
745            
746 3         28 require Type::Tiny;
747 3         22 my $new = "Type::Tiny"->new( %opts );
748 3         15 $ttt_cache{ refaddr( $t ) } = $new;
749 3         9 weaken( $ttt_cache{ refaddr( $t ) } );
750 3         20 return $new;
751             } #/ sub _TypeTinyFromGeneric
752              
753             sub _TypeTinyFromMouse {
754 0     0   0 my $t = $_[0];
755            
756             my %opts = (
757 0 0   0   0 constraint => sub { $t->check( @_ ? @_ : $_ ) },
758 0 0   0   0 message => sub { $t->get_message( @_ ? @_ : $_ ) },
759 0         0 );
760            
761 0 0       0 $opts{display_name} = $t->name if $t->can( "name" );
762            
763 0 0   0   0 $opts{coercion} = sub { $t->coerce( @_ ? @_ : $_ ) }
764 0 0 0     0 if $t->can( "has_coercion" )
      0        
765             && $t->has_coercion
766             && $t->can( "coerce" );
767            
768 0 0       0 if ( $t->{'constraint_generator'} ) {
769             $opts{constraint_generator} = sub {
770            
771             # convert args into Moose native types; not strictly necessary
772 0 0   0   0 my @args = map { is_TypeTiny( $_ ) ? $_->mouse_type : $_ } @_;
  0         0  
773 0         0 _TypeTinyFromMouse( $t->parameterize( @args ) );
774 0         0 };
775             }
776            
777 0         0 require Type::Tiny;
778 0         0 my $new = "Type::Tiny"->new( %opts );
779 0         0 $ttt_cache{ refaddr( $t ) } = $new;
780 0         0 weaken( $ttt_cache{ refaddr( $t ) } );
781 0         0 return $new;
782             } #/ sub _TypeTinyFromMouse
783              
784             my $QFS;
785              
786             sub _TypeTinyFromCodeRef {
787 40019     40019   66725 my $t = $_[0];
788            
789             my %opts = (
790             constraint => sub {
791 93     93   157 return !!eval { $t->( $_ ) };
  93         366  
792             },
793             message => sub {
794 2     2   2 local $@;
795 2 50       4 eval { $t->( $_ ); 1 } or do { chomp $@; return $@ if $@ };
  2 100       5  
  1         3  
  1         6  
  1         12  
796 1         5 return sprintf( '%s did not pass type constraint', Type::Tiny::_dd( $_ ) );
797             },
798 40019         302329 );
799            
800 40019 100 66     337709 if ( $QFS ||= "Sub::Quote"->can( "quoted_from_sub" ) ) {
801 1 50       2 my ( undef, $perlstring, $captures ) = @{ $QFS->( $t ) || [] };
  1         5  
802 1 50       89 if ( $perlstring ) {
803 1         3 $perlstring = "!!eval{ $perlstring }";
804             $opts{inlined} = sub {
805 11     11   40 my $var = $_[1];
806 11 50       53 Sub::Quote::inlinify(
807             $perlstring,
808             $var,
809             $var eq q($_) ? '' : "local \$_ = $var;",
810             1,
811             );
812             }
813 1 50 33     11 if $perlstring && !$captures;
814             } #/ if ( $perlstring )
815             } #/ if ( $QFS ||= "Sub::Quote"...)
816            
817 40019         206274 require Type::Tiny;
818 40019         180208 my $new = "Type::Tiny"->new( %opts );
819 40019         129976 $ttt_cache{ refaddr( $t ) } = $new;
820 40019         84802 weaken( $ttt_cache{ refaddr( $t ) } );
821 40019         227455 return $new;
822             } #/ sub _TypeTinyFromCodeRef
823              
824             1;
825              
826             __END__