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