File Coverage

blib/lib/Sub/Implant.pm
Criterion Covered Total %
statement 80 86 93.0
branch 26 34 76.4
condition 13 16 81.2
subroutine 18 19 94.7
pod 2 2 100.0
total 139 157 88.5


line stmt bran cond sub pod time code
1             package Sub::Implant;
2              
3 2     2   76880 use 5.010;
  2         7  
  2         78  
4 2     2   11 use strict;
  2         2  
  2         145  
5 2     2   25 use warnings;
  2         8  
  2         108  
6              
7             =head1 NAME
8              
9             Sub::Implant - Make a named sub out of a subref
10              
11             =head1 VERSION
12              
13             Version 2.02
14              
15             =cut (remainder of POD after __END__)
16              
17             our $VERSION = '2.02';
18              
19 2     2   10 use Carp;
  2         5  
  2         993  
20              
21             sub import {
22 6     6   11436 my $class = shift;
23 6         34 $class->_import_into(scalar caller, @_);
24             }
25              
26             sub _import_into {
27 6     6   13 my $class = shift;
28 6         16 my ($client, @arg) = @_;
29 6 100       27 unshift @arg, qw(implant) unless @arg; # default export
30 6         28 my %export = (
31             implant => \ &implant,
32             infuse => \ &infuse,
33             );
34              
35 6         20 while ( @arg ) {
36 6         21 my $export = shift @arg;
37 6 50       24 my $code = $export{$export} or croak(
38             "$export is not exported by the $class module"
39             );
40 6 100       24 my %opt = %{ shift @arg } if ref $arg[0] eq 'HASH';
  1         6  
41 6   66     32 my $name = $opt{as} // $export;
42 6         17 implant($client, $name, $code);
43             }
44             }
45              
46             sub infuse {
47 1     1 1 450 my ($package, $what, %opt) = @_;
48 1         5 for my $name ( keys %$what ) {
49 2         6 my $code = $what->{$name};
50 2         10 implant($package, $name, $code, %opt)
51             }
52             }
53              
54             sub implant {
55 18     18 1 4838 my ($name, $sub, %opt) = _get_args(scalar caller, @_);
56 14         47 _do_define($name, $sub, %opt);
57 14 100       62 _do_name($name, $sub, %opt) if $opt{name};
58 14         13900 $sub
59             }
60              
61 2     2   12 use Scalar::Util qw(reftype);
  2         3  
  2         899  
62              
63             sub _get_args {
64             # pick up caller
65 18     18   29 my $caller = shift;
66              
67             # unwrap original arguments
68 18 100       341 croak "Name and subref must be given" if @_ < 2;
69 16   50     5190 $_ //= '' for @_;
70            
71 16 100 100     189 if ( (reftype $_[1] // '') eq 'CODE' ) {
    100 100        
72 4         11 unshift @_, ''; # dummy package
73             } elsif ( (reftype $_[2] // '') ne 'CODE' ) {
74 1         129 croak "No subref given";
75             }
76 15         43 my ($package, $name, $sub, %opt) = @_;
77 15   100     70 $opt{redef} //= 0;
78 15   100     60 $opt{name} //= 1;
79              
80             # build full name
81 15 100       45 if ( $name =~ /::/ ) {
82 4 100       124 croak "Can't specify package and qualified name" if $package;
83             } else {
84 11   66     27 $package ||= $caller;
85 11         29 $name = join '::', $package, $name;
86             }
87              
88             # all checked and set
89 14         93 ($name, $sub, %opt)
90             }
91              
92             sub _do_define {
93 14     14   36 my ($name, $sub, %opt) = @_;
94 14 100       72 if ( defined &$name ) {
95 2 100       135 carp "Subroutine $name redefined" unless $opt{redef};
96             }
97 2     2   12 no warnings 'redefine';
  2         9  
  2         72  
98 2     2   9 no strict 'refs';
  2         3  
  2         285  
99 14         98 *$name = $sub;
100             }
101              
102             sub _do_name_off {
103 0     0   0 my ($name, $sub, %opt) = @_;
104 0         0 my $old_name = _get_subname($sub);
105 0 0       0 return if $old_name;
106 0 0       0 _check_match($name, $sub, $old_name) unless $opt{lie}; # option 'lie' unused
107 0         0 _subname($name, $sub);
108 0         0 return;
109             }
110              
111 2     2   1900 use Sub::Identify qw(sub_name);
  2         2270  
  2         147  
112 2     2   2558 use Sub::Name qw(subname);
  2         2401  
  2         420  
113              
114             sub _do_name {
115 13     13   30 my ($name, $sub, %opt) = @_;
116 13         45 my $old_name = sub_name($sub);
117 13 100       110 return if $old_name ne '__ANON__';
118 3 50       14 _check_match($name, $sub, $old_name) unless $opt{lie}; # option 'lie' unused
119 3         22 subname($name, $sub);
120 3         6 return;
121             }
122              
123             sub _check_match {
124             # see if a name points to a given subref
125 3     3   7 my ($name, $sub, $old_name) = @_;
126 3         4 my $reached = do {
127 2     2   27 no strict 'refs';
  2         4  
  2         276  
128 3         11 *$name{CODE}
129             };
130 3 50       12 croak(
131             "Won't rename $old_name to undefined $name'"
132             ) unless $reached;
133 3 50       12 croak(
134             "Won't rename $old_name to non-matching $name"
135             ) unless $reached == $sub;
136             }
137              
138             1 # End of Sub::Implant
139             __END__