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