blob: e9ff41a328e6e72fdb5b85906b5a0649be9fda96 [file] [log] [blame]
Gavin McDonald0b75e1a2010-10-28 02:12:01 +00001<?php
2/*
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 * @package thrift.protocol
21 */
22
23
24/**
25 * Protocol module. Contains all the types and definitions needed to implement
26 * a protocol encoder/decoder.
27 *
28 * @package thrift.protocol
29 */
30
31/**
32 * Protocol exceptions
33 */
34class TProtocolException extends TException {
35 const UNKNOWN = 0;
36 const INVALID_DATA = 1;
37 const NEGATIVE_SIZE = 2;
38 const SIZE_LIMIT = 3;
39 const BAD_VERSION = 4;
40
41 function __construct($message=null, $code=0) {
42 parent::__construct($message, $code);
43 }
44}
45
46/**
47 * Protocol base class module.
48 */
49abstract class TProtocol {
50 // The below may seem silly, but it is to get around the problem that the
51 // "instanceof" operator can only take in a T_VARIABLE and not a T_STRING
52 // or T_CONSTANT_ENCAPSED_STRING. Using "is_a()" instead of "instanceof" is
53 // a workaround but is deprecated in PHP5. This is used in the generated
54 // deserialization code.
55 static $TBINARYPROTOCOLACCELERATED = 'TBinaryProtocolAccelerated';
56
57 /**
58 * Underlying transport
59 *
60 * @var TTransport
61 */
62 protected $trans_;
63
64 /**
65 * Constructor
66 */
67 protected function __construct($trans) {
68 $this->trans_ = $trans;
69 }
70
71 /**
72 * Accessor for transport
73 *
74 * @return TTransport
75 */
76 public function getTransport() {
77 return $this->trans_;
78 }
79
80 /**
81 * Writes the message header
82 *
83 * @param string $name Function name
84 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
85 * @param int $seqid The sequence id of this message
86 */
87 public abstract function writeMessageBegin($name, $type, $seqid);
88
89 /**
90 * Close the message
91 */
92 public abstract function writeMessageEnd();
93
94 /**
95 * Writes a struct header.
96 *
97 * @param string $name Struct name
98 * @throws TException on write error
99 * @return int How many bytes written
100 */
101 public abstract function writeStructBegin($name);
102
103 /**
104 * Close a struct.
105 *
106 * @throws TException on write error
107 * @return int How many bytes written
108 */
109 public abstract function writeStructEnd();
110
111 /*
112 * Starts a field.
113 *
114 * @param string $name Field name
115 * @param int $type Field type
116 * @param int $fid Field id
117 * @throws TException on write error
118 * @return int How many bytes written
119 */
120 public abstract function writeFieldBegin($fieldName, $fieldType, $fieldId);
121
122 public abstract function writeFieldEnd();
123
124 public abstract function writeFieldStop();
125
126 public abstract function writeMapBegin($keyType, $valType, $size);
127
128 public abstract function writeMapEnd();
129
130 public abstract function writeListBegin($elemType, $size);
131
132 public abstract function writeListEnd();
133
134 public abstract function writeSetBegin($elemType, $size);
135
136 public abstract function writeSetEnd();
137
138 public abstract function writeBool($bool);
139
140 public abstract function writeByte($byte);
141
142 public abstract function writeI16($i16);
143
144 public abstract function writeI32($i32);
145
146 public abstract function writeI64($i64);
147
148 public abstract function writeDouble($dub);
149
150 public abstract function writeString($str);
151
152 /**
153 * Reads the message header
154 *
155 * @param string $name Function name
156 * @param int $type message type TMessageType::CALL or TMessageType::REPLY
157 * @parem int $seqid The sequence id of this message
158 */
159 public abstract function readMessageBegin(&$name, &$type, &$seqid);
160
161 /**
162 * Read the close of message
163 */
164 public abstract function readMessageEnd();
165
166 public abstract function readStructBegin(&$name);
167
168 public abstract function readStructEnd();
169
170 public abstract function readFieldBegin(&$name, &$fieldType, &$fieldId);
171
172 public abstract function readFieldEnd();
173
174 public abstract function readMapBegin(&$keyType, &$valType, &$size);
175
176 public abstract function readMapEnd();
177
178 public abstract function readListBegin(&$elemType, &$size);
179
180 public abstract function readListEnd();
181
182 public abstract function readSetBegin(&$elemType, &$size);
183
184 public abstract function readSetEnd();
185
186 public abstract function readBool(&$bool);
187
188 public abstract function readByte(&$byte);
189
190 public abstract function readI16(&$i16);
191
192 public abstract function readI32(&$i32);
193
194 public abstract function readI64(&$i64);
195
196 public abstract function readDouble(&$dub);
197
198 public abstract function readString(&$str);
199
200 /**
201 * The skip function is a utility to parse over unrecognized date without
202 * causing corruption.
203 *
204 * @param TType $type What type is it
205 */
206 public function skip($type) {
207 switch ($type) {
208 case TType::BOOL:
209 return $this->readBool($bool);
210 case TType::BYTE:
211 return $this->readByte($byte);
212 case TType::I16:
213 return $this->readI16($i16);
214 case TType::I32:
215 return $this->readI32($i32);
216 case TType::I64:
217 return $this->readI64($i64);
218 case TType::DOUBLE:
219 return $this->readDouble($dub);
220 case TType::STRING:
221 return $this->readString($str);
222 case TType::STRUCT:
223 {
224 $result = $this->readStructBegin($name);
225 while (true) {
226 $result += $this->readFieldBegin($name, $ftype, $fid);
227 if ($ftype == TType::STOP) {
228 break;
229 }
230 $result += $this->skip($ftype);
231 $result += $this->readFieldEnd();
232 }
233 $result += $this->readStructEnd();
234 return $result;
235 }
236 case TType::MAP:
237 {
238 $result = $this->readMapBegin($keyType, $valType, $size);
239 for ($i = 0; $i < $size; $i++) {
240 $result += $this->skip($keyType);
241 $result += $this->skip($valType);
242 }
243 $result += $this->readMapEnd();
244 return $result;
245 }
246 case TType::SET:
247 {
248 $result = $this->readSetBegin($elemType, $size);
249 for ($i = 0; $i < $size; $i++) {
250 $result += $this->skip($elemType);
251 }
252 $result += $this->readSetEnd();
253 return $result;
254 }
255 case TType::LST:
256 {
257 $result = $this->readListBegin($elemType, $size);
258 for ($i = 0; $i < $size; $i++) {
259 $result += $this->skip($elemType);
260 }
261 $result += $this->readListEnd();
262 return $result;
263 }
264 default:
265 return 0;
266 }
267 }
268
269 /**
270 * Utility for skipping binary data
271 *
272 * @param TTransport $itrans TTransport object
273 * @param int $type Field type
274 */
275 public static function skipBinary($itrans, $type) {
276 switch ($type) {
277 case TType::BOOL:
278 return $itrans->readAll(1);
279 case TType::BYTE:
280 return $itrans->readAll(1);
281 case TType::I16:
282 return $itrans->readAll(2);
283 case TType::I32:
284 return $itrans->readAll(4);
285 case TType::I64:
286 return $itrans->readAll(8);
287 case TType::DOUBLE:
288 return $itrans->readAll(8);
289 case TType::STRING:
290 $len = unpack('N', $itrans->readAll(4));
291 $len = $len[1];
292 if ($len > 0x7fffffff) {
293 $len = 0 - (($len - 1) ^ 0xffffffff);
294 }
295 return 4 + $itrans->readAll($len);
296 case TType::STRUCT:
297 {
298 $result = 0;
299 while (true) {
300 $ftype = 0;
301 $fid = 0;
302 $data = $itrans->readAll(1);
303 $arr = unpack('c', $data);
304 $ftype = $arr[1];
305 if ($ftype == TType::STOP) {
306 break;
307 }
308 // I16 field id
309 $result += $itrans->readAll(2);
310 $result += self::skipBinary($itrans, $ftype);
311 }
312 return $result;
313 }
314 case TType::MAP:
315 {
316 // Ktype
317 $data = $itrans->readAll(1);
318 $arr = unpack('c', $data);
319 $ktype = $arr[1];
320 // Vtype
321 $data = $itrans->readAll(1);
322 $arr = unpack('c', $data);
323 $vtype = $arr[1];
324 // Size
325 $data = $itrans->readAll(4);
326 $arr = unpack('N', $data);
327 $size = $arr[1];
328 if ($size > 0x7fffffff) {
329 $size = 0 - (($size - 1) ^ 0xffffffff);
330 }
331 $result = 6;
332 for ($i = 0; $i < $size; $i++) {
333 $result += self::skipBinary($itrans, $ktype);
334 $result += self::skipBinary($itrans, $vtype);
335 }
336 return $result;
337 }
338 case TType::SET:
339 case TType::LST:
340 {
341 // Vtype
342 $data = $itrans->readAll(1);
343 $arr = unpack('c', $data);
344 $vtype = $arr[1];
345 // Size
346 $data = $itrans->readAll(4);
347 $arr = unpack('N', $data);
348 $size = $arr[1];
349 if ($size > 0x7fffffff) {
350 $size = 0 - (($size - 1) ^ 0xffffffff);
351 }
352 $result = 5;
353 for ($i = 0; $i < $size; $i++) {
354 $result += self::skipBinary($itrans, $vtype);
355 }
356 return $result;
357 }
358 default:
359 return 0;
360 }
361 }
362}
363
364/**
365 * Protocol factory creates protocol objects from transports
366 */
367interface TProtocolFactory {
368 /**
369 * Build a protocol from the base transport
370 *
371 * @return TProtcol protocol
372 */
373 public function getProtocol($trans);
374}
375
376
377?>