File Coverage

blib/lib/FFI/Platypus/Type/Enum.pm
Criterion Covered Total %
statement 65 66 98.4
branch 41 42 97.6
condition 7 9 77.7
subroutine 11 11 100.0
pod 0 1 0.0
total 124 129 96.1


line stmt bran cond sub pod time code
1             package FFI::Platypus::Type::Enum;
2              
3 1     1   247575 use strict;
  1         8  
  1         31  
4 1     1   6 use warnings;
  1         2  
  1         28  
5 1     1   6 use constant 1.32 ();
  1         15  
  1         17  
6 1     1   13 use 5.008001;
  1         3  
7 1     1   541 use Ref::Util qw( is_plain_arrayref is_plain_hashref is_ref );
  1         1620  
  1         72  
8 1     1   7 use Scalar::Util qw( dualvar );
  1         2  
  1         58  
9 1     1   7 use Carp qw( croak );
  1         2  
  1         767  
10              
11             # ABSTRACT: Custom platypus type for dealing with C enumerated types
12             our $VERSION = '0.05'; # VERSION
13              
14              
15             our @CARP_NOT = qw( FFI::Platypus );
16              
17             sub ffi_custom_type_api_1
18             {
19             my %config = defined $_[2] && is_plain_hashref $_[2]
20 13 100 66 13 0 57485 ? %{ splice(@_, 2, 1) }
  8         63  
21             : ();
22 13         39 my(undef, undef, @values) = @_;
23              
24 13         21 my $index = 0;
25 13         24 my %str_lookup;
26             my %int_lookup;
27 13 100       32 my $prefix = defined $config{prefix} ? $config{prefix} : '';
28 13   100     51 $config{rev} ||= 'str';
29 13 100       198 ($config{rev} =~ /^(int|str|dualvar)$/) or croak("rev must be either 'int', 'str', or 'dualvar'");
30              
31 12         25 foreach my $value (@values)
32             {
33 38         59 my $name;
34             my @aliases;
35              
36 38 100       87 if(is_plain_arrayref $value)
    100          
37             {
38 11         17 my %opt;
39 11 100       25 if(@$value % 2)
40             {
41 1         4 ($name,%opt) = @$value;
42             }
43             else
44             {
45 10         27 ($name,$index,%opt) = @$value;
46             }
47 11 100       16 @aliases = @{ delete $opt{alias} || [] };
  11         39  
48 11 100       28 croak("unrecognized options: @{[ sort keys %opt ]}") if %opt;
  1         109  
49             }
50             elsif(!is_ref $value)
51             {
52 26         39 $name = $value;
53             }
54             else
55             {
56 1         123 croak("not a array ref or scalar: $value");
57             }
58              
59 36 100       74 if($index < 0)
60             {
61 2   50     13 $config{type} ||= 'senum';
62             }
63              
64 36 100       72 if(my $packages = $config{package})
65             {
66 8 100       20 foreach my $package (is_plain_arrayref $packages ? @$packages : $packages)
67             {
68 10         20 foreach my $name ($name,@aliases)
69             {
70 14         42 my $full = join '::', $package, $prefix . uc($name);
71 14         404 constant->import($full, $index);
72             }
73             }
74             }
75              
76 36 100       183 croak("$name declared twice") if exists $str_lookup{$name};
77              
78 35 100       84 $int_lookup{$index} = $name unless exists $int_lookup{$index};
79 35         69 $str_lookup{$_} = $index for @aliases;
80 35         114 $str_lookup{$name} = $index++;
81             }
82              
83 9   100     40 $config{type} ||= 'enum';
84              
85 9 100       19 if(defined $config{maps})
86             {
87 1 50       4 if(is_plain_arrayref $config{maps})
88             {
89 1         2 @{ $config{maps} } = (\%str_lookup, \%int_lookup, $config{type});
  1         4  
90             }
91             else
92             {
93 0         0 croak("maps is not an array reference");
94             }
95             }
96              
97             my %type = (
98             native_type => $config{type},
99             perl_to_native => sub {
100             exists $str_lookup{$_[0]}
101             ? $str_lookup{$_[0]}
102 32 100   32   9956 : exists $int_lookup{$_[0]}
    100          
103             ? $_[0]
104             : croak("illegal enum value $_[0]");
105             },
106 9         53 );
107              
108 9 100       32 if($config{rev} eq 'str')
    100          
109             {
110             $type{native_to_perl} = sub {
111             exists $int_lookup{$_[0]}
112 16 100   16   1261 ? $int_lookup{$_[0]}
113             : $_[0];
114             }
115 7         23 }
116             elsif($config{rev} eq 'dualvar')
117             {
118             $type{native_to_perl} = sub {
119             exists $int_lookup{$_[0]}
120 4 100   4   2767 ? dualvar( $_[0], $int_lookup{$_[0]} )
121             : $_[0];
122 1         4 };
123             }
124              
125 9         38 \%type;
126             }
127              
128             1;
129              
130             __END__