blob: eb150e37d2f16b489a13fab86a2dbc9340211531 [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>
9 */
Mark Slee5f8237d2006-10-26 04:57:03 +000010
11/**
12 * Data types that can be sent via Thrift
13 */
14class TType {
15 const STOP = 0;
16 const VOID = 1;
17 const BOOL = 2;
18 const BYTE = 3;
19 const I08 = 3;
20 const DOUBLE = 4;
21 const I16 = 6;
22 const I32 = 8;
23 const I64 = 10;
24 const STRING = 11;
25 const UTF7 = 11;
26 const STRUCT = 12;
27 const MAP = 13;
28 const SET = 14;
29 const LST = 15; // N.B. cannot use LIST keyword in PHP!
30 const UTF8 = 16;
31 const UTF16 = 17;
32}
33
34/**
35 * Message types for RPC
36 */
37class TMessageType {
38 const CALL = 1;
39 const REPLY = 2;
40}
41
42/**
43 * Protocol base class module.
44 */
Mark Slee6e536442006-06-30 18:28:50 +000045abstract class TProtocol {
46
Mark Slee5f8237d2006-10-26 04:57:03 +000047 /**
48 * Input transport
49 *
50 * @var TTransport
51 */
52 protected $inputTransport_;
53
54 /**
55 * Output transport
56 *
57 * @var TTransport
58 */
59 protected $outputTransport_;
60
61 /**
62 * Constructor
63 */
64 protected function __construct($in, $out=null) {
65 $this->inputTransport_ = $in;
66 $this->outputTransport_ = $out ? $out : $in;
67 }
68
69 /**
70 * Accessor for input
71 *
72 * @return TTransport
73 */
74 public function getInputTransport() {
75 return $this->inputTransport_;
76 }
77
78 /**
79 * Accessor for output
80 *
81 * @return TTransport
82 */
83 public function getOutputTransport() {
84 return $this->outputTransport_;
85 }
86
Mark Sleecfc01932006-09-01 22:18:16 +000087 /**
88 * Writes the message header
89 *
Mark Sleecfc01932006-09-01 22:18:16 +000090 * @param string $name Function name
91 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
92 * @param int $seqid The sequence id of this message
93 */
Mark Slee5f8237d2006-10-26 04:57:03 +000094 public abstract function writeMessageBegin($name, $type, $seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +000095
Mark Sleecfc01932006-09-01 22:18:16 +000096 /**
97 * Close the message
Mark Sleecfc01932006-09-01 22:18:16 +000098 */
Mark Slee5f8237d2006-10-26 04:57:03 +000099 public abstract function writeMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000100
Mark Slee6e536442006-06-30 18:28:50 +0000101 /**
102 * Writes a struct header.
103 *
Mark Slee6e536442006-06-30 18:28:50 +0000104 * @param string $name Struct name
105 * @throws TException on write error
106 * @return int How many bytes written
107 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000108 public abstract function writeStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000109
110 /**
111 * Close a struct.
112 *
Mark Slee6e536442006-06-30 18:28:50 +0000113 * @throws TException on write error
114 * @return int How many bytes written
115 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000116 public abstract function writeStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000117
118 /*
119 * Starts a field.
120 *
Mark Slee6e536442006-06-30 18:28:50 +0000121 * @param string $name Field name
122 * @param int $type Field type
123 * @param int $fid Field id
124 * @throws TException on write error
125 * @return int How many bytes written
126 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000127 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000128
Mark Slee5f8237d2006-10-26 04:57:03 +0000129 public abstract function writeFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000130
Mark Slee5f8237d2006-10-26 04:57:03 +0000131 public abstract function writeFieldStop();
Mark Slee6e536442006-06-30 18:28:50 +0000132
Mark Slee5f8237d2006-10-26 04:57:03 +0000133 public abstract function writeMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000134
Mark Slee5f8237d2006-10-26 04:57:03 +0000135 public abstract function writeMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000136
Mark Slee5f8237d2006-10-26 04:57:03 +0000137 public abstract function writeListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000138
Mark Slee5f8237d2006-10-26 04:57:03 +0000139 public abstract function writeListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000140
Mark Slee5f8237d2006-10-26 04:57:03 +0000141 public abstract function writeSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000142
Mark Slee5f8237d2006-10-26 04:57:03 +0000143 public abstract function writeSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000144
Mark Slee5f8237d2006-10-26 04:57:03 +0000145 public abstract function writeBool($bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000146
Mark Slee5f8237d2006-10-26 04:57:03 +0000147 public abstract function writeByte($byte);
Mark Slee6e536442006-06-30 18:28:50 +0000148
Mark Slee5f8237d2006-10-26 04:57:03 +0000149 public abstract function writeI16($i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000150
Mark Slee5f8237d2006-10-26 04:57:03 +0000151 public abstract function writeI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000152
Mark Slee5f8237d2006-10-26 04:57:03 +0000153 public abstract function writeI64($i64);
Mark Slee6e536442006-06-30 18:28:50 +0000154
Mark Slee5f8237d2006-10-26 04:57:03 +0000155 public abstract function writeDouble($dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000156
Mark Slee5f8237d2006-10-26 04:57:03 +0000157 public abstract function writeString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000158
Mark Sleecfc01932006-09-01 22:18:16 +0000159 /**
160 * Reads the message header
161 *
Mark Sleecfc01932006-09-01 22:18:16 +0000162 * @param string $name Function name
163 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
164 * @parem int $seqid The sequence id of this message
165 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000166 public abstract function readMessageBegin(&$name, &$type, &$seqid);
Marc Slemkod97eb612006-08-24 23:37:36 +0000167
Mark Sleecfc01932006-09-01 22:18:16 +0000168 /**
169 * Read the close of message
Mark Sleecfc01932006-09-01 22:18:16 +0000170 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000171 public abstract function readMessageEnd();
Marc Slemkod97eb612006-08-24 23:37:36 +0000172
Mark Slee5f8237d2006-10-26 04:57:03 +0000173 public abstract function readStructBegin(&$name);
Mark Slee6e536442006-06-30 18:28:50 +0000174
Mark Slee5f8237d2006-10-26 04:57:03 +0000175 public abstract function readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000176
Mark Slee5f8237d2006-10-26 04:57:03 +0000177 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
Mark Slee6e536442006-06-30 18:28:50 +0000178
Mark Slee5f8237d2006-10-26 04:57:03 +0000179 public abstract function readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000180
Mark Slee5f8237d2006-10-26 04:57:03 +0000181 public abstract function readMapBegin(&$keyType, &$valType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000182
Mark Slee5f8237d2006-10-26 04:57:03 +0000183 public abstract function readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000184
Mark Slee5f8237d2006-10-26 04:57:03 +0000185 public abstract function readListBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000186
Mark Slee5f8237d2006-10-26 04:57:03 +0000187 public abstract function readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000188
Mark Slee5f8237d2006-10-26 04:57:03 +0000189 public abstract function readSetBegin(&$elemType, &$size);
Mark Slee6e536442006-06-30 18:28:50 +0000190
Mark Slee5f8237d2006-10-26 04:57:03 +0000191 public abstract function readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000192
Mark Slee5f8237d2006-10-26 04:57:03 +0000193 public abstract function readBool(&$bool);
Mark Slee78f58e22006-09-02 04:17:07 +0000194
Mark Slee5f8237d2006-10-26 04:57:03 +0000195 public abstract function readByte(&$byte);
Mark Slee6e536442006-06-30 18:28:50 +0000196
Mark Slee5f8237d2006-10-26 04:57:03 +0000197 public abstract function readI16(&$i16);
Mark Sleecfc01932006-09-01 22:18:16 +0000198
Mark Slee5f8237d2006-10-26 04:57:03 +0000199 public abstract function readI32(&$i32);
Mark Slee6e536442006-06-30 18:28:50 +0000200
Mark Slee5f8237d2006-10-26 04:57:03 +0000201 public abstract function readI64(&$i64);
Mark Slee6e536442006-06-30 18:28:50 +0000202
Mark Slee5f8237d2006-10-26 04:57:03 +0000203 public abstract function readDouble(&$dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000204
Mark Slee5f8237d2006-10-26 04:57:03 +0000205 public abstract function readString(&$str);
Mark Slee6e536442006-06-30 18:28:50 +0000206
Mark Sleecfc01932006-09-01 22:18:16 +0000207 /**
208 * The skip function is a utility to parse over unrecognized date without
209 * causing corruption.
210 *
Mark Sleecfc01932006-09-01 22:18:16 +0000211 * @param TType $type What type is it
212 */
Mark Slee5f8237d2006-10-26 04:57:03 +0000213 public function skip($type) {
Mark Slee6e536442006-06-30 18:28:50 +0000214 switch ($type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000215 case TType::BOOL:
Mark Slee5f8237d2006-10-26 04:57:03 +0000216 return $this->readBool($bool);
Mark Slee6e536442006-06-30 18:28:50 +0000217 case TType::BYTE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000218 return $this->readByte($byte);
Adam Nichols2f816f22007-01-11 21:25:29 +0000219 case TType::I16:
Mark Slee5f8237d2006-10-26 04:57:03 +0000220 return $this->readI16($i16);
Mark Slee6e536442006-06-30 18:28:50 +0000221 case TType::I32:
Mark Slee5f8237d2006-10-26 04:57:03 +0000222 return $this->readI32($i32);
Mark Slee6e536442006-06-30 18:28:50 +0000223 case TType::I64:
Mark Slee5f8237d2006-10-26 04:57:03 +0000224 return $this->readI64($i64);
Mark Sleec98d0502006-09-06 02:42:25 +0000225 case TType::DOUBLE:
Mark Slee5f8237d2006-10-26 04:57:03 +0000226 return $this->readDouble($dub);
Mark Slee6e536442006-06-30 18:28:50 +0000227 case TType::STRING:
Mark Slee5f8237d2006-10-26 04:57:03 +0000228 return $this->readString($str);
Mark Slee6e536442006-06-30 18:28:50 +0000229 case TType::STRUCT:
230 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000231 $result = $this->readStructBegin($name);
Mark Slee6e536442006-06-30 18:28:50 +0000232 while (true) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000233 $result += $this->readFieldBegin($name, $ftype, $fid);
Mark Slee6e536442006-06-30 18:28:50 +0000234 if ($ftype == TType::STOP) {
235 break;
236 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000237 $result += $this->skip($ftype);
238 $result += $this->readFieldEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000239 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000240 $result += $this->readStructEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000241 return $result;
242 }
243 case TType::MAP:
244 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000245 $result = $this->readMapBegin($keyType, $valType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000246 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000247 $result += $this->skip($keyType);
248 $result += $this->skip($valType);
Mark Slee6e536442006-06-30 18:28:50 +0000249 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000250 $result += $this->readMapEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000251 return $result;
252 }
253 case TType::SET:
254 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000255 $result = $this->readSetBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000256 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000257 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000258 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000259 $result += $this->readSetEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000260 return $result;
261 }
262 case TType::LST:
263 {
Mark Slee5f8237d2006-10-26 04:57:03 +0000264 $result = $this->readListBegin($elemType, $size);
Mark Slee6e536442006-06-30 18:28:50 +0000265 for ($i = 0; $i < $size; $i++) {
Mark Slee5f8237d2006-10-26 04:57:03 +0000266 $result += $this->skip($elemType);
Mark Slee6e536442006-06-30 18:28:50 +0000267 }
Mark Slee5f8237d2006-10-26 04:57:03 +0000268 $result += $this->readListEnd();
Mark Slee6e536442006-06-30 18:28:50 +0000269 return $result;
270 }
271 default:
272 return 0;
273 }
274 }
Mark Slee99e2b262006-10-10 01:42:29 +0000275
276 /**
277 * Utility for skipping binary data
278 *
279 * @param TTransport $itrans TTransport object
280 * @param int $type Field type
281 */
282 public static function skipBinary($itrans, $type) {
283 switch ($type) {
284 case TType::BOOL:
285 return $itrans->readAll(1);
286 case TType::BYTE:
287 return $itrans->readAll(1);
Adam Nichols2f816f22007-01-11 21:25:29 +0000288 case TType::I16:
Mark Slee99e2b262006-10-10 01:42:29 +0000289 return $itrans->readAll(2);
290 case TType::I32:
291 return $itrans->readAll(4);
292 case TType::I64:
293 return $itrans->readAll(8);
294 case TType::DOUBLE:
295 return $itrans->readAll(8);
296 case TType::STRING:
297 $len = unpack('N', $itrans->readAll(4));
298 $len = $len[1];
299 if ($len > 0x7fffffff) {
300 $len = 0 - (($len - 1) ^ 0xffffffff);
301 }
302 return 4 + $itrans->readAll($len);
303 case TType::STRUCT:
304 {
305 $result = 0;
306 while (true) {
307 $ftype = 0;
308 $fid = 0;
Mark Slee5f8237d2006-10-26 04:57:03 +0000309 $data = $itrans->readAll(1);
Mark Slee99e2b262006-10-10 01:42:29 +0000310 $arr = unpack('c', $data);
311 $ftype = $arr[1];
312 if ($ftype == TType::STOP) {
313 break;
314 }
315 // I16 field id
316 $result += $itrans->readAll(2);
317 $result += self::skipBinary($itrans, $ftype);
318 }
319 return $result;
320 }
321 case TType::MAP:
322 {
323 // Ktype
324 $data = $itrans->readAll(1);
325 $arr = unpack('c', $data);
326 $ktype = $arr[1];
327 // Vtype
328 $data = $itrans->readAll(1);
329 $arr = unpack('c', $data);
330 $vtype = $arr[1];
331 // Size
332 $data = $itrans->readAll(4);
333 $arr = unpack('N', $data);
334 $size = $arr[1];
335 if ($size > 0x7fffffff) {
336 $size = 0 - (($size - 1) ^ 0xffffffff);
337 }
338 $result = 6;
339 for ($i = 0; $i < $size; $i++) {
340 $result += self::skipBinary($itrans, $ktype);
341 $result += self::skipBinary($itrans, $vtype);
342 }
343 return $result;
344 }
345 case TType::SET:
346 case TType::LST:
347 {
348 // Vtype
349 $data = $itrans->readAll(1);
350 $arr = unpack('c', $data);
351 $vtype = $arr[1];
352 // Size
353 $data = $itrans->readAll(4);
354 $arr = unpack('N', $data);
355 $size = $arr[1];
356 if ($size > 0x7fffffff) {
357 $size = 0 - (($size - 1) ^ 0xffffffff);
358 }
359 $result = 5;
360 for ($i = 0; $i < $size; $i++) {
361 $result += self::skipBinary($itrans, $vtype);
362 }
363 return $result;
364 }
365 default:
366 return 0;
367 }
368 }
Mark Slee6e536442006-06-30 18:28:50 +0000369}
370
Mark Slee5f8237d2006-10-26 04:57:03 +0000371/**
372 * Protocol factory creates protocol objects from transports
373 */
374interface TProtocolFactory {
375 /**
376 * Build input and output protocols from the given transports.
377 *
378 * @return array Two elements, (iprot, oprot)
379 */
380 public function getIOProtocols($itrans, $otrans);
381}
382
383
Mark Slee6e536442006-06-30 18:28:50 +0000384?>