File Coverage

blib/lib/Wily/Message.pm
Criterion Covered Total %
statement 40 42 95.2
branch 7 12 58.3
condition n/a
subroutine 11 12 91.6
pod 0 5 0.0
total 58 71 81.6


line stmt bran cond sub pod time code
1             package Wily::Message;
2              
3 2     2   20104 use v5.8;
  2         7  
  2         71  
4 2     2   11 use strict;
  2         17  
  2         56  
5 2     2   10 use warnings;
  2         2  
  2         52  
6 2     2   8 use Carp;
  2         3  
  2         163  
7 2     2   2101 use Encode qw/decode_utf8 encode_utf8/;
  2         25099  
  2         427  
8              
9             require Exporter;
10              
11             our @ISA = qw(Exporter);
12              
13             # Items to export into callers namespace by default. Note: do not export
14             # names by default without a very good reason. Use EXPORT_OK instead.
15             # Do not simply export all your public functions/methods/constants.
16              
17             # This allows declaration use Wily::Message ':all';
18             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
19             # will save memory.
20             our %EXPORT_TAGS = ( 'constants' => [ qw(WEexec WEgoto WEdestroy WEreplace
21             WEfencepost WRerror WMlist WRlist WMnew WRnew WMattach WRattach
22             WMsetname WRsetname WMgetname WRgetname WMsettools WRsettools
23             WMgettools WRgettools WMread WRread WMreplace WRreplace WMexec WRexec
24             WMgoto WRgoto WMgetfeatures WRgetfeatures WMdetach WRdetach WMfencepost
25             ) ] );
26              
27             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'constants'} } );
28              
29             our $VERSION = '0.01';
30              
31             use constant {
32             # EVENTS (and event masks)
33 2         1963 WEexec => 1,
34             WEgoto => 2,
35             WEdestroy => 4,
36             WEreplace => 8,
37              
38             WEfencepost =>9,
39              
40             # REQUESTS AND RESPONSES
41             WRerror => 10,
42             WMlist => 11,
43             WRlist => 12,
44             WMnew => 13,
45             WRnew => 14,
46             WMattach => 15,
47             WRattach => 16,
48             WMsetname => 17,
49             WRsetname => 18,
50             WMgetname => 19,
51             WRgetname => 20,
52             WMsettools => 21,
53             WRsettools => 22,
54             WMgettools => 23,
55             WRgettools => 24,
56             WMread => 25,
57             WRread => 26,
58             WMreplace => 27,
59             WRreplace => 28,
60             WMexec => 29,
61             WRexec => 30,
62             WMgoto => 31,
63             WRgoto => 32,
64              
65             # Non-standard messages
66             WMgetfeatures => 33,
67             WRgetfeatures => 34,
68             WMdetach => 35,
69             WRdetach => 36,
70            
71             WMfencepost => 37,
72 2     2   17 };
  2         4  
73              
74             our $COOKIE = 0xfeed;
75             our $HEADER_SIZE = 22;
76              
77              
78             sub new {
79 8     8 0 1887 my $package = shift;
80 8         11 my ($type, $win, $p0, $p1, $flag, $s) = @_;
81 8         16 for ($type, $win, $p0, $p1, $flag) {
82 40 100       80 $_ = 0 unless defined;
83             }
84 8 100       18 $s = '' unless defined $s;
85              
86 8         44 my $self = {'type' => $type,
87             'message_id' => 0,
88             'window_id' => $win,
89             'p0' => $p0,
90             'p1' => $p1,
91             'flag' => $flag,
92             's' => $s
93             };
94 8         31 return bless $self, $package;
95             }
96              
97             sub flatten {
98 2     2 0 13 my $self = shift;
99 2         8 return pack('nnNnnNNna'.(length($self->{s})+1), $COOKIE,
100             $self->{type}, $self->size(), $self->{message_id},
101             $self->{window_id}, $self->{p0}, $self->{p1},
102             $self->{flag}, encode_utf8($self->{s}));
103             }
104              
105             sub size {
106 4     4 0 16 my $self = shift;
107 4         16 return $HEADER_SIZE + 1 + length(encode_utf8($self->{s}));
108             }
109              
110             sub from_string {
111 2     2 0 12 my $self = shift;
112 2         4 my $msg = shift;
113 2         7 my $size = _message_length($msg);
114 2         3 my $cookie;
115 2         18 ($cookie, $self->{type}, undef, $self->{message_id}, $self->{window_id},
116             $self->{p0}, $self->{p1}, $self->{flag}, $self->{s}) =
117             unpack('nnNnnNNna'.($size-1-$HEADER_SIZE), $msg);
118 2 50       8 croak "Invalid Cookie" unless $cookie eq $COOKIE;
119 2         8 $self->{s} = decode_utf8($self->{s});
120 2 50       88 return $size
121             }
122              
123              
124             sub _message_length {
125 2     2   3 my $buffer = shift;
126 2 50       7 croak "Buffer shorter than header size" unless length($buffer) > $HEADER_SIZE;
127 2         10 return unpack('N', substr($buffer, 4));
128             }
129              
130             sub complete_message {
131 0     0 0   my $buffer = shift;
132 0 0         return length($buffer) > $HEADER_SIZE and
133             length($buffer) >= _message_length($buffer);
134             }
135              
136              
137             1;
138             __END__