File Coverage

blib/lib/Class/XSReader.pm
Criterion Covered Total %
statement 44 62 70.9
branch 22 46 47.8
condition 9 36 25.0
subroutine 7 9 77.7
pod n/a
total 82 153 53.5


line stmt bran cond sub pod time code
1 1     1   3826 use 5.008008;
  1         5  
2 1     1   8 use strict;
  1         2  
  1         34  
3 1     1   5 use warnings;
  1         3  
  1         80  
4 1     1   6 use Class::XSConstructor ();
  1         2  
  1         170  
5              
6             package Class::XSReader;
7              
8             BEGIN {
9 1     1   5 our $AUTHORITY = 'cpan:TOBYINK';
10 1         2 our $VERSION = '0.023006';
11            
12 1 50       3 if ( eval { require Types::Standard; 1 } ) {
  1         6  
  1         6  
13 1         9 Types::Standard->import(
14             qw/ is_ArrayRef is_HashRef is_ScalarRef is_CodeRef is_Object /
15             );
16             }
17             else {
18 0         0 eval q|
19             require Scalar::Util;
20             sub is_ArrayRef ($) { ref $_[0] eq 'ARRAY' }
21             sub is_HashRef ($) { ref $_[0] eq 'HASH' }
22             sub is_ScalarRef ($) { ref $_[0] eq 'SCALAR' or ref $_[0] eq 'REF' }
23             sub is_CodeRef ($) { ref $_[0] eq 'CODE' }
24             sub is_Object ($) { !!Scalar::Util::blessed($_[0]) }
25             |;
26             }
27             };
28              
29             sub import {
30 3     3   74 my $class = shift;
31            
32 3         7 my $package;
33 3 50       15 if ( 'SCALAR' eq ref $_[0] ) {
34 0         0 $package = ${+shift};
  0         0  
35             }
36 3   33     28 $package ||= our($SETUP_FOR) || caller;
      33        
37            
38 3         10 while ( @_ ) {
39 3         7 my $slot = shift;
40 3 50       11 my $thing = ref($_[0]) ? shift : {};
41 3         7 my %spec;
42             my $type;
43            
44 3 50       16 if ( is_ArrayRef $thing ) {
    50          
    0          
45 0         0 %spec = @$thing;
46             }
47             elsif ( is_HashRef $thing ) {
48 3         16 %spec = %$thing;
49             }
50             elsif ( is_CodeRef $thing ) {
51 0         0 %spec = ( default => $thing );
52             }
53             else {
54 0         0 Exporter::Tiny::_croak( "Expected ARRAY/HASH/CODE reference, not $thing" );
55             }
56            
57 3 50       13 if ( $slot =~ /\A(.*)\!\z/ ) {
58 0         0 $slot = $1;
59 0         0 $spec{required} = !!1;
60             }
61            
62 3 50       10 $spec{lazy} = 1 unless exists $spec{lazy};
63            
64 3 50 33     30 if ( is_Object $spec{isa} and $spec{isa}->can('compiled_check') ) {
    0 0        
65 3         49 $type = $spec{isa};
66 3         10 $spec{isa} = $type->compiled_check;
67             }
68             elsif ( is_Object $spec{isa} and $spec{isa}->can('check') ) {
69             # Support it for compatibility with more basic Type::API::Constraint
70             # implementations, but this will be slowwwwww!
71 0         0 $type = $spec{isa};
72 0     0   0 $spec{isa} = sub { !! $type->check($_[0]) };
  0         0  
73             }
74            
75 3 0 33     28 if ( defined $spec{coerce} and !ref $spec{coerce} and $spec{coerce} eq 1 ) {
      33        
76 0         0 my $c;
77 0 0 0     0 if (
    0 0        
      0        
      0        
78             $type->can('has_coercion')
79             and $type->has_coercion
80             and $type->can('coercion')
81             and is_Object( $c = $type->coercion )
82             and $c->can('compiled_coercion') ) {
83 0         0 $spec{coerce} = $c->compiled_coercion;
84             }
85             elsif ( $type->can('coerce') ) {
86 0     0   0 $spec{coerce} = sub { $type->coerce($_[0]) };
  0         0  
87             }
88             }
89            
90 3         35 my @unknown_keys = grep !/\A(isa|required|is|lazy|default|builder|coerce|init_arg|trigger|weak_ref|alias|slot_initializer|undef_tolerant|reader|clone|clone_on_write|clone_on_read)\z/, keys %spec;
91 3 50       10 if ( @unknown_keys ) {
92 0         0 _croak("Unknown keys in spec: %s", join ", ", sort @unknown_keys);
93             }
94            
95 3 100 66     16 my $has_default = ( exists $spec{default} or defined $spec{builder} ) ? !!$spec{lazy} : 0;
96 3         7 my $has_type = exists $spec{isa};
97 3   66     20 my $clone = ( $spec{clone_on_read} or $spec{clone} );
98            
99             my @XS_args = (
100             sprintf( '%s::%s', $package, exists($spec{reader}) ? $spec{reader} : $slot ),
101             $slot,
102             $has_default,
103             $has_default ? Class::XSConstructor::_common_default( $spec{default} ) : 0,
104             $has_default ? Class::XSConstructor->_canonicalize_defaults( \%spec ) : undef,
105             $has_type ? Class::XSConstructor::_type_to_number( $type ) : 15,
106             $has_type ? $spec{isa} : undef,
107             $has_type ? $spec{coerce} : undef,
108 3 50       32 $clone ? $clone : undef,
    100          
    100          
    50          
    50          
    50          
    100          
109             );
110            
111 3 50       17 if (our $REDEFINE) {
112 1     1   6557 no warnings 'redefine';
  1         22  
  1         228  
113 0         0 Class::XSConstructor::install_reader( @XS_args );
114             }
115             else {
116 3         3033 Class::XSConstructor::install_reader( @XS_args );
117             }
118             }
119             }
120              
121             1;
122              
123             __END__