File Coverage

blib/lib/Data/Resolver/Asset.pm
Criterion Covered Total %
statement 110 139 79.1
branch 20 30 66.6
condition 10 13 76.9
subroutine 20 24 83.3
pod 9 9 100.0
total 169 215 78.6


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             package Data::Resolver::Asset;
3 6     6   112928 use v5.24;
  6         22  
4 6     6   32 use warnings;
  6         11  
  6         408  
5 6     6   37 use experimental 'signatures';
  6         14  
  6         51  
6 6     6   1626 use English '-no_match_vars';
  6         2253  
  6         67  
7 6     6   9024 use File::Temp qw< tempdir tempfile >;
  6         113498  
  6         621  
8 6     6   2527 use File::Spec::Functions qw< splitpath catpath >;
  6         4042  
  6         486  
9 6     6   701 use Moo;
  6         10007  
  6         82  
10 6     6   6729 no warnings 'experimental::signatures';
  6         18  
  6         412  
11              
12 6     6   713 use namespace::clean;
  6         21227  
  6         59  
13              
14             with 'Data::Resolver::RoleComplain';
15              
16             has file => (is => 'lazy', predicate => 'has_file');
17             has _filehandle => (
18             is => 'ro',
19             init_arg => 'filehandle',
20             predicate => 'has_filehandle',
21             clearer => '_clear_filehandle'
22             );
23             has key => (is => 'lazy');
24             has raw_ref => (
25             is => 'lazy',
26             predicate => 'has_raw_ref',
27             init_arg => 'raw',
28             coerce => sub ($item) { ref($item) eq 'SCALAR' ? $item : \$item },
29             );
30              
31 19     19 1 164 sub assert_useable ($self) {
  19         34  
  19         31  
32 19 100       69 $self->is_useable or $self->complain(400, 'Not Useable');
33 17         44 return $self;
34             }
35              
36 3     3   4749 sub _build_file ($self) {
  3         7  
  3         4  
37 3         11 $self->assert_useable;
38              
39 3         6 my ($dst_fh, $path); # establish destination
40 3 50       82 if (defined(my $key = $self->key)) {
41 3         45 my $dir = tempdir(CLEANUP => 1);
42 3         2163 my ($v, $dirs) = splitpath($dir, 'no-file');
43 3         35 my (undef, undef, $basename) = splitpath($key);
44 3         69 $path = catpath($v, $dirs, $basename);
45             }
46             else {
47 0         0 ($dst_fh, $path) = tempfile(UNLINK => 1);
48             }
49 3   33     47 $dst_fh = $self->_raw_fh($dst_fh // $path, '>');
50              
51 3 50       27 if ($self->has_filehandle) {
    50          
52 0         0 $self->_copy($self->filehandle, $dst_fh);
53             }
54             elsif ($self->has_raw_ref) {
55 3         6 print {$dst_fh} ${$self->raw_ref};
  3         6  
  3         112  
56             }
57             else {
58 0         0 die "unexpected branch";
59             }
60              
61 3         281 return $path;
62             } ## end sub _build_file
63              
64 0     0   0 sub _build__filehandle ($self) {
  0         0  
  0         0  
65 0         0 $self->assert_useable;
66 0 0       0 my $fh =
67             $self->_raw_fh($self->has_raw_ref ? $self->raw_ref : $self->file);
68 0         0 return $fh;
69             } ## end sub _build__filehandle
70              
71 1     1   1886 sub _build_key ($self) {
  1         3  
  1         3  
72 1 50       7 return undef unless $self->has_file;
73 1         25 my ($v, $ds, $name) = splitpath($self->file);
74 1         35 return $name;
75             }
76              
77 8     8   149 sub _build_raw_ref ($self) {
  8         14  
  8         14  
78 8         27 my $fh = $self->filehandle;
79 8         262 my $key = $self->key;
80 8         119 local $/;
81 8 50       402 defined(my $buf = <$fh>)
82             or $self->complain(400, "readline('$key'): $OS_ERROR");
83 8         150 return \$buf;
84             } ## end sub _build_raw_ref
85              
86 0     0   0 sub _copy ($s, $src_rawfh, $dst) {
  0         0  
  0         0  
  0         0  
  0         0  
87 0         0 require File::Copy;
88 0         0 my $dst_rawfh = $s->_raw_fh($dst, '>');
89 0         0 File::Copy::copy($src_rawfh, $dst_rawfh);
90 0         0 return $s;
91             } ## end sub _copy
92              
93 1     1 1 20 sub decoded_as ($self, $encoding) {
  1         3  
  1         2  
  1         2  
94 1         8 require Encode;
95 1         4 return Encode::decode($encoding, $self->raw_data);
96             }
97              
98 1     1 1 16 sub decoded_as_utf8 ($self) { return $self->decoded_as('UTF-8') }
  1         2  
  1         2  
  1         5  
99              
100 0     0 1 0 sub fh ($self, @rest) { return $self->filehandle(@rest) }
  0         0  
  0         0  
  0         0  
  0         0  
101              
102 13     13 1 4960 sub filehandle ($self, %args) {
  13         30  
  13         26  
  13         50  
103 13         50 $self->assert_useable;
104              
105 13   50     87 my $binmode = $args{binmode} // ':raw';
106 13   100     51 my $nomem = $args{not_from_memory} // 0;
107              
108 13 100 100     375 my $src =
    100          
109             $self->has_filehandle ? $self->_filehandle
110             : ($nomem || (!$self->has_raw_ref)) ? $self->file
111             : $self->raw_ref;
112 13         406 $self->_clear_filehandle;
113              
114 13         105 my $fh = $self->_raw_fh($src);
115 13 50       87 binmode($fh, $binmode) or $self->complain(400, "binmode(): $OS_ERROR");
116 13         51 return $fh;
117             } ## end sub filehandle
118              
119 25     25 1 3972 sub is_useable ($self) {
  25         48  
  25         44  
120 25 100 100     338 $self->has_filehandle || $self->has_raw_ref || $self->has_file;
121             }
122              
123 1     1 1 18 sub parsed_as_json ($self) {
  1         2  
  1         2  
124 1         9 require JSON::PP;
125 1         5 return JSON::PP::decode_json($self->raw_data);
126             }
127              
128 19     19 1 6376 sub raw_data ($self) { return ${$self->raw_ref} }
  19         40  
  19         32  
  19         36  
  19         515  
129              
130 16     16   32 sub _raw_fh ($self, $fh, $mode = '<') {
  16         31  
  16         53  
  16         35  
  16         30  
131 16         29 my $name = '';
132 16 100       60 if (ref($fh) ne 'GLOB') {
133 14 100       39 $name = ref($fh) ? '' : $fh;
134 14         25 my $target = $fh;
135 14         27 $fh = undef;
136 14 50       1076 open $fh, $mode, $target
137             or $self->complain(400, "open($name): $OS_ERROR");
138             } ## end if (ref($fh) ne 'GLOB')
139 16 50       108 binmode $fh, ':raw'
140             or $self->complain(400, "binmode('$name'): $OS_ERROR");
141 16         51 return $fh;
142             } ## end sub _raw_fh
143              
144 0     0 1   sub save_as ($self, $dst) { $self->_copy($self->filehandle, $dst); $dst }
  0            
  0            
  0            
  0            
  0            
145              
146             1;