File Coverage

blib/lib/Thrift/BinaryProtocol.pm
Criterion Covered Total %
statement 183 242 75.6
branch 10 24 41.6
condition n/a
subroutine 48 61 78.6
pod 0 41 0.0
total 241 368 65.4


line stmt bran cond sub pod time code
1             #
2             # Licensed to the Apache Software Foundation (ASF) under one
3             # or more contributor license agreements. See the NOTICE file
4             # distributed with this work for additional information
5             # regarding copyright ownership. The ASF licenses this file
6             # to you under the Apache License, Version 2.0 (the
7             # "License"); you may not use this file except in compliance
8             # with the License. You may obtain a copy of the License at
9             #
10             # http://www.apache.org/licenses/LICENSE-2.0
11             #
12             # Unless required by applicable law or agreed to in writing,
13             # software distributed under the License is distributed on an
14             # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15             # KIND, either express or implied. See the License for the
16             # specific language governing permissions and limitations
17             # under the License.
18             #
19              
20 3     3   316217 use 5.10.0;
  3         10  
21 3     3   12 use strict;
  3         12  
  3         54  
22 3     3   11 use warnings;
  3         5  
  3         116  
23              
24 3     3   1282 use Bit::Vector;
  3         3042  
  3         193  
25 3     3   1421 use Encode;
  3         46796  
  3         283  
26 3     3   1326 use Thrift;
  3         8  
  3         82  
27 3     3   1172 use Thrift::Exception;
  3         9  
  3         83  
28 3     3   1160 use Thrift::MessageType;
  3         7  
  3         62  
29 3     3   1295 use Thrift::Protocol;
  3         9  
  3         76  
30 3     3   12 use Thrift::Type;
  3         4  
  3         39  
31 3     3   1287 use utf8;
  3         666  
  3         16  
32              
33             #
34             # Binary implementation of the Thrift protocol.
35             #
36             package Thrift::BinaryProtocol;
37 3     3   160 use base('Thrift::Protocol');
  3         5  
  3         338  
38 3     3   13 use version 0.77; our $VERSION = version->declare("$Thrift::VERSION");
  3         34  
  3         14  
39              
40 3     3   264 use constant VERSION_MASK => 0xffff0000;
  3         4  
  3         141  
41 3     3   11 use constant VERSION_1 => 0x80010000;
  3         3  
  3         200  
42 3     3   13 use constant IS_BIG_ENDIAN => unpack('h*', pack('s', 1)) =~ m/01/;
  3         3  
  3         4638  
