File Coverage

blib/lib/Object/FromData/Hash.pm
Criterion Covered Total %
statement 53 62 85.4
branch 14 24 58.3
condition 1 2 50.0
subroutine 10 14 71.4
pod 7 7 100.0
total 85 109 77.9


line stmt bran cond sub pod time code
1             package Object::FromData::Hash;
2              
3 3     3   10 use strict;
  3         4  
  3         65  
4 3     3   9 use warnings;
  3         2  
  3         54  
5 3     3   10 use Digest::MD5 'md5_hex'; # convenience, not security
  3         2  
  3         365  
6              
7             sub _new {
8 3     3   4 my ( $class, $arg_for ) = @_;
9              
10 3         4 my $hashref = $arg_for->{ref};
11 3   50     13 my $allow_private = $arg_for->{allow_private} || 0;
12 3         19 my @all_keys = sort CORE::keys %$hashref;
13 3 50       6 my @keys = $allow_private ? @all_keys : grep { !/^_/ } @all_keys;
  12         20  
14              
15 3         21 my $new_class = "${class}::" . md5_hex( join '-' => @keys );
16             {
17 3     3   11 no strict 'refs';
  3         17  
  3         417  
  3         5  
18 3         4 @{"${new_class}::ISA"} = $class;
  3         37  
19             }
20              
21 3         4 my %hash;
22 3         10 my $self = {
23             hash => \%hash,
24             keys => \@keys,
25             allow_private => $allow_private,
26             current_index => 0,
27             };
28              
29 3         6 KEY: foreach my $key (@all_keys) {
30 12         12 my $value = $hashref->{$key};
31 12 100       20 if ( !ref $value ) {
    100          
    50          
32 10         20 $hash{$key} = $value;
33             }
34             elsif ( 'ARRAY' eq ref $value ) {
35 1         7 $hash{$key}
36             = Object::FromData::Array->_new( { ref => $value } );
37             }
38             elsif ( 'HASH' eq ref $value ) {
39 1         6 $hash{$key} = $class->_new( { ref => $value } );
40             }
41             else {
42 0         0 die "Don't yet handle $value";
43             }
44 12 100       24 if ( $key =~ /^_/ ) {
45 1 50       4 next KEY unless $allow_private;
46             }
47 3     3   11 no strict 'refs';
  3         3  
  3         774  
48 11     10   21 *{"$new_class::$key"} = sub { $hash{$key} };
  11         39  
  10         719  
49             }
50 3         12 return bless $self => $new_class;
51             }
52              
53             sub keys {
54 1     1 1 3 my $self = shift;
55 1 50       6 $self = shift if @_;
56 1         2 return keys %{ $self->{hash} };
  1         15  
57             }
58              
59             sub values {
60 0     0 1 0 my $self = shift;
61 0 0       0 $self = shift if @_;
62 0         0 return values %{ $self->{hash} };
  0         0  
63             }
64              
65             sub reset {
66 0     0 1 0 my $self = shift;
67 0 0       0 $self = shift if @_;
68 0         0 $self->{current_index} = 0;
69             }
70              
71             sub has_more {
72 6     6 1 1796 my $self = shift;
73 6 100       15 $self = shift if @_;
74 6         9 my $keys = $self->{keys};
75 6         17 return $self->{current_index} <= $#$keys;
76             }
77              
78             sub each {
79 4     4 1 3 my $self = shift;
80 4 50       7 $self = shift if @_;
81 4         3 my $keys = $self->{keys};
82 4 50       7 return unless $self->{current_index} <= $#$keys;
83 4         6 my $key = $self->{keys}[ $self->{current_index}++ ];
84 4         9 return $key, $self->$key;
85             }
86              
87 0     0 1   sub is_hashref {1}
88       0 1   sub is_arrayref { }
89              
90             1;
91              
92             __END__