File Coverage

lib/Google/RestApi/Utils.pm
Criterion Covered Total %
statement 111 115 96.5
branch 38 42 90.4
condition 2 5 40.0
subroutine 26 27 96.3
pod 0 10 0.0
total 177 199 88.9


line stmt bran cond sub pod time code
1             package Google::RestApi::Utils;
2              
3 1     1   25049 use strict;
  1         3  
  1         32  
4 1     1   10 use warnings;
  1         2  
  1         44  
5              
6             our $VERSION = '1.0.4';
7              
8 1     1   6 use feature 'state';
  1         2  
  1         81  
9              
10 1     1   6 use autodie;
  1         3  
  1         8  
11 1     1   7023 use File::Spec::Functions qw( catfile );
  1         5  
  1         79  
12 1     1   6 use File::Basename qw( dirname );
  1         2  
  1         68  
13 1     1   1206 use Hash::Merge ();
  1         8228  
  1         26  
14 1     1   10 use Log::Log4perl qw( :easy );
  1         2  
  1         11  
15 1     1   908 use Scalar::Util qw( blessed );
  1         6  
  1         47  
16 1     1   14 use Type::Params qw( compile compile_named );
  1         4  
  1         12  
17 1     1   490 use Types::Standard qw( Str StrMatch HashRef Any slurpy );
  1         2  
  1         14  
18 1     1   3038 use YAML::Any qw( Dump LoadFile );
  1         2  
  1         5  
19              
20 1     1   730 use Google::RestApi::Types qw( ReadableFile );
  1         17  
  1         9  
21              
22 1     1   711 no autovivification;
  1         3  
  1         10  
23              
24 1     1   58 use Exporter qw(import);
  1         19  
  1         1373  
