blob: 95196041ce7a9cb2ba97550d22cbc792037b9459 [file] [log] [blame]
Mark Slee6e536442006-06-30 18:28:50 +00001<?php
2
Mark Sleecfc01932006-09-01 22:18:16 +00003/**
Mark Slee5f8237d2006-10-26 04:57:03 +00004 * Protocol module. Contains all the types and definitions needed to implement
5 * a protocol encoder/decoder.
Mark Slee6e536442006-06-30 18:28:50 +00006 *
7 * @package thrift.protocol
8 * @author Mark Slee <mcslee@facebook.com>
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +00009 * @author Aditya Agarwal <aditya@facebook.com>
Mark Slee6e536442006-06-30 18:28:50 +000010 */
Mark Slee5f8237d2006-10-26 04:57:03 +000011
12/**
13 * Data types that can be sent via Thrift
14 */
15class TType {
16 const STOP = 0;
17 const VOID = 1;
18 const BOOL = 2;
19 const BYTE = 3;
20 const I08 = 3;
21 const DOUBLE = 4;
22 const I16 = 6;
23 const I32 = 8;
24 const I64 = 10;
25 const STRING = 11;
26 const UTF7 = 11;
27 const STRUCT = 12;
28 const MAP = 13;
29 const SET = 14;
30 const LST = 15; // N.B. cannot use LIST keyword in PHP!
31 const UTF8 = 16;
32 const UTF16 = 17;
33}
34
35/**
36 * Message types for RPC
37 */
38class TMessageType {
39 const CALL = 1;
40 const REPLY = 2;
41}
42
43/**
44 * Protocol base class module.
45 */
Mark Slee6e536442006-06-30 18:28:50 +000046abstract class TProtocol {
47
Mark Slee5f8237d2006-10-26 04:57:03 +000048 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000049 * Underlying transport
Mark Slee5f8237d2006-10-26 04:57:03 +000050 *
51 * @var TTransport
52 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000053 protected $trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000054
55 /**
56 * Constructor
57 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000058 protected function __construct($trans) {
59 $this->trans_ = $trans;
Mark Slee5f8237d2006-10-26 04:57:03 +000060 }
61
62 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000063 * Accessor for transport
Mark Slee5f8237d2006-10-26 04:57:03 +000064 *
65 * @return TTransport
66 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +000067 public function getTransport() {
68 return $this->trans_;
Mark Slee5f8237d2006-10-26 04:57:03 +000069 }
70
Mark Sleecfc01932006-09-01 22:18:16 +000071 /**
72 * Writes the message header
73 *
Mark Sleecfc01932006-09-01 22:18:16 +000074 * @param string $name Function name
75 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
76 * @param int $seqid The sequence id of this message
77 */
Mark Slee5f8237d2006-10-26 04:57:03 +000078 public abstract function writeMessageBegin($name, $type, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000079
Mark Sleecfc01932006-09-01 22:18:16 +000080 /**
81 * Close the message
Mark Sleecfc01932006-09-01 22:18:16 +000082 */
Mark Slee5f8237d2006-10-26 04:57:03 +000083 public abstract function writeMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +000084
Mark Slee6e536442006-06-30 18:28:50 +000085 /**
86 * Writes a struct header.
87 *
Mark Slee6e536442006-06-30 18:28:50 +000088 * @param string $name Struct name
89 * @throws TException on write error
90 * @return int How many bytes written
91 */
Mark Slee5f8237d2006-10-26 04:57:03 +000092 public abstract function writeStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +000093
94 /**
95 * Close a struct.
96 *
Mark Slee6e536442006-06-30 18:28:50 +000097 * @throws TException on write error
98 * @return int How many bytes written
99 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000100 public abstract function writeStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000101
102 /*
103 * Starts a field.
104 *
Mark Slee6e536442006-06-30 18:28:50 +0000105 * @param string $name Field name
106 * @param int $type Field type
107 * @param int $fid Field id
108 * @throws TException on write error
109 * @return int How many bytes written
110 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000111 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000112
Mark Slee5f8237d2006-10-26 04:57:03 +0000113 public abstract function writeFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000114
Mark Slee5f8237d2006-10-26 04:57:03 +0000115 public abstract function writeFieldStop();
Mark Slee6e536442006-06-30 18:28:50 +0000116
Mark Slee5f8237d2006-10-26 04:57:03 +0000117 public abstract function writeMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000118
Mark Slee5f8237d2006-10-26 04:57:03 +0000119 public abstract function writeMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000120
Mark Slee5f8237d2006-10-26 04:57:03 +0000121 public abstract function writeListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000122
Mark Slee5f8237d2006-10-26 04:57:03 +0000123 public abstract function writeListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000124
Mark Slee5f8237d2006-10-26 04:57:03 +0000125 public abstract function writeSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000126
Mark Slee5f8237d2006-10-26 04:57:03 +0000127 public abstract function writeSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000128
Mark Slee5f8237d2006-10-26 04:57:03 +0000129 public abstract function writeBool($bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000130
Mark Slee5f8237d2006-10-26 04:57:03 +0000131 public abstract function writeByte($byte);
Mark Slee6e536442006-06-30 18:28:50 +0000132
Mark Slee5f8237d2006-10-26 04:57:03 +0000133 public abstract function writeI16($i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000134
Mark Slee5f8237d2006-10-26 04:57:03 +0000135 public abstract function writeI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000136
Mark Slee5f8237d2006-10-26 04:57:03 +0000137 public abstract function writeI64($i64);
Mark Slee6e536442006-06-30 18:28:50 +0000138
Mark Slee5f8237d2006-10-26 04:57:03 +0000139 public abstract function writeDouble($dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000140
Mark Slee5f8237d2006-10-26 04:57:03 +0000141 public abstract function writeString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000142
Mark Sleecfc01932006-09-01 22:18:16 +0000143 /**
144 * Reads the message header
145 *
Mark Sleecfc01932006-09-01 22:18:16 +0000146 * @param string $name Function name
147 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
148 * @parem int $seqid The sequence id of this message
149 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000150 public abstract function readMessageBegin(&$name, &$type, &$seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000151
Mark Sleecfc01932006-09-01 22:18:16 +0000152 /**
153 * Read the close of message
Mark Sleecfc01932006-09-01 22:18:16 +0000154 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000155 public abstract function readMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000156
Mark Slee5f8237d2006-10-26 04:57:03 +0000157 public abstract function readStructBegin(&$name);
Mark Slee6e536442006-06-30 18:28:50 +0000158
Mark Slee5f8237d2006-10-26 04:57:03 +0000159 public abstract function readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000160
Mark Slee5f8237d2006-10-26 04:57:03 +0000161 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000162
Mark Slee5f8237d2006-10-26 04:57:03 +0000163 public abstract function readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000164
Mark Slee5f8237d2006-10-26 04:57:03 +0000165 public abstract function readMapBegin(&$keyType, &$valType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000166
Mark Slee5f8237d2006-10-26 04:57:03 +0000167 public abstract function readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000168
Mark Slee5f8237d2006-10-26 04:57:03 +0000169 public abstract function readListBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000170
Mark Slee5f8237d2006-10-26 04:57:03 +0000171 public abstract function readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000172
Mark Slee5f8237d2006-10-26 04:57:03 +0000173 public abstract function readSetBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000174
Mark Slee5f8237d2006-10-26 04:57:03 +0000175 public abstract function readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000176
Mark Slee5f8237d2006-10-26 04:57:03 +0000177 public abstract function readBool(&$bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000178
Mark Slee5f8237d2006-10-26 04:57:03 +0000179 public abstract function readByte(&$byte);
Mark Slee6e536442006-06-30 18:28:50 +0000180
Mark Slee5f8237d2006-10-26 04:57:03 +0000181 public abstract function readI16(&$i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000182
Mark Slee5f8237d2006-10-26 04:57:03 +0000183 public abstract function readI32(&$i32);
Mark Slee6e536442006-06-30 18:28:50 +0000184
Mark Slee5f8237d2006-10-26 04:57:03 +0000185 public abstract function readI64(&$i64);
Mark Slee6e536442006-06-30 18:28:50 +0000186
Mark Slee5f8237d2006-10-26 04:57:03 +0000187 public abstract function readDouble(&$dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000188
Mark Slee5f8237d2006-10-26 04:57:03 +0000189 public abstract function readString(&$str);
Mark Slee6e536442006-06-30 18:28:50 +0000190
Mark Sleecfc01932006-09-01 22:18:16 +0000191 /**
192 * The skip function is a utility to parse over unrecognized date without
193 * causing corruption.
194 *
Mark Sleecfc01932006-09-01 22:18:16 +0000195 * @param TType $type What type is it
196 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000197 public function skip($type) {
Mark Slee6e536442006-06-30 18:28:50 +0000198 switch ($type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000199 case TType::BOOL:
Mark Slee5f8237d2006-10-26 04:57:03 +0000200 return $this->readBool($bool);
Mark Slee6e536442006-06-30 18:28:50 +0000201 case TType::BYTE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000202 return $this->readByte($byte);
Adam Nichols2f816f22007-01-11 21:25:29 +0000203 case TType::I16:
Mark Slee5f8237d2006-10-26 04:57:03 +0000204 return $this->readI16($i16);
Mark Slee6e536442006-06-30 18:28:50 +0000205 case TType::I32:
Mark Slee5f8237d2006-10-26 04:57:03 +0000206 return $this->readI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000207 case TType::I64:
Mark Slee5f8237d2006-10-26 04:57:03 +0000208 return $this->readI64($i64);
Mark Sleec98d0502006-09-06 02:42:25 +0000209 case TType::DOUBLE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000210 return $this->readDouble($dub);
Mark Slee6e536442006-06-30 18:28:50 +0000211 case TType::STRING:
Mark Slee5f8237d2006-10-26 04:57:03 +0000212 return $this->readString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000213 case TType::STRUCT:
214 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000215 $result = $this->readStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000216 while (true) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000217 $result += $this->readFieldBegin($name, $ftype, $fid);
Mark Slee6e536442006-06-30 18:28:50 +0000218 if ($ftype == TType::STOP) {
219 break;
220 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000221 $result += $this->skip($ftype);
222 $result += $this->readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000223 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000224 $result += $this->readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000225 return $result;
226 }
227 case TType::MAP:
228 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000229 $result = $this->readMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000230 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000231 $result += $this->skip($keyType);
232 $result += $this->skip($valType);
Mark Slee6e536442006-06-30 18:28:50 +0000233 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000234 $result += $this->readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000235 return $result;
236 }
237 case TType::SET:
238 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000239 $result = $this->readSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000240 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000241 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000242 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000243 $result += $this->readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000244 return $result;
245 }
246 case TType::LST:
247 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000248 $result = $this->readListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000249 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000250 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000251 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000252 $result += $this->readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000253 return $result;
254 }
255 default:
256 return 0;
257 }
258 }
Mark Slee99e2b262006-10-10 01:42:29 +0000259
260 /**
261 * Utility for skipping binary data
262 *
263 * @param TTransport $itrans TTransport object
264 * @param int $type Field type
265 */
266 public static function skipBinary($itrans, $type) {
267 switch ($type) {
268 case TType::BOOL:
269 return $itrans->readAll(1);
270 case TType::BYTE:
271 return $itrans->readAll(1);
Adam Nichols2f816f22007-01-11 21:25:29 +0000272 case TType::I16:
Mark Slee99e2b262006-10-10 01:42:29 +0000273 return $itrans->readAll(2);
274 case TType::I32:
275 return $itrans->readAll(4);
276 case TType::I64:
277 return $itrans->readAll(8);
278 case TType::DOUBLE:
279 return $itrans->readAll(8);
280 case TType::STRING:
281 $len = unpack('N', $itrans->readAll(4));
282 $len = $len[1];
283 if ($len > 0x7fffffff) {
284 $len = 0 - (($len - 1) ^ 0xffffffff);
285 }
286 return 4 + $itrans->readAll($len);
287 case TType::STRUCT:
288 {
289 $result = 0;
290 while (true) {
291 $ftype = 0;
292 $fid = 0;
Mark Slee5f8237d2006-10-26 04:57:03 +0000293 $data = $itrans->readAll(1);
Mark Slee99e2b262006-10-10 01:42:29 +0000294 $arr = unpack('c', $data);
295 $ftype = $arr[1];
296 if ($ftype == TType::STOP) {
297 break;
298 }
299 // I16 field id
300 $result += $itrans->readAll(2);
301 $result += self::skipBinary($itrans, $ftype);
302 }
303 return $result;
304 }
305 case TType::MAP:
306 {
307 // Ktype
308 $data = $itrans->readAll(1);
309 $arr = unpack('c', $data);
310 $ktype = $arr[1];
311 // Vtype
312 $data = $itrans->readAll(1);
313 $arr = unpack('c', $data);
314 $vtype = $arr[1];
315 // Size
316 $data = $itrans->readAll(4);
317 $arr = unpack('N', $data);
318 $size = $arr[1];
319 if ($size > 0x7fffffff) {
320 $size = 0 - (($size - 1) ^ 0xffffffff);
321 }
322 $result = 6;
323 for ($i = 0; $i < $size; $i++) {
324 $result += self::skipBinary($itrans, $ktype);
325 $result += self::skipBinary($itrans, $vtype);
326 }
327 return $result;
328 }
329 case TType::SET:
330 case TType::LST:
331 {
332 // Vtype
333 $data = $itrans->readAll(1);
334 $arr = unpack('c', $data);
335 $vtype = $arr[1];
336 // Size
337 $data = $itrans->readAll(4);
338 $arr = unpack('N', $data);
339 $size = $arr[1];
340 if ($size > 0x7fffffff) {
341 $size = 0 - (($size - 1) ^ 0xffffffff);
342 }
343 $result = 5;
344 for ($i = 0; $i < $size; $i++) {
345 $result += self::skipBinary($itrans, $vtype);
346 }
347 return $result;
348 }
349 default:
350 return 0;
351 }
352 }
Mark Slee6e536442006-06-30 18:28:50 +0000353}
354
Mark Slee5f8237d2006-10-26 04:57:03 +0000355/**
356 * Protocol factory creates protocol objects from transports
357 */
358interface TProtocolFactory {
359 /**
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000360 * Build a protocol from the base transport
Mark Slee5f8237d2006-10-26 04:57:03 +0000361 *
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000362 * @return TProtcol protocol
Mark Slee5f8237d2006-10-26 04:57:03 +0000363 */
Aditya Agarwal6a5bcaa2007-02-06 02:50:56 +0000364 public function getProtocol($trans);
Mark Slee5f8237d2006-10-26 04:57:03 +0000365}
366
367
Mark Slee6e536442006-06-30 18:28:50 +0000368?>