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   179320 use 5.10.0;
  3         31  
21 3     3   13 use strict;
  3         5  
  3         59  
22 3     3   12 use warnings;
  3         5  
  3         66  
23              
24 3     3   1146 use Bit::Vector;
  3         2505  
  3         113  
25 3     3   1453 use Encode;
  3         24890  
  3         194  
26 3     3   947 use Thrift;
  3         5  
  3         76  
27 3     3   1043 use Thrift::Exception;
  3         7  
  3         68  
28 3     3   921 use Thrift::MessageType;
  3         6  
  3         64  
29 3     3   1007 use Thrift::Protocol;
  3         7  
  3         101  
30 3     3   16 use Thrift::Type;
  3         7  
  3         43  
31 3     3   1513 use utf8;
  3         36  
  3         15  
32              
33             #
34             # Binary implementation of the Thrift protocol.
35             #
36             package Thrift::BinaryProtocol;
37 3     3   118 use base('Thrift::Protocol');
  3         5  
  3         244  
38 3     3   17 use version 0.77; our $VERSION = version->declare("$Thrift::VERSION");
  3         41  
  3         13  
39              
40 3     3   281 use constant VERSION_MASK => 0xffff0000;
  3         4  
  3         130  
41 3     3   25 use constant VERSION_1 => 0x80010000;
  3         5  
  3         183  
42 3     3   17 use constant IS_BIG_ENDIAN => unpack('h*', pack('s', 1)) =~ m/01/;
  3         3  
  3         5456  
