r1273@opsdev009 (orig r68684): dreiss | 2007-11-07 17:05:46 -0800
[amiethrift.git] / lib / perl / lib / Thrift / BinaryProtocol.pm
blobbb570a26380b884d930270cfb28e04bed581960c
2 # Copyright (c) 2006- Facebook
3 # Distributed under the Thrift Software License
5 # See accompanying file LICENSE or visit the Thrift site at:
6 # http://developers.facebook.com/thrift/
8 # package - thrift.protocol.binary
9 # author - T Jake Luciani <jakers@gmail.com>
10 # author - Mark Slee <mcslee@facebook.com>
13 require 5.6.0;
15 use strict;
16 use warnings;
18 use Thrift;
19 use Thrift::Protocol;
21 use Bit::Vector;
24 # Binary implementation of the Thrift protocol.
26 package Thrift::BinaryProtocol;
27 use base('Thrift::Protocol');
29 use constant VERSION_MASK => 0xffff0000;
30 use constant VERSION_1 => 0x80010000;
32 sub new
34 my $classname = shift;
35 my $trans = shift;
36 my $self = $classname->SUPER::new($trans);
38 return bless($self,$classname);
41 sub writeMessageBegin
43 my $self = shift;
44 my ($name, $type, $seqid) = @_;
46 return
47 $self->writeI32(VERSION_1 | $type) +
48 $self->writeString($name) +
49 $self->writeI32($seqid);
52 sub writeMessageEnd
54 my $self = shift;
55 return 0;
58 sub writeStructBegin{
59 my $self = shift;
60 my $name = shift;
61 return 0;
64 sub writeStructEnd
66 my $self = shift;
67 return 0;
70 sub writeFieldBegin
72 my $self = shift;
73 my ($fieldName, $fieldType, $fieldId) = @_;
75 return
76 $self->writeByte($fieldType) +
77 $self->writeI16($fieldId);
80 sub writeFieldEnd
82 my $self = shift;
83 return 0;
86 sub writeFieldStop
88 my $self = shift;
89 return $self->writeByte(TType::STOP);
92 sub writeMapBegin
94 my $self = shift;
95 my ($keyType, $valType, $size) = @_;
97 return
98 $self->writeByte($keyType) +
99 $self->writeByte($valType) +
100 $self->writeI32($size);
103 sub writeMapEnd
105 my $self = shift;
106 return 0;
109 sub writeListBegin
111 my $self = shift;
112 my ($elemType, $size) = @_;
114 return
115 $self->writeByte($elemType) +
116 $self->writeI32($size);
119 sub writeListEnd
121 my $self = shift;
122 return 0;
125 sub writeSetBegin
127 my $self = shift;
128 my ($elemType, $size) = @_;
130 return
131 $self->writeByte($elemType) +
132 $self->writeI32($size);
135 sub writeSetEnd
137 my $self = shift;
138 return 0;
141 sub writeBool
143 my $self = shift;
144 my $value = shift;
146 my $data = pack('c', $value ? 1 : 0);
147 $self->{trans}->write($data, 1);
148 return 1;
151 sub writeByte
153 my $self = shift;
154 my $value= shift;
156 my $data = pack('c', $value);
157 $self->{trans}->write($data, 1);
158 return 1;
161 sub writeI16
163 my $self = shift;
164 my $value= shift;
166 my $data = pack('n', $value);
167 $self->{trans}->write($data, 2);
168 return 2;
171 sub writeI32
173 my $self = shift;
174 my $value= shift;
176 my $data = pack('N', $value);
177 $self->{trans}->write($data, 4);
178 return 4;
181 sub writeI64
183 my $self = shift;
184 my $value= shift;
185 my $data;
187 my $vec;
188 #stop annoying error
189 $vec = Bit::Vector->new_Dec(64, $value);
190 $data = pack 'NN', $vec->Chunk_Read(32, 32), $vec->Chunk_Read(32, 0);
192 $self->{trans}->write($data, 8);
194 return 8;
198 sub writeDouble
200 my $self = shift;
201 my $value= shift;
203 my $data = pack('d', $value);
204 $self->{trans}->write(scalar reverse($data), 8);
205 return 8;
208 sub writeString{
209 my $self = shift;
210 my $value= shift;
212 my $len = length($value);
214 my $result = $self->writeI32($len);
215 if ($len) {
216 $self->{trans}->write($value,$len);
218 return $result + $len;
223 #All references
225 sub readMessageBegin
227 my $self = shift;
228 my ($name, $type, $seqid) = @_;
230 my $version = 0;
231 my $result = $self->readI32(\$version);
232 if (($version & VERSION_MASK) > 0) {
233 if (($version & VERSION_MASK) != VERSION_1) {
234 die new Thrift::TException('Missing version identifier')
236 $$type = $version & 0x000000ff;
237 return
238 $result +
239 $self->readString($name) +
240 $self->readI32($seqid);
241 } else { # old client support code
242 return
243 $result +
244 $self->readStringBody($name, $version) + # version here holds the size of the string
245 $self->readByte($type) +
246 $self->readI32($seqid);
250 sub readMessageEnd
252 my $self = shift;
253 return 0;
256 sub readStructBegin
258 my $self = shift;
259 my $name = shift;
261 $$name = '';
263 return 0;
266 sub readStructEnd
268 my $self = shift;
269 return 0;
272 sub readFieldBegin
274 my $self = shift;
275 my ($name, $fieldType, $fieldId) = @_;
277 my $result = $self->readByte($fieldType);
279 if ($$fieldType == TType::STOP) {
280 $$fieldId = 0;
281 return $result;
284 $result += $self->readI16($fieldId);
286 return $result;
289 sub readFieldEnd() {
290 my $self = shift;
291 return 0;
294 sub readMapBegin
296 my $self = shift;
297 my ($keyType, $valType, $size) = @_;
299 return
300 $self->readByte($keyType) +
301 $self->readByte($valType) +
302 $self->readI32($size);
305 sub readMapEnd()
307 my $self = shift;
308 return 0;
311 sub readListBegin
313 my $self = shift;
314 my ($elemType, $size) = @_;
316 return
317 $self->readByte($elemType) +
318 $self->readI32($size);
321 sub readListEnd
323 my $self = shift;
324 return 0;
327 sub readSetBegin
329 my $self = shift;
330 my ($elemType, $size) = @_;
332 return
333 $self->readByte($elemType) +
334 $self->readI32($size);
337 sub readSetEnd
339 my $self = shift;
340 return 0;
343 sub readBool
345 my $self = shift;
346 my $value = shift;
348 my $data = $self->{trans}->readAll(1);
349 my @arr = unpack('c', $data);
350 $$value = $arr[0] == 1;
351 return 1;
354 sub readByte
356 my $self = shift;
357 my $value = shift;
359 my $data = $self->{trans}->readAll(1);
360 my @arr = unpack('c', $data);
361 $$value = $arr[0];
362 return 1;
365 sub readI16
367 my $self = shift;
368 my $value = shift;
370 my $data = $self->{trans}->readAll(2);
372 my @arr = unpack('n', $data);
374 $$value = $arr[0];
376 if ($$value > 0x7fff) {
377 $$value = 0 - (($$value - 1) ^ 0xffff);
380 return 2;
383 sub readI32
385 my $self = shift;
386 my $value= shift;
388 my $data = $self->{trans}->readAll(4);
389 my @arr = unpack('N', $data);
391 $$value = $arr[0];
392 if ($$value > 0x7fffffff) {
393 $$value = 0 - (($$value - 1) ^ 0xffffffff);
395 return 4;
398 sub readI64
400 my $self = shift;
401 my $value = shift;
403 my $data = $self->{trans}->readAll(8);
405 my ($hi,$lo)=unpack('NN',$data);
407 my $vec = new Bit::Vector(64);
409 $vec->Chunk_Store(32,32,$hi);
410 $vec->Chunk_Store(32,0,$lo);
412 $$value = $vec->to_Dec();
414 return 8;
417 sub readDouble
419 my $self = shift;
420 my $value = shift;
422 my $data = scalar reverse($self->{trans}->readAll(8));
423 my @arr = unpack('d', $data);
425 $$value = $arr[0];
427 return 8;
430 sub readString
432 my $self = shift;
433 my $value = shift;
435 my $len;
436 my $result = $self->readI32(\$len);
438 if ($len) {
439 $$value = $self->{trans}->readAll($len);
440 } else {
441 $$value = '';
444 return $result + $len;
447 sub readStringBody
449 my $self = shift;
450 my $value = shift;
451 my $len = shift;
453 if ($len) {
454 $$value = $self->{trans}->readAll($len);
455 } else {
456 $$value = '';
459 return $len;
463 # Binary Protocol Factory
465 package TBinaryProtocolFactory;
466 use base('TProtocolFactory');
468 sub new
470 my $classname = shift;
471 my $self = $classname->SUPER::new();
473 return bless($self,$classname);
476 sub getProtocol{
477 my $self = shift;
478 my $trans = shift;
480 return new TBinaryProtocol($trans);