43              
44             sub new
45             {
46 8     8 0 47 my $classname = shift;
47 8         12 my $trans = shift;
48 8         48 my $self = $classname->SUPER::new($trans);
49              
50 8         28 return bless($self,$classname);
51             }
52              
53             sub writeMessageBegin
54             {
55 26     26 0 28 my $self = shift;
56 26         34 my ($name, $type, $seqid) = @_;
57              
58             return
59 26         58 $self->writeI32(VERSION_1 | $type) +
60             $self->writeString($name) +
61             $self->writeI32($seqid);
62             }
63              
64             sub writeMessageEnd
65             {
66 26     26 0 25 my $self = shift;
67 26         34 return 0;
68             }
69              
70             sub writeStructBegin
71             {
72 28     28 0 31 my $self = shift;
73 28         39 my $name = shift;
74 28         38 return 0;
75             }
76              
77             sub writeStructEnd
78             {
79 28     28 0 51 my $self = shift;
80 28         40 return 0;
81             }
82              
83             sub writeFieldBegin
84             {
85 26     26 0 29 my $self = shift;
86 26         37 my ($fieldName, $fieldType, $fieldId) = @_;
87              
88             return
89 26         48 $self->writeByte($fieldType) +
90             $self->writeI16($fieldId);
91             }
92              
93             sub writeFieldEnd
94             {
95 26     26 0 46 my $self = shift;
96 26         31 return 0;
97             }
98              
99             sub writeFieldStop
100             {
101 28     28 0 27 my $self = shift;
102 28         49 return $self->writeByte(Thrift::TType::STOP);
103             }
104              
105             sub writeMapBegin
106             {
107 0     0 0 0 my $self = shift;
108 0         0 my ($keyType, $valType, $size) = @_;
109              
110             return
111 0         0 $self->writeByte($keyType) +
112             $self->writeByte($valType) +
113             $self->writeI32($size);
114             }
115              
116             sub writeMapEnd
117             {
118 0     0 0 0 my $self = shift;
119 0         0 return 0;
120             }
121              
122             sub writeListBegin
123             {
124 1     1 0 1 my $self = shift;
125 1         4 my ($elemType, $size) = @_;
126              
127             return
128 1         3 $self->writeByte($elemType) +
129             $self->writeI32($size);
130             }
131              
132             sub writeListEnd
133             {
134 1     1 0 3 my $self = shift;
135 1         3 return 0;
136             }
137              
138             sub writeSetBegin
139             {
140 0     0 0 0 my $self = shift;
141 0         0 my ($elemType, $size) = @_;
142              
143             return
144 0         0 $self->writeByte($elemType) +
145             $self->writeI32($size);
146             }
147              
148             sub writeSetEnd
149             {
150 0     0 0 0 my $self = shift;
151 0         0 return 0;
152             }
153              
154             sub writeBool
155             {
156 0     0 0 0 my $self = shift;
157 0         0 my $value = shift;
158              
159 0 0       0 my $data = pack('c', $value ? 1 : 0);
160 0         0 $self->{trans}->write($data, 1);
161 0         0 return 1;
162             }
163              
164             sub writeByte
165             {
166 60     60 0 70 my $self = shift;
167 60         55 my $value= shift;
168              
169 60         90 my $data = pack('c', $value);
170 60         109 $self->{trans}->write($data, 1);
171 60         91 return 1;
172             }
173              
174             sub writeI16
175             {
176 26     26 0 26 my $self = shift;
177 26         26 my $value= shift;
178              
179 26         44 my $data = pack('n', $value);
180 26         46 $self->{trans}->write($data, 2);
181 26         39 return 2;
182             }
183              
184             sub writeI32
185             {
186 102     102 0 108 my $self = shift;
187 102         159 my $value= shift;
188              
189 102         148 my $data = pack('N', $value);
190 102         183 $self->{trans}->write($data, 4);
191 102         146 return 4;
192             }
193              
194             sub writeI64
195             {
196 2     2 0 3 my $self = shift;
197 2         3 my $value= shift;
198 2         5 my $data;
199              
200             my $vec;
201             #stop annoying error
202 2         52 $vec = Bit::Vector->new_Dec(64, $value);
203 2         12 $data = pack 'NN', $vec->Chunk_Read(32, 32), $vec->Chunk_Read(32, 0);
204              
205 2         7 $self->{trans}->write($data, 8);
206              
207 2         9 return 8;
208             }
209              
210              
211             sub writeDouble
212             {
213 0     0 0 0 my $self = shift;
214 0         0 my $value= shift;
215              
216 0         0 my $data = pack('d', $value);
217 0 0       0 if (IS_BIG_ENDIAN) {
218 0         0 $self->{trans}->write($data, 8);
219             }
220             else {
221 0         0 $self->{trans}->write(scalar reverse($data), 8);
222             }
223 0         0 return 8;
224             }
225              
226             sub writeString{
227 32     32 0 32 my $self = shift;
228 32         34 my $value= shift;
229              
230 32 50       84 if( utf8::is_utf8($value) ){
231 0         0 $value = Encode::encode_utf8($value);
232             }
233              
234 32         36 my $len = length($value);
235              
236 32         45 my $result = $self->writeI32($len);
237              
238 32 50       69 if ($len) {
239 32         49 $self->{trans}->write($value,$len);
240             }
241 32         51 return $result + $len;
242             }
243              
244              
245             #
246             #All references
247             #
248             sub readMessageBegin
249             {
250 26     26 0 1083 my $self = shift;
251 26         48 my ($name, $type, $seqid) = @_;
252              
253 26         41 my $version = 0;
254 26         46 my $result = $self->readI32(\$version);
255 26 50       58 if (($version & VERSION_MASK) > 0) {
256 26 50       43 if (($version & VERSION_MASK) != VERSION_1) {
257 0         0 die Thrift::TProtocolException->new('Missing version identifier',
258             Thrift::TProtocolException::BAD_VERSION);
259             }
260 26         35 $$type = $version & 0x000000ff;
261             return
262 26         54 $result +
263             $self->readString($name) +
264             $self->readI32($seqid);
265             }
266             else { # old client support code
267             return
268 0         0 $result +
269             $self->readStringBody($name, $version) + # version here holds the size of the string
270             $self->readByte($type) +
271             $self->readI32($seqid);
272             }
273             }
274              
275             sub readMessageEnd
276             {
277 26     26 0 30 my $self = shift;
278 26         34 return 0;
279             }
280              
281             sub readStructBegin
282             {
283 28     28 0 30 my $self = shift;
284 28         32 my $name = shift;
285              
286 28         34 $$name = '';
287              
288 28         42 return 0;
289             }
290              
291             sub readStructEnd
292             {
293 28     28 0 34 my $self = shift;
294 28         45 return 0;
295             }
296              
297             sub readFieldBegin
298             {
299 54     54 0 55 my $self = shift;
300 54         72 my ($name, $fieldType, $fieldId) = @_;
301              
302 54         81 my $result = $self->readByte($fieldType);
303              
304 54 100       87 if ($$fieldType == Thrift::TType::STOP) {
305 28         35 $$fieldId = 0;
306 28         50 return $result;
307             }
308              
309 26         66 $result += $self->readI16($fieldId);
310              
311 26         47 return $result;
312             }
313              
314             sub readFieldEnd() {
315 26     26 0 87 my $self = shift;
316 26         45 return 0;
317             }
318              
319             sub readMapBegin
320             {
321 0     0 0 0 my $self = shift;
322 0         0 my ($keyType, $valType, $size) = @_;
323              
324             return
325 0         0 $self->readByte($keyType) +
326             $self->readByte($valType) +
327             $self->readI32($size);
328             }
329              
330             sub readMapEnd()
331             {
332 0     0 0 0 my $self = shift;
333 0         0 return 0;
334             }
335              
336             sub readListBegin
337             {
338 1     1 0 8 my $self = shift;
339 1         3 my ($elemType, $size) = @_;
340              
341             return
342 1         2 $self->readByte($elemType) +
343             $self->readI32($size);
344             }
345              
346             sub readListEnd
347             {
348 1     1 0 1 my $self = shift;
349 1         7 return 0;
350             }
351              
352             sub readSetBegin
353             {
354 0     0 0 0 my $self = shift;
355 0         0 my ($elemType, $size) = @_;
356              
357             return
358 0         0 $self->readByte($elemType) +
359             $self->readI32($size);
360             }
361              
362             sub readSetEnd
363             {
364 0     0 0 0 my $self = shift;
365 0         0 return 0;
366             }
367              
368             sub readBool
369             {
370 0     0 0 0 my $self = shift;
371 0         0 my $value = shift;
372              
373 0         0 my $data = $self->{trans}->readAll(1);
374 0         0 my @arr = unpack('c', $data);
375 0         0 $$value = $arr[0] == 1;
376 0         0 return 1;
377             }
378              
379             sub readByte
380             {
381 61     61 0 142 my $self = shift;
382 61         63 my $value = shift;
383              
384 61         107 my $data = $self->{trans}->readAll(1);
385 60         110 my @arr = unpack('c', $data);
386 60         72 $$value = $arr[0];
387 60         76 return 1;
388             }
389              
390             sub readI16
391             {
392 26     26 0 40 my $self = shift;
393 26         30 my $value = shift;
394              
395 26         40 my $data = $self->{trans}->readAll(2);
396              
397 26         43 my @arr = unpack('n', $data);
398              
399 26         39 $$value = $arr[0];
400              
401 26 50       56 if ($$value > 0x7fff) {
402 0         0 $$value = 0 - (($$value - 1) ^ 0xffff);
403             }
404              
405 26         43 return 2;
406             }
407              
408             sub readI32
409             {
410 102     102 0 109 my $self = shift;
411 102         105 my $value= shift;
412              
413 102         182 my $data = $self->{trans}->readAll(4);
414 102         162 my @arr = unpack('N', $data);
415              
416 102         114 $$value = $arr[0];
417 102 100       147 if ($$value > 0x7fffffff) {
418 26         40 $$value = 0 - (($$value - 1) ^ 0xffffffff);
419             }
420 102         153 return 4;
421             }
422              
423             sub readI64
424             {
425 2     2 0 2 my $self = shift;
426 2         3 my $value = shift;
427              
428 2         4 my $data = $self->{trans}->readAll(8);
429              
430 2         5 my ($hi,$lo)=unpack('NN',$data);
431              
432 2         13 my $vec = Bit::Vector->new(64);
433              
434 2         7 $vec->Chunk_Store(32,32,$hi);
435 2         5 $vec->Chunk_Store(32,0,$lo);
436              
437 2         31 $$value = $vec->to_Dec();
438              
439 2         9 return 8;
440             }
441              
442             sub readDouble
443             {
444 0     0 0 0 my $self = shift;
445 0         0 my $value = shift;
446              
447 0         0 my $data;
448 0 0       0 if (IS_BIG_ENDIAN) {
449 0         0 $data = $self->{trans}->readAll(8);
450             }
451             else {
452 0         0 $data = scalar reverse($self->{trans}->readAll(8));
453             }
454              
455 0         0 my @arr = unpack('d', $data);
456              
457 0         0 $$value = $arr[0];
458              
459 0         0 return 8;
460             }
461              
462             sub readString
463             {
464 32     32 0 36 my $self = shift;
465 32         46 my $value = shift;
466              
467 32         33 my $len;
468 32         91 my $result = $self->readI32(\$len);
469              
470 32 50       60 if ($len) {
471 32         56 $$value = $self->{trans}->readAll($len);
472             }
473             else {
474 0         0 $$value = '';
475             }
476              
477 32         64 return $result + $len;
478             }
479              
480             sub readStringBody
481             {
482 0     0 0 0 my $self = shift;
483 0         0 my $value = shift;
484 0         0 my $len = shift;
485              
486 0 0       0 if ($len) {
487 0         0 $$value = $self->{trans}->readAll($len);
488             }
489             else {
490 0         0 $$value = '';
491             }
492              
493 0         0 return $len;
494             }
495              
496             #
497             # Binary Protocol Factory
498             #
499             package Thrift::BinaryProtocolFactory;
500 3     3   21 use base('Thrift::TProtocolFactory');
  3         4  
  3         983  
501 3     3   19 use version 0.77; our $VERSION = version->declare("$Thrift::VERSION");
  3         36  
  3         16  
502              
503             sub new
504             {
505 2     2   22 my $classname = shift;
506 2         19 my $self = $classname->SUPER::new();
507              
508 2         6 return bless($self,$classname);
509             }
510              
511             sub getProtocol{
512 4     4   13 my $self = shift;
513 4         14 my $trans = shift;
514              
515 4         8 return Thrift::BinaryProtocol->new($trans);
516             }
517              
518             1;