File Coverage

blib/lib/Net/WebSocket/PMCE/deflate/Data/Streamer.pm
Criterion Covered Total %
statement 30 30 100.0
branch 8 8 100.0
condition n/a
subroutine 8 8 100.0
pod 2 3 66.6
total 48 49 97.9


line stmt bran cond sub pod time code
1             package Net::WebSocket::PMCE::deflate::Data::Streamer;
2              
3 3     3   22 use strict;
  3         7  
  3         92  
4 3     3   14 use warnings;
  3         7  
  3         88  
5              
6             =encoding utf-8
7              
8             =head1 NAME
9              
10             Net::WebSocket::PMCE::deflate::Data::Streamer
11              
12             =head1 SYNOPSIS
13              
14             my $streamer = $deflate_data->create_streamer( $frame_class );
15              
16             #These frames form a single compressed message in three
17             #fragments whose content is “onetwothree”.
18             my @frames = (
19             $streamer->create_chunk('one'),
20             $streamer->create_chunk('two'),
21             $streamer->create_final('three'),
22             );
23              
24             =head1 DESCRIPTION
25              
26             This class implements fragmentation for the permessage-deflate WebSocket
27             extension. It allows you to send a single message in arbitrarily many
28             parts. The class is not instantiated directly, but instances are returned
29             as the result of L’s
30             C method.
31              
32             Strictly speaking, this is a base class; the C<::Client> and C<::Server>
33             subclasses implement a bit of logic specific to either endpoint type.
34              
35             The C and C methods follow the same
36             pattern as L.
37              
38             =cut
39              
40 3     3   1052 use Module::Runtime ();
  3         3792  
  3         132  
41              
42 3     3   1338 use Net::WebSocket::Frame::continuation ();
  3         8  
  3         790  
43              
44             =head1 METHODS
45              
46             =cut
47              
48             sub new {
49 5     5 0 16 my ($class, $data_obj, $frame_class) = @_;
50              
51 5 100       71 Module::Runtime::require_module($frame_class) if !$frame_class->can('new');
52              
53 5         23 my $self = {
54             _data_obj => $data_obj,
55             _frame_class => $frame_class,
56             };
57              
58 5         32 return bless $self, $class;
59             }
60              
61             my ($_COMPRESS_FUNC, $_FIN);
62              
63             =head2 I->create_chunk( OCTET_STRING )
64              
65             Compresses OCTET_STRING. The compressor doesn’t necessarily produce output
66             from this, however. If the compressor does produce output, then this
67             method returns a frame object (an instance of either the streamer’s
68             assigned frame class or L); otherwise,
69             undef is returned.
70              
71             =cut
72              
73             sub create_chunk {
74 40     40 1 467529 $_COMPRESS_FUNC = '_compress_non_final_fragment';
75 40         73 $_FIN = 0;
76              
77 40         164 goto &_create;
78             }
79              
80             =head2 I->create_final( OCTET_STRING )
81              
82             Compresses OCTET_STRING and flushes the compressor. The output matches
83             that of C except that the output is always a frame object.
84             The output of this method will complete the message.
85              
86             =cut
87              
88             sub create_final {
89 5     5 1 13513 $_COMPRESS_FUNC = $_[0]->{'_data_obj'}{'final_frame_compress_func'};
90 5         11 $_FIN = 1;
91              
92 5         18 goto &_create;
93             }
94              
95             sub _create {
96 45     45   109 my ($self) = @_;
97              
98 45         120 my $data_obj = $self->{'_data_obj'};
99              
100 45         184 my $payload_sr = \($data_obj->$_COMPRESS_FUNC( $_[1] ));
101              
102 45 100       183 return undef if !length $$payload_sr;
103              
104 6 100       36 my $class = $self->{'_frames_count'} ? 'Net::WebSocket::Frame::continuation' : $self->{'_frame_class'};
105 6 100       63 my $rsv = $self->{'_frames_count'} ? 0 : $data_obj->INITIAL_FRAME_RSV();
106              
107 6         18 $self->{'_frames_count'}++;
108              
109 6         92 return $class->new(
110             payload => $payload_sr,
111             rsv => $rsv,
112             $data_obj->FRAME_MASK_ARGS(),
113             );
114             }
115              
116             1;