File Coverage

blib/lib/Perlbal/ChunkedUploadState.pm
Criterion Covered Total %
statement 33 36 91.6
branch 13 16 81.2
condition 1 2 50.0
subroutine 5 6 83.3
pod 0 4 0.0
total 52 64 81.2


line stmt bran cond sub pod time code
1             package Perlbal::ChunkedUploadState;
2 22     22   135 use strict;
  22         56  
  22         13340  
3              
4             sub new {
5 3     3 0 13 my ($pkg, %args) = @_;
6 3         20 my $self = bless {
7             'buf' => '',
8             'bytes_remain' => 0, # remaining in chunk (ignoring final 2 byte CRLF)
9             }, $pkg;
10 3         9 foreach my $k (qw(on_new_chunk on_disconnect on_zero_chunk)) {
11 9   50 0   47 $self->{$k} = (delete $args{$k}) || sub {};
  0         0  
12             }
13 3 50       13 die "bogus args" if %args;
14 3         12 return $self;
15             }
16              
17             sub on_readable {
18 38     38 0 72 my ($self, $ds) = @_;
19 38         207 my $rbuf = $ds->read(131072);
20 38 50       2484 unless (defined $rbuf) {
21 0         0 $self->{on_disconnect}->();
22 0         0 return;
23             }
24              
25 38         1730 $self->{buf} .= $$rbuf;
26              
27 38         134 while ($self->drive_machine) {}
28             }
29              
30             # returns 1 if progress was made parsing buffer
31             sub drive_machine {
32 98     98 0 135 my $self = shift;
33              
34 98         416 my $buflen = length($self->{buf});
35 98 100       432 return 0 unless $buflen;
36              
37 70 100       162 if (my $br = $self->{bytes_remain}) {
38 44 100       96 my $extract = $buflen > $br ? $br : $buflen;
39 44         3876 my $ch = substr($self->{buf}, 0, $extract, '');
40 44         81 $self->{bytes_remain} -= $extract;
41 44 50       112 die "assert" if $self->{bytes_remain} < 0;
42 44         183 $self->{on_new_chunk}->(\$ch);
43 44         482 return 1;
44             }
45              
46 26 100       1463 return 0 unless $self->{buf} =~ s/^(?:\r\n)?([0-9a-fA-F]+)(?:;.*)?\r\n//;
47 19         82 $self->{bytes_remain} = hex($1);
48              
49 19 100       53 if ($self->{bytes_remain} == 0) {
50             # FIXME: new state machine state for trailer parsing/discarding.
51             # (before we do on_zero_chunk). for now, though, just assume
52             # no trailers and throw away the extra post-trailer \r\n that
53             # is probably in this packet. hacky.
54 3         18 $self->{buf} =~ s/^\r\n//;
55 3         9 $self->{hit_zero} = 1;
56 3         15 $self->{on_zero_chunk}->();
57 3         186 return 0;
58             }
59 16         69 return 1;
60             }
61              
62 12     12 0 65 sub hit_zero_chunk { $_[0]{hit_zero} }
63              
64             1;