blob: 3b2f589d28ffbf760ed870db4229d46bb6f864bc [file] [log] [blame]
Mark Slee6e536442006-06-30 18:28:50 +00001<?php
2
Mark Sleecfc01932006-09-01 22:18:16 +00003/**
Mark Slee4902c052007-03-01 00:31:30 +00004 * Copyright (c) 2006- Facebook
5 * Distributed under the Thrift Software License
6 *
7 * See accompanying file LICENSE or visit the Thrift site at:
8 * http://developers.facebook.com/thrift/
9 *
10 * @package thrift.protocol
Mark Slee4902c052007-03-01 00:31:30 +000011 */
12
13/**
Mark Slee5f8237d2006-10-26 04:57:03 +000014 * Protocol module. Contains all the types and definitions needed to implement
15 * a protocol encoder/decoder.
Mark Slee6e536442006-06-30 18:28:50 +000016 *
17 * @package thrift.protocol
Mark Slee6e536442006-06-30 18:28:50 +000018 */
Mark Slee5f8237d2006-10-26 04:57:03 +000019
Mark Slee5f8237d2006-10-26 04:57:03 +000020/**
Mark Sleedac78562007-02-21 07:35:03 +000021 * Protocol exceptions
22 */
23class TProtocolException extends TException {
24 const UNKNOWN = 0;
25 const INVALID_DATA = 1;
26 const NEGATIVE_SIZE = 2;
27 const SIZE_LIMIT = 3;
Mark Slee808454e2007-06-20 21:51:57 +000028 const BAD_VERSION = 4;
Mark Sleedac78562007-02-21 07:35:03 +000029
30 function __construct($message=null, $code=0) {
31 parent::__construct($message, $code);
32 }
33}
34
35/**
Mark Slee5f8237d2006-10-26 04:57:03 +000036 * Protocol base class module.
37 */
Mark Slee6e536442006-06-30 18:28:50 +000038abstract class TProtocol {
Mark Slee97264862007-12-20 03:23:27 +000039 // The below may seem silly, but it is to get around the problem that the
40 // "instanceof" operator can only take in a T_VARIABLE and not a T_STRING
41 // or T_CONSTANT_ENCAPSED_STRING. Using "is_a()" instead of "instanceof" is
42 // a workaround but is deprecated in PHP5. This is used in the generated
43 // deserialization code.
44 static $TBINARYPROTOCOLACCELERATED = 'TBinaryProtocolAccelerated';
Mark Slee6e536442006-06-30 18:28:50 +000045
Mark Slee5f8237d2006-10-26 04:57:03 +000046 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000047 * Underlying transport
Mark Slee5f8237d2006-10-26 04:57:03 +000048 *
49 * @var TTransport
50 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000051 protected $trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000052
53 /**
54 * Constructor
55 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000056 protected function __construct($trans) {
57 $this->trans_ = $trans;
Mark Slee5f8237d2006-10-26 04:57:03 +000058 }
59
60 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000061 * Accessor for transport
Mark Slee5f8237d2006-10-26 04:57:03 +000062 *
63 * @return TTransport
64 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000065 public function getTransport() {
66 return $this->trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000067 }
68
Mark Slee97264862007-12-20 03:23:27 +000069 /**
Mark Sleecfc01932006-09-01 22:18:16 +000070 * Writes the message header
71 *
Mark Sleecfc01932006-09-01 22:18:16 +000072 * @param string $name Function name
73 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
74 * @param int $seqid The sequence id of this message
75 */
Mark Slee5f8237d2006-10-26 04:57:03 +000076 public abstract function writeMessageBegin($name, $type, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000077
Mark Sleecfc01932006-09-01 22:18:16 +000078 /**
79 * Close the message
Mark Sleecfc01932006-09-01 22:18:16 +000080 */
Mark Slee5f8237d2006-10-26 04:57:03 +000081 public abstract function writeMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +000082
Mark Slee6e536442006-06-30 18:28:50 +000083 /**
84 * Writes a struct header.
85 *
Mark Slee6e536442006-06-30 18:28:50 +000086 * @param string $name Struct name
87 * @throws TException on write error
88 * @return int How many bytes written
89 */
Mark Slee5f8237d2006-10-26 04:57:03 +000090 public abstract function writeStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +000091
92 /**
93 * Close a struct.
94 *
Mark Slee6e536442006-06-30 18:28:50 +000095 * @throws TException on write error
96 * @return int How many bytes written
97 */
Mark Slee5f8237d2006-10-26 04:57:03 +000098 public abstract function writeStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +000099
100 /*
101 * Starts a field.
102 *
Mark Slee6e536442006-06-30 18:28:50 +0000103 * @param string $name Field name
104 * @param int $type Field type
105 * @param int $fid Field id
106 * @throws TException on write error
107 * @return int How many bytes written
108 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000109 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000110
Mark Slee5f8237d2006-10-26 04:57:03 +0000111 public abstract function writeFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000112
Mark Slee5f8237d2006-10-26 04:57:03 +0000113 public abstract function writeFieldStop();
Mark Slee6e536442006-06-30 18:28:50 +0000114
Mark Slee5f8237d2006-10-26 04:57:03 +0000115 public abstract function writeMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000116
Mark Slee5f8237d2006-10-26 04:57:03 +0000117 public abstract function writeMapEnd();
Mark Slee97264862007-12-20 03:23:27 +0000118
Mark Slee5f8237d2006-10-26 04:57:03 +0000119 public abstract function writeListBegin($elemType, $size);
Mark Slee97264862007-12-20 03:23:27 +0000120
Mark Slee5f8237d2006-10-26 04:57:03 +0000121 public abstract function writeListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000122
Mark Slee5f8237d2006-10-26 04:57:03 +0000123 public abstract function writeSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000124
Mark Slee5f8237d2006-10-26 04:57:03 +0000125 public abstract function writeSetEnd();
Mark Slee97264862007-12-20 03:23:27 +0000126
Mark Slee5f8237d2006-10-26 04:57:03 +0000127 public abstract function writeBool($bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000128
Mark Slee5f8237d2006-10-26 04:57:03 +0000129 public abstract function writeByte($byte);
Mark Slee97264862007-12-20 03:23:27 +0000130
Mark Slee5f8237d2006-10-26 04:57:03 +0000131 public abstract function writeI16($i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000132
Mark Slee5f8237d2006-10-26 04:57:03 +0000133 public abstract function writeI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000134
Mark Slee5f8237d2006-10-26 04:57:03 +0000135 public abstract function writeI64($i64);
Mark Slee6e536442006-06-30 18:28:50 +0000136
Mark Slee5f8237d2006-10-26 04:57:03 +0000137 public abstract function writeDouble($dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000138
Mark Slee5f8237d2006-10-26 04:57:03 +0000139 public abstract function writeString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000140
Mark Sleecfc01932006-09-01 22:18:16 +0000141 /**
142 * Reads the message header
143 *
Mark Sleecfc01932006-09-01 22:18:16 +0000144 * @param string $name Function name
145 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
146 * @parem int $seqid The sequence id of this message
147 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000148 public abstract function readMessageBegin(&$name, &$type, &$seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000149
Mark Sleecfc01932006-09-01 22:18:16 +0000150 /**
151 * Read the close of message
Mark Sleecfc01932006-09-01 22:18:16 +0000152 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000153 public abstract function readMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000154
Mark Slee5f8237d2006-10-26 04:57:03 +0000155 public abstract function readStructBegin(&$name);
Mark Slee97264862007-12-20 03:23:27 +0000156
Mark Slee5f8237d2006-10-26 04:57:03 +0000157 public abstract function readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000158
Mark Slee5f8237d2006-10-26 04:57:03 +0000159 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000160
Mark Slee5f8237d2006-10-26 04:57:03 +0000161 public abstract function readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000162
Mark Slee5f8237d2006-10-26 04:57:03 +0000163 public abstract function readMapBegin(&$keyType, &$valType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000164
Mark Slee5f8237d2006-10-26 04:57:03 +0000165 public abstract function readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000166
Mark Slee5f8237d2006-10-26 04:57:03 +0000167 public abstract function readListBegin(&$elemType, &$size);
Mark Slee97264862007-12-20 03:23:27 +0000168
Mark Slee5f8237d2006-10-26 04:57:03 +0000169 public abstract function readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000170
Mark Slee5f8237d2006-10-26 04:57:03 +0000171 public abstract function readSetBegin(&$elemType, &$size);
Mark Slee97264862007-12-20 03:23:27 +0000172
Mark Slee5f8237d2006-10-26 04:57:03 +0000173 public abstract function readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000174
Mark Slee5f8237d2006-10-26 04:57:03 +0000175 public abstract function readBool(&$bool);
Mark Slee97264862007-12-20 03:23:27 +0000176
Mark Slee5f8237d2006-10-26 04:57:03 +0000177 public abstract function readByte(&$byte);
Mark Slee97264862007-12-20 03:23:27 +0000178
Mark Slee5f8237d2006-10-26 04:57:03 +0000179 public abstract function readI16(&$i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000180
Mark Slee5f8237d2006-10-26 04:57:03 +0000181 public abstract function readI32(&$i32);
Mark Slee6e536442006-06-30 18:28:50 +0000182
Mark Slee5f8237d2006-10-26 04:57:03 +0000183 public abstract function readI64(&$i64);
Mark Slee6e536442006-06-30 18:28:50 +0000184
Mark Slee5f8237d2006-10-26 04:57:03 +0000185 public abstract function readDouble(&$dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000186
Mark Slee5f8237d2006-10-26 04:57:03 +0000187 public abstract function readString(&$str);
Mark Slee6e536442006-06-30 18:28:50 +0000188
Mark Sleecfc01932006-09-01 22:18:16 +0000189 /**
190 * The skip function is a utility to parse over unrecognized date without
191 * causing corruption.
192 *
Mark Sleecfc01932006-09-01 22:18:16 +0000193 * @param TType $type What type is it
194 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000195 public function skip($type) {
Mark Slee6e536442006-06-30 18:28:50 +0000196 switch ($type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000197 case TType::BOOL:
Mark Slee5f8237d2006-10-26 04:57:03 +0000198 return $this->readBool($bool);
Mark Slee6e536442006-06-30 18:28:50 +0000199 case TType::BYTE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000200 return $this->readByte($byte);
Adam Nichols2f816f22007-01-11 21:25:29 +0000201 case TType::I16:
Mark Slee5f8237d2006-10-26 04:57:03 +0000202 return $this->readI16($i16);
Mark Slee6e536442006-06-30 18:28:50 +0000203 case TType::I32:
Mark Slee5f8237d2006-10-26 04:57:03 +0000204 return $this->readI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000205 case TType::I64:
Mark Slee5f8237d2006-10-26 04:57:03 +0000206 return $this->readI64($i64);
Mark Sleec98d0502006-09-06 02:42:25 +0000207 case TType::DOUBLE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000208 return $this->readDouble($dub);
Mark Slee6e536442006-06-30 18:28:50 +0000209 case TType::STRING:
Mark Slee5f8237d2006-10-26 04:57:03 +0000210 return $this->readString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000211 case TType::STRUCT:
212 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000213 $result = $this->readStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000214 while (true) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000215 $result += $this->readFieldBegin($name, $ftype, $fid);
Mark Slee6e536442006-06-30 18:28:50 +0000216 if ($ftype == TType::STOP) {
217 break;
218 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000219 $result += $this->skip($ftype);
220 $result += $this->readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000221 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000222 $result += $this->readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000223 return $result;
224 }
225 case TType::MAP:
226 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000227 $result = $this->readMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000228 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000229 $result += $this->skip($keyType);
230 $result += $this->skip($valType);
Mark Slee6e536442006-06-30 18:28:50 +0000231 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000232 $result += $this->readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000233 return $result;
234 }
235 case TType::SET:
236 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000237 $result = $this->readSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000238 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000239 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000240 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000241 $result += $this->readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000242 return $result;
243 }
244 case TType::LST:
245 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000246 $result = $this->readListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000247 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000248 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000249 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000250 $result += $this->readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000251 return $result;
252 }
253 default:
254 return 0;
255 }
256 }
Mark Slee99e2b262006-10-10 01:42:29 +0000257
258 /**
259 * Utility for skipping binary data
260 *
261 * @param TTransport $itrans TTransport object
262 * @param int $type Field type
263 */
264 public static function skipBinary($itrans, $type) {
265 switch ($type) {
266 case TType::BOOL:
267 return $itrans->readAll(1);
268 case TType::BYTE:
269 return $itrans->readAll(1);
Adam Nichols2f816f22007-01-11 21:25:29 +0000270 case TType::I16:
Mark Slee99e2b262006-10-10 01:42:29 +0000271 return $itrans->readAll(2);
272 case TType::I32:
273 return $itrans->readAll(4);
274 case TType::I64:
275 return $itrans->readAll(8);
276 case TType::DOUBLE:
277 return $itrans->readAll(8);
278 case TType::STRING:
279 $len = unpack('N', $itrans->readAll(4));
280 $len = $len[1];
281 if ($len > 0x7fffffff) {
282 $len = 0 - (($len - 1) ^ 0xffffffff);
283 }
284 return 4 + $itrans->readAll($len);
285 case TType::STRUCT:
286 {
287 $result = 0;
288 while (true) {
289 $ftype = 0;
290 $fid = 0;
Mark Slee5f8237d2006-10-26 04:57:03 +0000291 $data = $itrans->readAll(1);
Mark Slee99e2b262006-10-10 01:42:29 +0000292 $arr = unpack('c', $data);
293 $ftype = $arr[1];
294 if ($ftype == TType::STOP) {
295 break;
296 }
297 // I16 field id
298 $result += $itrans->readAll(2);
299 $result += self::skipBinary($itrans, $ftype);
300 }
301 return $result;
302 }
303 case TType::MAP:
304 {
305 // Ktype
306 $data = $itrans->readAll(1);
307 $arr = unpack('c', $data);
308 $ktype = $arr[1];
309 // Vtype
310 $data = $itrans->readAll(1);
311 $arr = unpack('c', $data);
312 $vtype = $arr[1];
313 // Size
314 $data = $itrans->readAll(4);
315 $arr = unpack('N', $data);
316 $size = $arr[1];
317 if ($size > 0x7fffffff) {
318 $size = 0 - (($size - 1) ^ 0xffffffff);
319 }
320 $result = 6;
321 for ($i = 0; $i < $size; $i++) {
322 $result += self::skipBinary($itrans, $ktype);
323 $result += self::skipBinary($itrans, $vtype);
324 }
325 return $result;
326 }
327 case TType::SET:
328 case TType::LST:
329 {
330 // Vtype
331 $data = $itrans->readAll(1);
332 $arr = unpack('c', $data);
333 $vtype = $arr[1];
334 // Size
335 $data = $itrans->readAll(4);
336 $arr = unpack('N', $data);
337 $size = $arr[1];
338 if ($size > 0x7fffffff) {
339 $size = 0 - (($size - 1) ^ 0xffffffff);
340 }
341 $result = 5;
342 for ($i = 0; $i < $size; $i++) {
343 $result += self::skipBinary($itrans, $vtype);
344 }
345 return $result;
346 }
347 default:
348 return 0;
Mark Slee97264862007-12-20 03:23:27 +0000349 }
Mark Slee99e2b262006-10-10 01:42:29 +0000350 }
Mark Slee6e536442006-06-30 18:28:50 +0000351}
352
Mark Slee5f8237d2006-10-26 04:57:03 +0000353/**
354 * Protocol factory creates protocol objects from transports
355 */
356interface TProtocolFactory {
357 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000358 * Build a protocol from the base transport
Mark Slee5f8237d2006-10-26 04:57:03 +0000359 *
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000360 * @return TProtcol protocol
Mark Slee5f8237d2006-10-26 04:57:03 +0000361 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000362 public function getProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000363}
Mark Slee97264862007-12-20 03:23:27 +0000364
Mark Slee5f8237d2006-10-26 04:57:03 +0000365
Mark Slee6e536442006-06-30 18:28:50 +0000366?>