blob: 02b41710599065f3a73b7169e36825572c39ea74 [file] [log] [blame]
Mark Slee7eb0d632007-03-01 00:00:27 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Mark Slee83c52a82006-06-07 06:51:18 +00007package com.facebook.thrift.protocol;
8
9import com.facebook.thrift.TException;
10import com.facebook.thrift.transport.TTransport;
Mark Slee6eb58922007-11-07 00:48:47 +000011import java.io.UnsupportedEncodingException;
Mark Slee83c52a82006-06-07 06:51:18 +000012
13/**
14 * Binary protocol implementation for thrift.
15 *
16 * @author Mark Slee <mcslee@facebook.com>
17 */
Mark Slee456b7a82006-10-25 20:53:37 +000018public class TBinaryProtocol extends TProtocol {
Mark Slee78f58e22006-09-02 04:17:07 +000019
Mark Slee808454e2007-06-20 21:51:57 +000020 protected static final int VERSION_MASK = 0xffff0000;
21 protected static final int VERSION_1 = 0x80010000;
22
23 protected boolean strictRead_ = false;
24 protected boolean strictWrite_ = true;
25
Mark Slee456b7a82006-10-25 20:53:37 +000026 /**
27 * Factory
28 */
29 public static class Factory implements TProtocolFactory {
Mark Slee808454e2007-06-20 21:51:57 +000030 protected boolean strictRead_ = false;
31 protected boolean strictWrite_ = true;
Mark Slee6eb58922007-11-07 00:48:47 +000032
Mark Slee808454e2007-06-20 21:51:57 +000033 public Factory() {
34 this(false, false);
35 }
36
37 public Factory(boolean strictRead, boolean strictWrite) {
38 strictRead_ = strictRead;
39 strictWrite_ = strictWrite;
40 }
41
Aditya Agarwal5a429582007-02-06 02:51:15 +000042 public TProtocol getProtocol(TTransport trans) {
Mark Slee808454e2007-06-20 21:51:57 +000043 return new TBinaryProtocol(trans, strictRead_, strictWrite_);
Mark Slee456b7a82006-10-25 20:53:37 +000044 }
Mark Slee78f58e22006-09-02 04:17:07 +000045 }
46
Mark Slee456b7a82006-10-25 20:53:37 +000047 /**
48 * Constructor
49 */
Aditya Agarwal5a429582007-02-06 02:51:15 +000050 public TBinaryProtocol(TTransport trans) {
Mark Slee808454e2007-06-20 21:51:57 +000051 this(trans, false, false);
Mark Slee83c52a82006-06-07 06:51:18 +000052 }
53
Mark Slee808454e2007-06-20 21:51:57 +000054 public TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite) {
55 super(trans);
56 strictRead_ = strictRead;
57 strictWrite_ = strictWrite;
58 }
59
60
Mark Slee456b7a82006-10-25 20:53:37 +000061 public void writeMessageBegin(TMessage message) throws TException {
Mark Slee808454e2007-06-20 21:51:57 +000062 if (strictWrite_) {
63 int version = VERSION_1 | message.type;
64 writeI32(version);
65 writeString(message.name);
66 writeI32(message.seqid);
67 } else {
68 writeString(message.name);
69 writeByte(message.type);
70 writeI32(message.seqid);
71 }
Mark Slee83c52a82006-06-07 06:51:18 +000072 }
73
Mark Slee456b7a82006-10-25 20:53:37 +000074 public void writeMessageEnd() {}
75
76 public void writeStructBegin(TStruct struct) {}
77
78 public void writeStructEnd() {}
79
80 public void writeFieldBegin(TField field) throws TException {
81 writeByte(field.type);
82 writeI16(field.id);
Mark Slee83c52a82006-06-07 06:51:18 +000083 }
84
Mark Slee456b7a82006-10-25 20:53:37 +000085 public void writeFieldEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +000086
Mark Slee456b7a82006-10-25 20:53:37 +000087 public void writeFieldStop() throws TException {
88 writeByte(TType.STOP);
Mark Slee83c52a82006-06-07 06:51:18 +000089 }
90
Mark Slee456b7a82006-10-25 20:53:37 +000091 public void writeMapBegin(TMap map) throws TException {
92 writeByte(map.keyType);
93 writeByte(map.valueType);
94 writeI32(map.size);
Mark Slee83c52a82006-06-07 06:51:18 +000095 }
96
Mark Slee456b7a82006-10-25 20:53:37 +000097 public void writeMapEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +000098
Mark Slee456b7a82006-10-25 20:53:37 +000099 public void writeListBegin(TList list) throws TException {
100 writeByte(list.elemType);
101 writeI32(list.size);
Mark Slee78f58e22006-09-02 04:17:07 +0000102 }
103
Mark Slee456b7a82006-10-25 20:53:37 +0000104 public void writeListEnd() {}
105
106 public void writeSetBegin(TSet set) throws TException {
107 writeByte(set.elemType);
108 writeI32(set.size);
109 }
110
111 public void writeSetEnd() {}
112
113 public void writeBool(boolean b) throws TException {
114 writeByte(b ? (byte)1 : (byte)0);
115 }
116
117 private byte [] bout = new byte[1];
118 public void writeByte(byte b) throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000119 bout[0] = b;
Aditya Agarwal5a429582007-02-06 02:51:15 +0000120 trans_.write(bout, 0, 1);
Mark Slee83c52a82006-06-07 06:51:18 +0000121 }
122
Mark Slee456b7a82006-10-25 20:53:37 +0000123 private byte[] i16out = new byte[2];
124 public void writeI16(short i16) throws TException {
Mark Slee78f58e22006-09-02 04:17:07 +0000125 i16out[0] = (byte)(0xff & (i16 >> 8));
126 i16out[1] = (byte)(0xff & (i16));
Aditya Agarwal5a429582007-02-06 02:51:15 +0000127 trans_.write(i16out, 0, 2);
Mark Slee83c52a82006-06-07 06:51:18 +0000128 }
129
Mark Slee456b7a82006-10-25 20:53:37 +0000130 private byte[] i32out = new byte[4];
131 public void writeI32(int i32) throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000132 i32out[0] = (byte)(0xff & (i32 >> 24));
133 i32out[1] = (byte)(0xff & (i32 >> 16));
134 i32out[2] = (byte)(0xff & (i32 >> 8));
135 i32out[3] = (byte)(0xff & (i32));
Aditya Agarwal5a429582007-02-06 02:51:15 +0000136 trans_.write(i32out, 0, 4);
Mark Slee83c52a82006-06-07 06:51:18 +0000137 }
138
Mark Slee456b7a82006-10-25 20:53:37 +0000139 private byte[] i64out = new byte[8];
140 public void writeI64(long i64) throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000141 i64out[0] = (byte)(0xff & (i64 >> 56));
142 i64out[1] = (byte)(0xff & (i64 >> 48));
143 i64out[2] = (byte)(0xff & (i64 >> 40));
144 i64out[3] = (byte)(0xff & (i64 >> 32));
145 i64out[4] = (byte)(0xff & (i64 >> 24));
146 i64out[5] = (byte)(0xff & (i64 >> 16));
147 i64out[6] = (byte)(0xff & (i64 >> 8));
148 i64out[7] = (byte)(0xff & (i64));
Aditya Agarwal5a429582007-02-06 02:51:15 +0000149 trans_.write(i64out, 0, 8);
Mark Slee83c52a82006-06-07 06:51:18 +0000150 }
151
Mark Slee456b7a82006-10-25 20:53:37 +0000152 public void writeDouble(double dub) throws TException {
153 writeI64(Double.doubleToLongBits(dub));
Mark Sleec98d0502006-09-06 02:42:25 +0000154 }
155
Mark Slee456b7a82006-10-25 20:53:37 +0000156 public void writeString(String str) throws TException {
Mark Slee6eb58922007-11-07 00:48:47 +0000157 try {
158 byte[] dat = str.getBytes("UTF-8");
159 writeI32(dat.length);
160 trans_.write(dat, 0, dat.length);
161 } catch (UnsupportedEncodingException uex) {
162 throw new TException("JVM DOES NOT SUPPORT UTF-8");
163 }
Mark Slee83c52a82006-06-07 06:51:18 +0000164 }
165
Mark Slee8d725a22007-04-13 01:57:12 +0000166 public void writeBinary(byte[] bin) throws TException {
167 writeI32(bin.length);
168 trans_.write(bin, 0, bin.length);
169 }
170
Mark Slee83c52a82006-06-07 06:51:18 +0000171 /**
172 * Reading methods.
173 */
174
Mark Slee456b7a82006-10-25 20:53:37 +0000175 public TMessage readMessageBegin() throws TException {
Mark Slee78f58e22006-09-02 04:17:07 +0000176 TMessage message = new TMessage();
Mark Slee808454e2007-06-20 21:51:57 +0000177
178 int size = readI32();
179 if (size < 0) {
180 int version = size & VERSION_MASK;
181 if (version != VERSION_1) {
182 throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in readMessageBegin");
183 }
184 message.type = (byte)(version & 0x000000ff);
185 message.name = readString();
186 message.seqid = readI32();
187 } else {
188 if (strictRead_) {
189 throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
190 }
191 message.name = readStringBody(size);
192 message.type = readByte();
193 message.seqid = readI32();
194 }
Mark Slee78f58e22006-09-02 04:17:07 +0000195 return message;
196 }
197
Mark Slee456b7a82006-10-25 20:53:37 +0000198 public void readMessageEnd() {}
Mark Slee78f58e22006-09-02 04:17:07 +0000199
Mark Slee456b7a82006-10-25 20:53:37 +0000200 public TStruct readStructBegin() {
Mark Slee530fd662006-08-09 00:05:18 +0000201 return new TStruct();
Mark Slee83c52a82006-06-07 06:51:18 +0000202 }
203
Mark Slee456b7a82006-10-25 20:53:37 +0000204 public void readStructEnd() {}
Mark Slee83c52a82006-06-07 06:51:18 +0000205
Mark Slee456b7a82006-10-25 20:53:37 +0000206 public TField readFieldBegin() throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000207 TField field = new TField();
Mark Slee456b7a82006-10-25 20:53:37 +0000208 field.type = readByte();
Mark Slee530fd662006-08-09 00:05:18 +0000209 if (field.type != TType.STOP) {
Mark Slee456b7a82006-10-25 20:53:37 +0000210 field.id = readI16();
Mark Slee83c52a82006-06-07 06:51:18 +0000211 }
Mark Slee530fd662006-08-09 00:05:18 +0000212 return field;
Mark Slee83c52a82006-06-07 06:51:18 +0000213 }
Mark Slee6eb58922007-11-07 00:48:47 +0000214
Mark Slee456b7a82006-10-25 20:53:37 +0000215 public void readFieldEnd() {}
Mark Slee6eb58922007-11-07 00:48:47 +0000216
Mark Slee456b7a82006-10-25 20:53:37 +0000217 public TMap readMapBegin() throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000218 TMap map = new TMap();
Mark Slee456b7a82006-10-25 20:53:37 +0000219 map.keyType = readByte();
220 map.valueType = readByte();
221 map.size = readI32();
Mark Slee530fd662006-08-09 00:05:18 +0000222 return map;
Mark Slee83c52a82006-06-07 06:51:18 +0000223 }
224
Mark Slee456b7a82006-10-25 20:53:37 +0000225 public void readMapEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +0000226
Mark Slee456b7a82006-10-25 20:53:37 +0000227 public TList readListBegin() throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000228 TList list = new TList();
Mark Slee456b7a82006-10-25 20:53:37 +0000229 list.elemType = readByte();
230 list.size = readI32();
Mark Slee530fd662006-08-09 00:05:18 +0000231 return list;
Mark Slee83c52a82006-06-07 06:51:18 +0000232 }
233
Mark Slee456b7a82006-10-25 20:53:37 +0000234 public void readListEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +0000235
Mark Slee456b7a82006-10-25 20:53:37 +0000236 public TSet readSetBegin() throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000237 TSet set = new TSet();
Mark Slee456b7a82006-10-25 20:53:37 +0000238 set.elemType = readByte();
239 set.size = readI32();
Mark Slee530fd662006-08-09 00:05:18 +0000240 return set;
Mark Slee83c52a82006-06-07 06:51:18 +0000241 }
242
Mark Slee456b7a82006-10-25 20:53:37 +0000243 public void readSetEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +0000244
Mark Slee456b7a82006-10-25 20:53:37 +0000245 public boolean readBool() throws TException {
246 return (readByte() == 1);
Mark Slee78f58e22006-09-02 04:17:07 +0000247 }
248
Mark Slee456b7a82006-10-25 20:53:37 +0000249 private byte[] bin = new byte[1];
250 public byte readByte() throws TException {
Aditya Agarwal5a429582007-02-06 02:51:15 +0000251 trans_.readAll(bin, 0, 1);
Mark Slee530fd662006-08-09 00:05:18 +0000252 return bin[0];
Mark Slee83c52a82006-06-07 06:51:18 +0000253 }
254
Mark Slee456b7a82006-10-25 20:53:37 +0000255 private byte[] i16rd = new byte[2];
256 public short readI16() throws TException {
Aditya Agarwal5a429582007-02-06 02:51:15 +0000257 trans_.readAll(i16rd, 0, 2);
Mark Slee78f58e22006-09-02 04:17:07 +0000258 return
259 (short)
260 (((i16rd[0] & 0xff) << 8) |
261 ((i16rd[1] & 0xff)));
Mark Slee83c52a82006-06-07 06:51:18 +0000262 }
263
Mark Slee456b7a82006-10-25 20:53:37 +0000264 private byte[] i32rd = new byte[4];
265 public int readI32() throws TException {
Aditya Agarwal5a429582007-02-06 02:51:15 +0000266 trans_.readAll(i32rd, 0, 4);
Mark Slee530fd662006-08-09 00:05:18 +0000267 return
268 ((i32rd[0] & 0xff) << 24) |
269 ((i32rd[1] & 0xff) << 16) |
270 ((i32rd[2] & 0xff) << 8) |
271 ((i32rd[3] & 0xff));
Mark Slee83c52a82006-06-07 06:51:18 +0000272 }
Mark Slee6eb58922007-11-07 00:48:47 +0000273
Mark Slee456b7a82006-10-25 20:53:37 +0000274 private byte[] i64rd = new byte[8];
275 public long readI64() throws TException {
Aditya Agarwal5a429582007-02-06 02:51:15 +0000276 trans_.readAll(i64rd, 0, 8);
Mark Slee530fd662006-08-09 00:05:18 +0000277 return
278 ((long)(i64rd[0] & 0xff) << 56) |
279 ((long)(i64rd[1] & 0xff) << 48) |
280 ((long)(i64rd[2] & 0xff) << 40) |
281 ((long)(i64rd[3] & 0xff) << 32) |
282 ((long)(i64rd[4] & 0xff) << 24) |
283 ((long)(i64rd[5] & 0xff) << 16) |
284 ((long)(i64rd[6] & 0xff) << 8) |
285 ((long)(i64rd[7] & 0xff));
Mark Slee83c52a82006-06-07 06:51:18 +0000286 }
287
Mark Slee456b7a82006-10-25 20:53:37 +0000288 public double readDouble() throws TException {
289 return Double.longBitsToDouble(readI64());
Mark Sleec98d0502006-09-06 02:42:25 +0000290 }
291
Mark Slee456b7a82006-10-25 20:53:37 +0000292 public String readString() throws TException {
293 int size = readI32();
Mark Slee808454e2007-06-20 21:51:57 +0000294 return readStringBody(size);
295 }
296
297 public String readStringBody(int size) throws TException {
Mark Slee6eb58922007-11-07 00:48:47 +0000298 try {
299 byte[] buf = new byte[size];
300 trans_.readAll(buf, 0, size);
301 return new String(buf, "UTF-8");
302 } catch (UnsupportedEncodingException uex) {
303 throw new TException("JVM DOES NOT SUPPORT UTF-8");
304 }
Mark Slee83c52a82006-06-07 06:51:18 +0000305 }
Mark Slee8d725a22007-04-13 01:57:12 +0000306
307 public byte[] readBinary() throws TException {
308 int size = readI32();
309 byte[] buf = new byte[size];
310 trans_.readAll(buf, 0, size);
311 return buf;
312 }
313
Mark Slee83c52a82006-06-07 06:51:18 +0000314}