File Coverage

blib/lib/Thrift/BinaryProtocol.pm
Criterion Covered Total %
statement 99 225 44.0
branch 6 24 25.0
condition n/a
subroutine 26 55 47.2
pod 0 41 0.0
total 131 345 37.9


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