File Coverage

blib/lib/Object/Anon.pm
Criterion Covered Total %
statement 46 46 100.0
branch 6 6 100.0
condition 2 2 100.0
subroutine 13 13 100.0
pod 0 1 0.0
total 67 68 98.5


line stmt bran cond sub pod time code
1             package Object::Anon;
2             $Object::Anon::VERSION = '0.002';
3             # ABSTRACT: Create objects on the fly
4              
5 7     7   180305 use strict;
  7         20  
  7         273  
6 7     7   274 use warnings;
  7         15  
  7         234  
7              
8 7     7   46 use Carp qw(croak);
  7         12  
  7         513  
9              
10 7     7   38 use Exporter qw(import);
  7         13  
  7         649  
11             our @EXPORT = qw(anon);
12              
13             sub anon (%) {
14 7     7 0 1465 my ($hash) = @_;
15 7         36 return _objectify($hash);
16             }
17              
18 7     7   13931 use overload ();
  7         7408  
  7         1234  
19             my %overload_ops = map { $_ => 1 } map { split /\s+/, $_ } values %overload::ops;
20              
21             my $anon_class_id = 0;
22              
23             sub _objectify {
24 12     12   27 my ($hash, $seen) = @_;
25 12   100     69 $seen ||= {};
26              
27 12 100       49 if ($seen->{$hash}) {
28 1         29 croak "circular reference detected";
29             }
30 11         45 $seen->{$hash} = 1;
31              
32 11         38 my $class = "Object::Anon::__ANON__::".$anon_class_id++;
33              
34 11         46 for my $key (keys %$hash) {
35 10 100       71 if ($overload_ops{$key}) {
36 1         6 $class->overload::OVERLOAD($key => _value_sub($hash->{$key}, $seen));
37             }
38             else {
39 7     7   46 no strict 'refs';
  7         13  
  7         2067  
40 9         40 *{$class."::".$key} = _value_sub($hash->{$key}, $seen);
  8         126  
41             }
42             }
43              
44 10         72 return bless do { \my %o }, $class;
  10         61  
45             }
46              
47             sub _value_sub {
48 13     13   32 my ($value, $seen) = @_;
49              
50 13         20 do {
51             {
52 5     5   28 HASH => sub { my $o = _objectify($value, $seen); sub { $o } },
  4         29  
  8         116  
53 1     1   3 ARRAY => sub { my @o = map { _value_sub($_, $seen)->() } @$value; sub { \@o } },
  3         10  
  1         4  
  7         110  
54 2     2   18 CODE => sub { $value },
55 5     5   48 }->{ref $value} || sub { sub { $value } }
  4         29  
56 13 100       261 }->();
57             }
58              
59             1;
60             __END__