File Coverage

blib/lib/FFI/Platypus/Type/Enum.pm
Criterion Covered Total %
statement 59 60 98.3
branch 35 36 97.2
condition 7 9 77.7
subroutine 9 9 100.0
pod 0 1 0.0
total 110 115 95.6


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