43              
44             sub new
45             {
46 8     8 0 29 my $classname = shift;
47 8         12 my $trans = shift;
48 8         30 my $self = $classname->SUPER::new($trans);
49              
50 8         20 return bless($self,$classname);
51             }
52              
53             sub writeMessageBegin
54             {
55 26     26 0 34 my $self = shift;
56 26         40 my ($name, $type, $seqid) = @_;
57              
58             return
59 26         51 $self->writeI32(VERSION_1 | $type) +
60             $self->writeString($name) +
61             $self->writeI32($seqid);
62             }
63              
64             sub writeMessageEnd
65             {
66 26     26 0 30 my $self = shift;
67 26         33 return 0;
68             }
69              
70             sub writeStructBegin
71             {
72 28     28 0 38 my $self = shift;
73 28         37 my $name = shift;
74 28         41 return 0;
75             }
76              
77             sub writeStructEnd
78             {
79 28     28 0 36 my $self = shift;
80 28         34 return 0;
81             }
82              
83             sub writeFieldBegin
84             {
85 26     26 0 34 my $self = shift;
86 26         39 my ($fieldName, $fieldType, $fieldId) = @_;
87              
88             return
89 26         45 $self->writeByte($fieldType) +
90             $self->writeI16($fieldId);
91             }
92              
93             sub writeFieldEnd
94             {
95 26     26 0 32 my $self = shift;
96 26         39 return 0;
97             }
98              
99             sub writeFieldStop
100             {
101 28     28 0 39 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 2 my $self = shift;
125 1         3 my ($elemType, $size) = @_;
126              
127             return
128 1         9 $self->writeByte($elemType) +
129             $self->writeI32($size);
130             }
131              
132             sub writeListEnd
133             {
134 1     1 0 2 my $self = shift;
135 1         2 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 68 my $self = shift;
167 60         65 my $value= shift;
168              
169 60         96 my $data = pack('c', $value);
170 60         135 $self->{trans}->write($data, 1);
171 60         88 return 1;
172             }
173              
174             sub writeI16
175             {
176 26     26 0 34 my $self = shift;
177 26         29 my $value= shift;
178              
179 26         38 my $data = pack('n', $value);
180 26         53 $self->{trans}->write($data, 2);
181 26         46 return 2;
182             }
183              
184             sub writeI32
185             {
186 102     102 0 116 my $self = shift;
187 102         110 my $value= shift;
188              
189 102         156 my $data = pack('N', $value);
190 102         201 $self->{trans}->write($data, 4);
191 102         160 return 4;
192             }
193              
194             sub writeI64
195             {
196 2     2 0 2 my $self = shift;
197 2         9 my $value= shift;
198 2         4 my $data;
199              
200             my $vec;
201             #stop annoying error
202 2         42 $vec = Bit::Vector->new_Dec(64, $value);
203 2         15 $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 39 my $self = shift;
228 32         33 my $value= shift;
229              
230 32 50       71 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         56 my $result = $self->writeI32($len);
237              
238 32 50       58 if ($len) {
239 32         55 $self->{trans}->write($value,$len);
240             }
241 32         83 return $result + $len;
242             }
243              
244              
245             #
246             #All references
247             #
248             sub readMessageBegin
249             {
250 26     26 0 664 my $self = shift;
251 26         40 my ($name, $type, $seqid) = @_;
252              
253 26         29 my $version = 0;
254 26         43 my $result = $self->readI32(\$version);
255 26 50       49 if (($version & VERSION_MASK) > 0) {
256 26 50       38 if (($version & VERSION_MASK) != VERSION_1) {
257 0         0 die Thrift::TProtocolException->new('Missing version identifier',
258             Thrift::TProtocolException::BAD_VERSION);
259             }
260 26         37 $$type = $version & 0x000000ff;
261             return
262 26         50 $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 32 my $self = shift;
278 26         39 return 0;
279             }
280              
281             sub readStructBegin
282             {
283 28     28 0 34 my $self = shift;
284 28         30 my $name = shift;
285              
286 28         32 $$name = '';
287              
288 28         47 return 0;
289             }
290              
291             sub readStructEnd
292             {
293 28     28 0 32 my $self = shift;
294 28         38 return 0;
295             }
296              
297             sub readFieldBegin
298             {
299 54     54 0 59 my $self = shift;
300 54         71 my ($name, $fieldType, $fieldId) = @_;
301              
302 54         98 my $result = $self->readByte($fieldType);
303              
304 54 100       88 if ($$fieldType == Thrift::TType::STOP) {
305 28         33 $$fieldId = 0;
306 28         49 return $result;
307             }
308              
309 26         46 $result += $self->readI16($fieldId);
310              
311 26         43 return $result;
312             }
313              
314             sub readFieldEnd() {
315 26     26 0 29 my $self = shift;
316 26         40 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 2 my $self = shift;
339 1         2 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 2 my $self = shift;
349 1         2 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 132 my $self = shift;
382 61         67 my $value = shift;
383              
384 61         103 my $data = $self->{trans}->readAll(1);
385 60         112 my @arr = unpack('c', $data);
386 60         76 $$value = $arr[0];
387 60         78 return 1;
388             }
389              
390             sub readI16
391             {
392 26     26 0 30 my $self = shift;
393 26         34 my $value = shift;
394              
395 26         43 my $data = $self->{trans}->readAll(2);
396              
397 26         51 my @arr = unpack('n', $data);
398              
399 26         32 $$value = $arr[0];
400              
401 26 50       47 if ($$value > 0x7fff) {
402 0         0 $$value = 0 - (($$value - 1) ^ 0xffff);
403             }
404              
405 26         33 return 2;
406             }
407              
408             sub readI32
409             {
410 102     102 0 119 my $self = shift;
411 102         110 my $value= shift;
412              
413 102         177 my $data = $self->{trans}->readAll(4);
414 102         203 my @arr = unpack('N', $data);
415              
416 102         114 $$value = $arr[0];
417 102 100       153 if ($$value > 0x7fffffff) {
418 26         42 $$value = 0 - (($$value - 1) ^ 0xffffffff);
419             }
420 102         173 return 4;
421             }
422              
423             sub readI64
424             {
425 2     2 0 3 my $self = shift;
426 2         3 my $value = shift;
427              
428 2         5 my $data = $self->{trans}->readAll(8);
429              
430 2         9 my ($hi,$lo)=unpack('NN',$data);
431              
432 2         8 my $vec = Bit::Vector->new(64);
433              
434 2         10 $vec->Chunk_Store(32,32,$hi);
435 2         5 $vec->Chunk_Store(32,0,$lo);
436              
437 2         22 $$value = $vec->to_Dec();
438              
439 2         8 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 39 my $self = shift;
465 32         37 my $value = shift;
466              
467 32         34 my $len;
468 32         42 my $result = $self->readI32(\$len);
469              
470 32 50       51 if ($len) {
471 32         55 $$value = $self->{trans}->readAll($len);
472             }
473             else {
474 0         0 $$value = '';
475             }
476              
477 32         58 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         13  
  3         864  
501 3     3   21 use version 0.77; our $VERSION = version->declare("$Thrift::VERSION");
  3         36  
  3         16  
502              
503             sub new
504             {
505 2     2   14 my $classname = shift;
506 2         11 my $self = $classname->SUPER::new();
507              
508 2         16 return bless($self,$classname);
509             }
510              
511             sub getProtocol{
512 4     4   12 my $self = shift;
513 4         13 my $trans = shift;
514              
515 4         9 return Thrift::BinaryProtocol->new($trans);
516             }
517              
518             1;