File Coverage

blib/lib/isa.pm
Criterion Covered Total %
statement 43 45 95.5
branch 6 12 50.0
condition 3 7 42.8
subroutine 11 11 100.0
pod 0 3 0.0
total 63 78 80.7


line stmt bran cond sub pod time code
1 1     1   69927 use 5.006;
  1         4  
2 1     1   5 use strict;
  1         2  
  1         20  
3 1     1   5 use warnings;
  1         1  
  1         241  
4              
5             package isa;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '2.000';
9              
10             BEGIN {
11 1 50   1   4 *HAS_XS = eval { require Type::Tiny::XS; 1 } ? sub(){!!1} : sub(){!!0};
  1         246  
  0         0  
12 1 50       6 *HAS_NATIVE = ($] ge '5.032') ? sub(){!!1} : sub(){!!0};
13 1   50     3 *perlstring = eval { require B; 'B'->can('perlstring') } || sub { sprintf '"%s"', quotemeta($_[0]) };
14             };
15              
16             sub import {
17 1     1   8 my ( $caller, $me ) = ( scalar(caller), shift );
18            
19 1         2 my $imports;
20 1 50 33     12 if ( @_==1 and ref($_[0]) eq 'HASH' ) {
21 0         0 $imports = $_[0];
22             }
23             else {
24 1         3 my %imports = map { $me->subname_for($_) => $_ } @_;
  2         5  
25 1         2 $imports = \%imports;
26             }
27            
28 1         3 $me->setup_for($caller, $imports);
29             }
30              
31             sub subname_for {
32 2     2 0 5 my ( $me, $class ) = ( shift, @_ );
33 2         11 $class =~ s/\W+/_/g;
34 2         9 'isa_' . $class;
35             }
36              
37             my %cache;
38             sub setup_for {
39 1     1 0 3 my ( $me, $caller, $imports ) = ( shift, @_ );
40            
41 1         5 while ( my ($subname, $class) = each %$imports ) {
42 1     1   7 no strict 'refs';
  1         2  
  1         41  
43 1     1   6 no warnings 'redefine';
  1         2  
  1         296  
44 2         1399 *{"$caller\::$subname"} = (
45 2   50     9 $cache{$class} ||= $me->generate_coderef($class)
46             or die("Problem generating coderef for $class")
47             );
48             }
49             }
50              
51             sub generate_coderef {
52 2     2 0 4 my ( $me, $class ) = ( shift, @_ );
53            
54 2         3 my $coderef;
55 2         3 if ( HAS_XS ) {
56             my $native_will_be_faster = 0;
57            
58             if ( HAS_NATIVE ) {
59             my $class_isa = eval { $class->can('isa') };
60             if ( $class_isa and $class_isa != \&UNIVERSAL::isa ) {
61             $native_will_be_faster = 1;
62             }
63             }
64            
65             unless ($native_will_be_faster) {
66             my $typename = sprintf('InstanceOf[%s]', $class);
67             $coderef = Type::Tiny::XS::get_coderef_for($typename);
68             return $coderef if $coderef;
69             }
70             }
71            
72 2         2 my $code;
73 2         3 if ( HAS_NATIVE ) {
74             $code = sprintf(
75             q{ package isa::__NATIVE__; use feature q[isa]; no warnings q[experimental::isa]; sub { $_[0] isa %s } },
76             perlstring($class),
77             );
78             }
79             else {
80 2         9 require Scalar::Util;
81 2         12 $code = sprintf(
82             q{ package isa::__LEGACY__; sub { Scalar::Util::blessed($_[0]) and $_[0]->isa(%s) } },
83             perlstring($class),
84             );
85             }
86            
87 2 50   3   178 $coderef = eval $code;
  3 50       37  
  3         159  
88 2 50       16 ref($coderef) ? $coderef : ();
89             }
90              
91             1;
92              
93             __END__