blob: 7dff48586ecf54ef0def5f751ad437a6ba813f6b [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 Slee83c52a82006-06-07 06:51:18 +000011
12/**
13 * Binary protocol implementation for thrift.
14 *
15 * @author Mark Slee <mcslee@facebook.com>
16 */
Mark Slee456b7a82006-10-25 20:53:37 +000017public class TBinaryProtocol extends TProtocol {
Mark Slee78f58e22006-09-02 04:17:07 +000018
Mark Slee808454e2007-06-20 21:51:57 +000019 protected static final int VERSION_MASK = 0xffff0000;
20 protected static final int VERSION_1 = 0x80010000;
21
22 protected boolean strictRead_ = false;
23 protected boolean strictWrite_ = true;
24
Mark Slee456b7a82006-10-25 20:53:37 +000025 /**
26 * Factory
27 */
28 public static class Factory implements TProtocolFactory {
Mark Slee808454e2007-06-20 21:51:57 +000029 protected boolean strictRead_ = false;
30 protected boolean strictWrite_ = true;
31
32 public Factory() {
33 this(false, false);
34 }
35
36 public Factory(boolean strictRead, boolean strictWrite) {
37 strictRead_ = strictRead;
38 strictWrite_ = strictWrite;
39 }
40
Aditya Agarwal5a429582007-02-06 02:51:15 +000041 public TProtocol getProtocol(TTransport trans) {
Mark Slee808454e2007-06-20 21:51:57 +000042 return new TBinaryProtocol(trans, strictRead_, strictWrite_);
Mark Slee456b7a82006-10-25 20:53:37 +000043 }
Mark Slee78f58e22006-09-02 04:17:07 +000044 }
45
Mark Slee456b7a82006-10-25 20:53:37 +000046 /**
47 * Constructor
48 */
Aditya Agarwal5a429582007-02-06 02:51:15 +000049 public TBinaryProtocol(TTransport trans) {
Mark Slee808454e2007-06-20 21:51:57 +000050 this(trans, false, false);
Mark Slee83c52a82006-06-07 06:51:18 +000051 }
52
Mark Slee808454e2007-06-20 21:51:57 +000053 public TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite) {
54 super(trans);
55 strictRead_ = strictRead;
56 strictWrite_ = strictWrite;
57 }
58
59
Mark Slee456b7a82006-10-25 20:53:37 +000060 public void writeMessageBegin(TMessage message) throws TException {
Mark Slee808454e2007-06-20 21:51:57 +000061 if (strictWrite_) {
62 int version = VERSION_1 | message.type;
63 writeI32(version);
64 writeString(message.name);
65 writeI32(message.seqid);
66 } else {
67 writeString(message.name);
68 writeByte(message.type);
69 writeI32(message.seqid);
70 }
Mark Slee83c52a82006-06-07 06:51:18 +000071 }
72
Mark Slee456b7a82006-10-25 20:53:37 +000073 public void writeMessageEnd() {}
74
75 public void writeStructBegin(TStruct struct) {}
76
77 public void writeStructEnd() {}
78
79 public void writeFieldBegin(TField field) throws TException {
80 writeByte(field.type);
81 writeI16(field.id);
Mark Slee83c52a82006-06-07 06:51:18 +000082 }
83
Mark Slee456b7a82006-10-25 20:53:37 +000084 public void writeFieldEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +000085
Mark Slee456b7a82006-10-25 20:53:37 +000086 public void writeFieldStop() throws TException {
87 writeByte(TType.STOP);
Mark Slee83c52a82006-06-07 06:51:18 +000088 }
89
Mark Slee456b7a82006-10-25 20:53:37 +000090 public void writeMapBegin(TMap map) throws TException {
91 writeByte(map.keyType);
92 writeByte(map.valueType);
93 writeI32(map.size);
Mark Slee83c52a82006-06-07 06:51:18 +000094 }
95
Mark Slee456b7a82006-10-25 20:53:37 +000096 public void writeMapEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +000097
Mark Slee456b7a82006-10-25 20:53:37 +000098 public void writeListBegin(TList list) throws TException {
99 writeByte(list.elemType);
100 writeI32(list.size);
Mark Slee78f58e22006-09-02 04:17:07 +0000101 }
102
Mark Slee456b7a82006-10-25 20:53:37 +0000103 public void writeListEnd() {}
104
105 public void writeSetBegin(TSet set) throws TException {
106 writeByte(set.elemType);
107 writeI32(set.size);
108 }
109
110 public void writeSetEnd() {}
111
112 public void writeBool(boolean b) throws TException {
113 writeByte(b ? (byte)1 : (byte)0);
114 }
115
116 private byte [] bout = new byte[1];
117 public void writeByte(byte b) throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000118 bout[0] = b;
Aditya Agarwal5a429582007-02-06 02:51:15 +0000119 trans_.write(bout, 0, 1);
Mark Slee83c52a82006-06-07 06:51:18 +0000120 }
121
Mark Slee456b7a82006-10-25 20:53:37 +0000122 private byte[] i16out = new byte[2];
123 public void writeI16(short i16) throws TException {
Mark Slee78f58e22006-09-02 04:17:07 +0000124 i16out[0] = (byte)(0xff & (i16 >> 8));
125 i16out[1] = (byte)(0xff & (i16));
Aditya Agarwal5a429582007-02-06 02:51:15 +0000126 trans_.write(i16out, 0, 2);
Mark Slee83c52a82006-06-07 06:51:18 +0000127 }
128
Mark Slee456b7a82006-10-25 20:53:37 +0000129 private byte[] i32out = new byte[4];
130 public void writeI32(int i32) throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000131 i32out[0] = (byte)(0xff & (i32 >> 24));
132 i32out[1] = (byte)(0xff & (i32 >> 16));
133 i32out[2] = (byte)(0xff & (i32 >> 8));
134 i32out[3] = (byte)(0xff & (i32));
Aditya Agarwal5a429582007-02-06 02:51:15 +0000135 trans_.write(i32out, 0, 4);
Mark Slee83c52a82006-06-07 06:51:18 +0000136 }
137
Mark Slee456b7a82006-10-25 20:53:37 +0000138 private byte[] i64out = new byte[8];
139 public void writeI64(long i64) throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000140 i64out[0] = (byte)(0xff & (i64 >> 56));
141 i64out[1] = (byte)(0xff & (i64 >> 48));
142 i64out[2] = (byte)(0xff & (i64 >> 40));
143 i64out[3] = (byte)(0xff & (i64 >> 32));
144 i64out[4] = (byte)(0xff & (i64 >> 24));
145 i64out[5] = (byte)(0xff & (i64 >> 16));
146 i64out[6] = (byte)(0xff & (i64 >> 8));
147 i64out[7] = (byte)(0xff & (i64));
Aditya Agarwal5a429582007-02-06 02:51:15 +0000148 trans_.write(i64out, 0, 8);
Mark Slee83c52a82006-06-07 06:51:18 +0000149 }
150
Mark Slee456b7a82006-10-25 20:53:37 +0000151 public void writeDouble(double dub) throws TException {
152 writeI64(Double.doubleToLongBits(dub));
Mark Sleec98d0502006-09-06 02:42:25 +0000153 }
154
Mark Slee456b7a82006-10-25 20:53:37 +0000155 public void writeString(String str) throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000156 byte[] dat = str.getBytes();
Mark Slee456b7a82006-10-25 20:53:37 +0000157 writeI32(dat.length);
Aditya Agarwal5a429582007-02-06 02:51:15 +0000158 trans_.write(dat, 0, dat.length);
Mark Slee83c52a82006-06-07 06:51:18 +0000159 }
160
Mark Slee8d725a22007-04-13 01:57:12 +0000161 public void writeBinary(byte[] bin) throws TException {
162 writeI32(bin.length);
163 trans_.write(bin, 0, bin.length);
164 }
165
Mark Slee83c52a82006-06-07 06:51:18 +0000166 /**
167 * Reading methods.
168 */
169
Mark Slee456b7a82006-10-25 20:53:37 +0000170 public TMessage readMessageBegin() throws TException {
Mark Slee78f58e22006-09-02 04:17:07 +0000171 TMessage message = new TMessage();
Mark Slee808454e2007-06-20 21:51:57 +0000172
173 int size = readI32();
174 if (size < 0) {
175 int version = size & VERSION_MASK;
176 if (version != VERSION_1) {
177 throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in readMessageBegin");
178 }
179 message.type = (byte)(version & 0x000000ff);
180 message.name = readString();
181 message.seqid = readI32();
182 } else {
183 if (strictRead_) {
184 throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
185 }
186 message.name = readStringBody(size);
187 message.type = readByte();
188 message.seqid = readI32();
189 }
Mark Slee78f58e22006-09-02 04:17:07 +0000190 return message;
191 }
192
Mark Slee456b7a82006-10-25 20:53:37 +0000193 public void readMessageEnd() {}
Mark Slee78f58e22006-09-02 04:17:07 +0000194
Mark Slee456b7a82006-10-25 20:53:37 +0000195 public TStruct readStructBegin() {
Mark Slee530fd662006-08-09 00:05:18 +0000196 return new TStruct();
Mark Slee83c52a82006-06-07 06:51:18 +0000197 }
198
Mark Slee456b7a82006-10-25 20:53:37 +0000199 public void readStructEnd() {}
Mark Slee83c52a82006-06-07 06:51:18 +0000200
Mark Slee456b7a82006-10-25 20:53:37 +0000201 public TField readFieldBegin() throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000202 TField field = new TField();
Mark Slee456b7a82006-10-25 20:53:37 +0000203 field.type = readByte();
Mark Slee530fd662006-08-09 00:05:18 +0000204 if (field.type != TType.STOP) {
Mark Slee456b7a82006-10-25 20:53:37 +0000205 field.id = readI16();
Mark Slee83c52a82006-06-07 06:51:18 +0000206 }
Mark Slee530fd662006-08-09 00:05:18 +0000207 return field;
Mark Slee83c52a82006-06-07 06:51:18 +0000208 }
209
Mark Slee456b7a82006-10-25 20:53:37 +0000210 public void readFieldEnd() {}
Mark Slee83c52a82006-06-07 06:51:18 +0000211
Mark Slee456b7a82006-10-25 20:53:37 +0000212 public TMap readMapBegin() throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000213 TMap map = new TMap();
Mark Slee456b7a82006-10-25 20:53:37 +0000214 map.keyType = readByte();
215 map.valueType = readByte();
216 map.size = readI32();
Mark Slee530fd662006-08-09 00:05:18 +0000217 return map;
Mark Slee83c52a82006-06-07 06:51:18 +0000218 }
219
Mark Slee456b7a82006-10-25 20:53:37 +0000220 public void readMapEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +0000221
Mark Slee456b7a82006-10-25 20:53:37 +0000222 public TList readListBegin() throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000223 TList list = new TList();
Mark Slee456b7a82006-10-25 20:53:37 +0000224 list.elemType = readByte();
225 list.size = readI32();
Mark Slee530fd662006-08-09 00:05:18 +0000226 return list;
Mark Slee83c52a82006-06-07 06:51:18 +0000227 }
228
Mark Slee456b7a82006-10-25 20:53:37 +0000229 public void readListEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +0000230
Mark Slee456b7a82006-10-25 20:53:37 +0000231 public TSet readSetBegin() throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000232 TSet set = new TSet();
Mark Slee456b7a82006-10-25 20:53:37 +0000233 set.elemType = readByte();
234 set.size = readI32();
Mark Slee530fd662006-08-09 00:05:18 +0000235 return set;
Mark Slee83c52a82006-06-07 06:51:18 +0000236 }
237
Mark Slee456b7a82006-10-25 20:53:37 +0000238 public void readSetEnd() {}
Mark Slee530fd662006-08-09 00:05:18 +0000239
Mark Slee456b7a82006-10-25 20:53:37 +0000240 public boolean readBool() throws TException {
241 return (readByte() == 1);
Mark Slee78f58e22006-09-02 04:17:07 +0000242 }
243
Mark Slee456b7a82006-10-25 20:53:37 +0000244 private byte[] bin = new byte[1];
245 public byte readByte() throws TException {
Aditya Agarwal5a429582007-02-06 02:51:15 +0000246 trans_.readAll(bin, 0, 1);
Mark Slee530fd662006-08-09 00:05:18 +0000247 return bin[0];
Mark Slee83c52a82006-06-07 06:51:18 +0000248 }
249
Mark Slee456b7a82006-10-25 20:53:37 +0000250 private byte[] i16rd = new byte[2];
251 public short readI16() throws TException {
Aditya Agarwal5a429582007-02-06 02:51:15 +0000252 trans_.readAll(i16rd, 0, 2);
Mark Slee78f58e22006-09-02 04:17:07 +0000253 return
254 (short)
255 (((i16rd[0] & 0xff) << 8) |
256 ((i16rd[1] & 0xff)));
Mark Slee83c52a82006-06-07 06:51:18 +0000257 }
258
Mark Slee456b7a82006-10-25 20:53:37 +0000259 private byte[] i32rd = new byte[4];
260 public int readI32() throws TException {
Aditya Agarwal5a429582007-02-06 02:51:15 +0000261 trans_.readAll(i32rd, 0, 4);
Mark Slee530fd662006-08-09 00:05:18 +0000262 return
263 ((i32rd[0] & 0xff) << 24) |
264 ((i32rd[1] & 0xff) << 16) |
265 ((i32rd[2] & 0xff) << 8) |
266 ((i32rd[3] & 0xff));
Mark Slee83c52a82006-06-07 06:51:18 +0000267 }
Mark Slee78f58e22006-09-02 04:17:07 +0000268
Mark Slee456b7a82006-10-25 20:53:37 +0000269 private byte[] i64rd = new byte[8];
270 public long readI64() throws TException {
Aditya Agarwal5a429582007-02-06 02:51:15 +0000271 trans_.readAll(i64rd, 0, 8);
Mark Slee530fd662006-08-09 00:05:18 +0000272 return
273 ((long)(i64rd[0] & 0xff) << 56) |
274 ((long)(i64rd[1] & 0xff) << 48) |
275 ((long)(i64rd[2] & 0xff) << 40) |
276 ((long)(i64rd[3] & 0xff) << 32) |
277 ((long)(i64rd[4] & 0xff) << 24) |
278 ((long)(i64rd[5] & 0xff) << 16) |
279 ((long)(i64rd[6] & 0xff) << 8) |
280 ((long)(i64rd[7] & 0xff));
Mark Slee83c52a82006-06-07 06:51:18 +0000281 }
282
Mark Slee456b7a82006-10-25 20:53:37 +0000283 public double readDouble() throws TException {
284 return Double.longBitsToDouble(readI64());
Mark Sleec98d0502006-09-06 02:42:25 +0000285 }
286
Mark Slee456b7a82006-10-25 20:53:37 +0000287 public String readString() throws TException {
288 int size = readI32();
Mark Slee808454e2007-06-20 21:51:57 +0000289 return readStringBody(size);
290 }
291
292 public String readStringBody(int size) throws TException {
Mark Slee530fd662006-08-09 00:05:18 +0000293 byte[] buf = new byte[size];
Aditya Agarwal5a429582007-02-06 02:51:15 +0000294 trans_.readAll(buf, 0, size);
Mark Slee530fd662006-08-09 00:05:18 +0000295 return new String(buf);
Mark Slee83c52a82006-06-07 06:51:18 +0000296 }
Mark Slee8d725a22007-04-13 01:57:12 +0000297
298 public byte[] readBinary() throws TException {
299 int size = readI32();
300 byte[] buf = new byte[size];
301 trans_.readAll(buf, 0, size);
302 return buf;
303 }
304
Mark Slee83c52a82006-06-07 06:51:18 +0000305}