File Coverage

blib/lib/Data/Record/Serialize/Role/Sink/Stream.pm
Criterion Covered Total %
statement 32 33 96.9
branch 11 14 78.5
condition 9 18 50.0
subroutine 8 8 100.0
pod 1 1 100.0
total 61 74 82.4


line stmt bran cond sub pod time code
1             package Data::Record::Serialize::Role::Sink::Stream;
2              
3             # ABSTRACT: output encoded data to a stream.
4              
5 7     7   3779 use v5.12;
  7         27  
6 7     7   40 use Scalar::Util;
  7         18  
  7         273  
7 7     7   42 use Moo::Role;
  7         17  
  7         42  
8              
9 7     7   3343 use Data::Record::Serialize::Error { errors => [ '::create', '::parameter', '::internal' ] }, -all;
  7         29  
  7         105  
10              
11             our $VERSION = '1.05';
12              
13 7     7   4601 use IO::File;
  7         12960  
  7         1148  
14              
15 7     7   62 use namespace::clean;
  7         32  
  7         51  
16              
17              
18              
19              
20              
21              
22              
23              
24              
25              
26              
27              
28              
29              
30              
31              
32              
33              
34              
35              
36              
37              
38              
39              
40              
41              
42              
43              
44              
45              
46             has output => (
47             is => 'ro',
48             default => q{-},
49             isa => sub {
50             defined $_[0]
51             or error( '::parameter', q{'output' parameter must be defined} );
52             my $ref = ref $_[0];
53             return if $ref eq 'GLOB' or $ref eq 'SCALAR';
54              
55             if ( $ref eq q{} ) {
56             $ref = ref( \$_[0] ); # turn plain *STDOUT into \*STDOUT
57             return if $ref eq 'GLOB';
58             return if length $_[0];
59             error( '::parameter', q{string 'output' parameter must not be empty} );
60             }
61              
62             return
63             if Scalar::Util::blessed $_[0]
64             and $_[0]->isa( 'IO::Handle' ) || $_[0]->isa( 'FileHandle' );
65             error( '::parameter', q{illegal value for 'output' parameter} );
66             },
67             );
68              
69              
70              
71              
72              
73              
74              
75             has fh => (
76             is => 'lazy',
77             init_arg => undef,
78             clearer => 1,
79             predicate => 1,
80             );
81              
82              
83              
84              
85              
86              
87              
88             has _passed_fh => (
89             is => 'rwp',
90             init_arg => undef,
91             default => 1,
92             );
93              
94             sub _build_fh {
95 17     17   1057 my $self = shift;
96              
97 17         67 my $output = $self->output;
98 17         53 my $ref = ref $output;
99              
100             # filename
101 17 100       57 if ( $ref eq q{} ) {
102 2 100       20 return $output if ref( \$output ) eq 'GLOB';
103 1 50       8 return \*STDOUT if $output eq q{-};
104              
105 1         4 $self->_set__passed_fh( 0 );
106             return (
107 1   33     6 IO::File->new( $output, 'w' )
108             or error( '::create', "unable to create output file: '$output'" ) );
109             }
110              
111 15 50 33     166 return $output
      66        
      66        
112             if $ref eq 'GLOB'
113             or Scalar::Util::blessed( $output )
114             && ( $output->isa( 'IO::Handle' ) || $output->isa( 'FileHandle' ) );
115              
116 12         58 $self->_set__passed_fh( 0 );
117             return (
118 12 50 33     110 IO::File->new( $output, 'w' )
119             or error( '::create', q{unable to open scalar for output} ) ) if $ref eq 'SCALAR';
120              
121 0         0 error( '::internal', q{can't get here} );
122             }
123              
124              
125              
126              
127              
128              
129              
130              
131              
132              
133              
134              
135              
136              
137              
138              
139              
140              
141              
142              
143              
144              
145              
146              
147              
148              
149             sub close {
150 20     20 1 452 my ( $self, $in_global_destruction ) = @_;
151              
152             # don't bother closing the FH in global destruction (it'll be done
153             # on its own) or if we were passed a file handle in the output
154             # attribute.
155 20 100 66     159 return if $in_global_destruction or $self->_passed_fh;
156              
157             # fh is lazy, so the object may close without every using it, so
158             # don't inadvertently create it.
159 10 100       199 $self->fh->close if $self->has_fh;
160 10         452 $self->clear_fh;
161             }
162              
163             1;
164              
165             #
166             # This file is part of Data-Record-Serialize
167             #
168             # This software is Copyright (c) 2017 by Smithsonian Astrophysical Observatory.
169             #
170             # This is free software, licensed under:
171             #
172             # The GNU General Public License, Version 3, June 2007
173             #
174              
175             __END__
176              
177             =pod
178              
179             =for :stopwords Diab Jerius Smithsonian Astrophysical Observatory
180              
181             =head1 NAME
182              
183             Data::Record::Serialize::Role::Sink::Stream - output encoded data to a stream.
184              
185             =head1 VERSION
186              
187             version 1.05
188              
189             =head1 SYNOPSIS
190              
191             with 'Data::Record::Serialize::Role::Sink::Stream';
192              
193             =head1 DESCRIPTION
194              
195             A L<Moo::Role> which provides the underlying support for stream sinks.
196             B<Data::Record::Serialize::Role::Sink::Stream> outputs encoded data to a
197             file handle.
198              
199             =head1 OBJECT ATTRIBUTES
200              
201             =head2 output
202              
203             One of the following:
204              
205             =over
206              
207             =item *
208              
209             The name of an output file (which will be created). If it is the
210             string C<->, output will be written to the standard output stream.
211             Must not be the empty string.
212              
213             =item *
214              
215             a reference to a scalar to which the records will be written.
216              
217             =item *
218              
219             a GLOB (i.e. C<\*STDOUT>), or a reference to an object which derives
220             from L<IO::Handle> (e.g. L<IO::File>, L<FileHandle>, etc.). These
221             will I<not> be closed upon destruction of the serializer or when the
222             L</close> method is called.
223              
224             =back
225              
226             =head2 fh
227              
228             The file handle to which the data will be output
229              
230             =head2 _passed_fh
231              
232             Will be true if L</output> was not a file name.
233              
234             =head1 CLASS METHODS
235              
236             =head2 new
237              
238             This role adds two named arguments to the constructor, L</output> and
239             L</fh>, which mirror the added object attributes.
240              
241             =head1 METHODS
242              
243             =head2 close
244              
245             $obj->close( ?$in_global_destruction );
246              
247             Close the object; useful in destructors. Only files created by the
248             serializer will be closed. If a filehandle, GLOB, or similar object
249             is passed via the constructor's L</output> parameter L</close> method
250             is called.
251              
252             =head1 INTERNALS
253              
254             =for Pod::Coverage close
255             has_fh
256             clear_fh
257              
258             =head1 SUPPORT
259              
260             =head2 Bugs
261              
262             Please report any bugs or feature requests to bug-data-record-serialize@rt.cpan.org or through the web interface at: L<https://rt.cpan.org/Public/Dist/Display.html?Name=Data-Record-Serialize>
263              
264             =head2 Source
265              
266             Source is available at
267              
268             https://gitlab.com/djerius/data-record-serialize
269              
270             and may be cloned from
271              
272             https://gitlab.com/djerius/data-record-serialize.git
273              
274             =head1 SEE ALSO
275              
276             Please see those modules/websites for more information related to this module.
277              
278             =over 4
279              
280             =item *
281              
282             L<Data::Record::Serialize|Data::Record::Serialize>
283              
284             =back
285              
286             =head1 AUTHOR
287              
288             Diab Jerius <djerius@cpan.org>
289              
290             =head1 COPYRIGHT AND LICENSE
291              
292             This software is Copyright (c) 2017 by Smithsonian Astrophysical Observatory.
293              
294             This is free software, licensed under:
295              
296             The GNU General Public License, Version 3, June 2007
297              
298             =cut