File Coverage

blib/lib/Protocol/SocketIO/Message.pm
Criterion Covered Total %
statement 64 67 95.5
branch 36 38 94.7
condition 12 18 66.6
subroutine 13 15 86.6
pod 9 9 100.0
total 134 147 91.1


line stmt bran cond sub pod time code
1             package Protocol::SocketIO::Message;
2              
3 1     1   420 use strict;
  1         1  
  1         22  
4 1     1   3 use warnings;
  1         0  
  1         17  
5              
6 1     1   3 use Encode ();
  1         0  
  1         9  
7 1     1   2 use JSON ();
  1         1  
  1         30  
8              
9 1     1   2 use overload '""' => sub { $_[0]->to_string }, fallback => 1;
  1     0   1  
  1         6  
  0         0  
10              
11             our %TYPES = (
12             'disconnect' => 0,
13             'connect' => 1,
14             'heartbeat' => 2,
15             'message' => 3,
16             'json_message' => 4,
17             'event' => 5,
18             'ack' => 6,
19             'error' => 7,
20             'noop' => 8
21             );
22              
23             sub new {
24 25     25 1 1588 my $class = shift;
25              
26 25         47 my $self = {@_};
27 25         29 bless $self, $class;
28              
29 25 100 66     91 $self->{type} ||= ref $self->{data} ? 'json_message' : 'message';
30              
31 25 100 100     86 if ($self->{type} eq 'connect' || $self->{type} eq 'heartbeat') {
32 3 100       6 $self->{endpoint} = '' unless defined $self->{endpoint};
33             }
34              
35 25         46 return $self;
36             }
37              
38             sub is_message {
39 0     0 1 0 my $self = shift;
40              
41 0   0     0 return $self->type eq 'message' || $self->type eq 'json_message';
42             }
43              
44             sub parse {
45 8     8 1 60 my $self = shift;
46 8         7 my ($string) = @_;
47              
48 8 50 33     25 return unless defined $string && $string ne '';
49              
50 8 100       18 return unless $string =~ m/:/;
51              
52 7         25 ($self->{type}, $self->{id}, $self->{endpoint}, $self->{data}) =
53             split ':', $string, 4;
54              
55 7 50       15 return unless defined $self->{type};
56              
57 7 100       16 if ($self->{id} =~ s/\+$//) {
58              
59             # TODO ack
60             }
61              
62 7         39 my %swapped = reverse %TYPES;
63 7 100       17 return unless exists $swapped{$self->{type}};
64              
65 6         19 $self->{type} = $swapped{$self->{type}};
66              
67 6         8 for (qw(id endpoint data)) {
68 18 100       28 $self->{$_} = '' unless defined $self->{$_};
69             }
70              
71 6 100 100     19 if ($self->{type} eq 'json_message' || $self->{type} eq 'event') {
72             eval {
73 4         32 $self->{data} = JSON::decode_json($self->{data});
74 3         7 1;
75 4 100       5 } or do {
76 1         1 delete $self->{data};
77             };
78              
79 4 100       8 return unless defined $self->{data};
80             }
81             else {
82 2         8 $self->{data} = Encode::decode('UTF-8', $self->{data});
83             }
84              
85 5         58 return $self;
86             }
87              
88 1     1 1 4 sub type { $_[0]->{type} }
89 2     2 1 10 sub id { $_[0]->{id} }
90 1     1 1 3 sub endpoint { $_[0]->{endpoint} }
91              
92 4     4 1 21 sub data { $_[0]->{data} }
93              
94             sub to_bytes {
95 19     19 1 93 my $self = shift;
96              
97 19         12 my @message;
98              
99 19         26 my $type = $TYPES{$self->{type}};
100              
101 19         10 my $data;
102 19 100 100     72 if ($self->{type} eq 'error') {
    100          
    100          
103 1         2 $data = join '+', $self->{reason}, $self->{advice};
104             }
105             elsif ($self->{type} eq 'json_message' || $self->{type} eq 'event') {
106 6         37 $data = JSON::encode_json($self->{data});
107             }
108             elsif ($self->{type} eq 'ack') {
109 2         2 $data = $self->{message_id};
110 2 100       3 if ($self->{args}) {
111 1         5 $data .= '+' . JSON::encode_json($self->{args});
112             }
113             }
114             else {
115 10         25 $data = Encode::encode('UTF-8', $self->{data});
116             }
117              
118 19         255 for ($data, $self->{endpoint}, $self->{id}, $type) {
119 76 100       98 if (@message) {
    100          
120 47 100       59 push @message, defined $_ ? $_ : '';
121             }
122             elsif (defined $_) {
123 19         23 push @message, $_;
124             }
125             }
126              
127 19         84 return join ':', reverse @message;
128             }
129              
130             sub to_string {
131 1     1 1 3 my $self = shift;
132              
133 1         2 return Encode::decode('UTF-8', $self->to_bytes);
134             }
135              
136             1;
137             __END__