File Coverage

blib/lib/App/Table2YAML/Serializer.pm
Criterion Covered Total %
statement 94 96 97.9
branch 22 26 84.6
condition 9 15 60.0
subroutine 16 16 100.0
pod 1 1 100.0
total 142 154 92.2


line stmt bran cond sub pod time code
1             package App::Table2YAML::Serializer;
2              
3 1     1   5 use common::sense;
  1         2  
  1         7  
4 1     1   44 use charnames q(:full);
  1         44  
  1         7  
5 1     1   201 use English qw[-no_match_vars];
  1         1  
  1         7  
6 1     1   4892 use Scalar::Util qw[looks_like_number];
  1         1  
  1         58  
7 1     1   4 use List::Util qw[first];
  1         2  
  1         53  
8 1     1   5 use Moo;
  1         1  
  1         7  
9 1     1   1259 use Unicode::CaseFold qw[case_fold];
  1         1015  
  1         222  
10              
11             our $VERSION = '0.002'; # VERSION
12              
13             has allow_nulls => (
14             is => q(rw),
15             isa => sub { $_[0] == 0 || $_[0] == 1 },
16             default => 1,
17             );
18              
19             sub serialize {
20 6     6 1 9 my $self = shift;
21 6         51 my @table = splice @_;
22              
23 6 50       16 return unless @table;
24              
25 6         11 my @header = @{ shift @table };
  6         22  
26 6         14 foreach (@header) { s{\A\p{IsSpace}+}{}msx; s{\p{IsSpace}+\z}{}msx; }
  39         70  
  39         97  
27              
28 6         13 my @yaml;
29 6         19 while ( my $row = shift @table ) {
30 408         402 my @row;
31 408         1014 while ( my ( $i, $header ) = each @header ) {
32 1752         2407 my $data = $row->[$i];
33 1752         3283 $data = $self->_serialize_scalar_data($data);
34 1752 50 33     36813 next if !( $self->allow_nulls() ) && $data eq q(null);
35 1752         12947 my %column = ( $header => $data );
36 1752         8689 push @row, {%column};
37             }
38 408 50       749 if (@row) {
39 408         807 my $yaml_record = $self->_serialize_row(@row);
40 408         2146 push @yaml, $yaml_record;
41             }
42             }
43              
44 6         158 return @yaml;
45             } ## end sub serialize
46              
47             sub _serialize_row {
48 408     408   471 my $self = shift;
49 408         835 my @row = splice @_;
50              
51 408         550 foreach my $column (@row) {
52 1752         3309 $column = $self->_serialize_hash($column);
53             }
54              
55 408         862 my $row = join qq(\N{COMMA}\N{SPACE}), @row;
56 408         936 $row = sprintf q(- [ %s ]), $row;
57              
58 408         948 return $row;
59             }
60              
61             sub _serialize_hash {
62 1752     1752   1669 my $self = shift;
63 1752         1563 my %hash = %{ +shift };
  1752         4450  
64              
65 1752         2015 my @hash;
66 1752         3908 while ( my ( $key, $value ) = each %hash ) {
67 1752         2753 my $pair = join qq(\N{COLON}\N{SPACE}), $key, $value;
68 1752         5213 push @hash, $pair;
69             }
70              
71 1752         2417 my $hash = join qq(\N{COMMA}), @hash;
72 1752         3449 $hash = sprintf q({%s}), $hash;
73              
74 1752         5211 return $hash;
75             } ## end sub _serialize_hash
76              
77             sub _serialize_scalar_data {
78 1752     1752   1989 my $self = shift;
79 1752         1842 my $data = shift;
80              
81 1752         2342 foreach ($data) {
82              
83 1752 50 33     11462 if ( !(defined) || $_ eq q() || m{^\p{IsSpace}+$}msx ) {
      33        
84 0         0 $_ = q(null);
85 0         0 last;
86             }
87              
88 1752         3276 s{\A\p{IsSpace}+}{}msx;
89 1752         2339 s{\p{IsSpace}+\z}{}msx;
90              
91 1752         3002 my $scalar_value = $self->_define_scalar_value($_);
92              
93 1752 100       5155 if ( $scalar_value eq q(string) ) {
    100          
94 513         609 s{"}{\\"}gmsx;
95 513         1484 $_ = qq("$_");
96             }
97             elsif ( $scalar_value eq q(inf_or_nan) ) {
98 18         76 s{^[+-]?\K}{.}msx;
99             }
100              
101             } ## end foreach ($data)
102              
103 1752         3166 return $data;
104             } ## end sub _serialize_scalar_data
105              
106             sub _define_scalar_value {
107 1752     1752   2163 my $self = shift;
108 1752         1891 my $value = shift;
109              
110 1752         1561 my $scalar_value;
111              
112 1752         3429 my $nv = looks_like_number($_);
113 1752 100       2864 if ( $nv != 0 ) {
114 1176 100 100     4559 if ( $nv == 36 ) {
    100          
115 9         11 $scalar_value = q(inf_or_nan);
116             }
117             elsif ( $nv == 20 || $nv == 28 ) {
118 15 100   36   61 if ( first { case_fold($value) eq $_ }
  36         108  
119             qw[infinity -infinity +infinity] )
120             {
121 6         13 $scalar_value = q(string);
122             }
123 9         16 else { $scalar_value = q(inf_or_nan) }
124             }
125 1152         1460 else { $scalar_value = q(numeric); }
126             }
127             else {
128 576 100 100 4464   3981 if ( first { case_fold($value) eq $_ }
  4464 100       11086  
    100          
129             qw[y true yes on n false no off] )
130             {
131 36         57 $scalar_value = q(boolean);
132             }
133 1077     1077   5275 elsif ( first { case_fold($value) eq $_ } qw[~ null] ) {
134 3         5 $scalar_value = q(null);
135             }
136             elsif ($value =~ m{^[+-]?0x[0-9A-F]+$}imsx
137             || $value
138             =~ m{^[+-]?(?:[0-9]{1,3})(?:_[0-9]{3})*(?:\.[0-9]+)?$}msx )
139             {
140 30         47 $scalar_value = q(numeric);
141             }
142 507         707 else { $scalar_value = q(string); }
143             } ## end else [ if ( $nv != 0 ) ]
144              
145 1752         4926 return $scalar_value;
146             } ## end sub _define_scalar_value
147              
148 1     1   5200 no Moo;
  1         4  
  1         10  
149             __PACKAGE__->meta->make_immutable;
150              
151             1;
152              
153             __END__