25             our @EXPORT_OK = qw(
26             named_extra
27             merge_config_file resolve_config_file_path
28             flatten_range
29             bool
30             dim_any dims_any dims_all
31             cl_black cl_white
32             strip
33             );
34             our %EXPORT_TAGS = (all => [ @EXPORT_OK ]);
35              
36             # used by validation with type::params.
37             # similar to allow_extra in params::validate, simply returns the
38             # extra key/value pairs we aren't interested in in the checked
39             # argument hash.
40             sub named_extra {
41 932     932 0 25140 state $check = compile_named(
42             _extra_ => HashRef,
43             validated => slurpy HashRef,
44             );
45 932         6539 my $p = $check->(@_);
46 931         24903 my $extra = delete $p->{_extra_};
47              
48 931         1519 my %p;
49 931 50       2826 %p = %{ $p->{validated} } if $p->{validated}; # these are validated by the caller.
  931         3066  
50 931         4136 @p{ keys %$extra } = values %$extra; # stuff back the ones the caller wasn't interested in.
51 931         3462 return \%p;
52             }
53              
54             sub merge_config_file {
55 301     301 0 2950 state $check = compile_named(
56             config_file => ReadableFile, { optional => 1 },
57             _extra_ => slurpy Any,
58             );
59 301         55671 my $passed_config = named_extra($check->(@_));
60              
61 299         986 my $config_file = $passed_config->{config_file};
62 299 100       1050 return $passed_config if !$config_file;
63              
64 154         330 my $config_from_file = eval { LoadFile($config_file); };
  154         552  
65 154 50       588365 LOGDIE "Unable to load config file '$config_file': $@" if $@;
66              
67             # left_precedence, the passed config wins over anything in the file.
68             # can't merge coderefs, error comes from Storable buried deep in hash::merge.
69 154         708 my $merged_config = Hash::Merge::merge($passed_config, $config_from_file);
70 154         14181 TRACE("Config used:\n". Dump($merged_config));
71              
72 154         478938 return $merged_config;
73             }
74              
75             # a standard way to store file names in a config and resolve them
76             # to a full path. can be used in Auth configs, possibly others.
77             # see sub RestApi::auth for more.
78             sub resolve_config_file_path {
79 288     288 0 4293 state $check = compile(HashRef, Str);
80 288         3524 my ($config, $file_key) = $check->(@_);
81              
82 288 100       3995 my $config_file = $config->{$file_key} or return;
83 145 100       2052 return $config_file if -f $config_file;
84              
85 143         448 my $full_file_path;
86 143 100 66     1142 if ($file_key ne 'config_file' && $config->{config_file}) {
87 2         80 my $dir = dirname($config->{config_file});
88 2         18 my $path = catfile($dir, $config_file);
89 2 100       55 $full_file_path = $path if -f $path
90             }
91              
92 143 100       469 if (!$full_file_path) {
93 142         459 my $dir = $config->{config_dir};
94 142 100       393 if ($dir) {
95 139         1036 my $path = catfile($dir, $config_file);
96 139 50       2794 $full_file_path = $path if -f $path
97             }
98             }
99            
100 143 100       626 LOGDIE("Unable to resolve config file '$file_key => $config_file' to a full file path")
101             if !$full_file_path;
102              
103             # action at a distance, but is convenient to stuff the real file name in the config here.
104 140         406 $config->{$file_key} = $full_file_path;
105            
106 140         449 return $full_file_path;
107             }
108              
109             # these are just used for debug message just above
110             # to display the original range in a pretty format.
111             sub flatten_range {
112 861     861 0 86776 my $range = shift;
113 861 100       2711 $range = $range->range_to_hash() if blessed($range);
114 861 100       1819 return 'False' if !$range;
115 818 100       3182 return $range if !ref($range);
116 254 100       765 return _flatten_range_hash($range) if ref($range) eq 'HASH';
117 104 50       372 return _flatten_range_array($range) if ref($range) eq 'ARRAY';
118 0         0 LOGDIE("Unable to flatten: " . ref($range));
119             }
120              
121             sub _flatten_range_hash {
122 150     150   269 my $range = shift;
123 150         684 my @flat = map { "$_ => " . flatten_range($range->{$_}); } sort keys %$range;
  287         789  
124 150         449 my $flat = join(', ', @flat);
125 150         733 return "{ $flat }";
126             }
127              
128             sub _flatten_range_array {
129 104     104   172 my $range = shift;
130 104         222 my @flat = map { flatten_range($_); } @$range;
  187         341  
131 104         320 my $flat = join(', ', @flat);
132 104         563 return "[ $flat ]";
133             }
134              
135             # changes perl boolean to json boolean.
136             sub bool {
137 25     25 0 4475 my $bool = shift;
138 25 100       128 return 'true' if !defined $bool; # bold() should turn on bold.
139 12 100       98 return 'false' if $bool =~ qr/^false$/i;
140 10 100       76 return $bool ? 'true' : 'false'; # converts bold(0) to 'false'.
141             }
142              
143             sub dims_any {
144 223     223 0 497 state $check = compile(StrMatch[qr/^(col|row)/i]);
145 223         4028 my ($dims) = $check->(@_);
146 222 100       4019 return $dims =~ /^col/i ? "COLUMNS" : "ROWS";
147             }
148              
149             sub dims_all {
150 3     3 0 8 my $dims = eval { dims_any(@_); };
  3         8  
151 3 100       210 return $dims if $dims;
152 1         8 state $check = compile(StrMatch[qr/^all/i]);
153 1         3586 ($dims) = $check->(@_);
154 1         23 return "ALL";
155             }
156              
157 5     5 0 148 sub cl_black { { red => 0, blue => 0, green => 0, alpha => 1 }; }
158 5     5 0 31 sub cl_white { { red => 1, blue => 1, green => 1, alpha => 1 }; }
159              
160             sub strip {
161 0   0 0 0   my $p = shift // '';
162 0           $p =~ s/^\s+|\s+$//g;
163 0           return $p;
164             }
165              
166             1;