blob: 2f2f4a1b6ed722360c85444a03f45126b6b4f65e [file] [log] [blame]
David Reiss7f42bcf2008-01-11 20:59:12 +00001//
2// TBinaryProtocol.cs
3//
4// Begin: Aug 19, 2007
David Reiss0c90f6f2008-02-06 22:18:40 +00005// Authors:
David Reiss7f42bcf2008-01-11 20:59:12 +00006// Todd Berman <tberman@imeem.com>
7// Will Palmeri <will@imeem.com>
8//
9// Distributed under the Thrift Software License
10//
11// See accompanying file LICENSE or visit the Thrift site at:
12// http://developers.facebook.com/thrift/using
13
14using System;
David Reiss7f42bcf2008-01-11 20:59:12 +000015using System.Text;
16using Thrift.Transport;
17
18namespace Thrift.Protocol
19{
20 public class TBinaryProtocol : TProtocol
21 {
22 protected const uint VERSION_MASK = 0xffff0000;
23 protected const uint VERSION_1 = 0x80010000;
24
25 protected bool strictRead_ = false;
26 protected bool strictWrite_ = true;
27
28 protected int readLength_;
29 protected bool checkReadLength_ = false;
30
31
32 #region BinaryProtocol Factory
33 /**
34 * Factory
35 */
36 public class Factory : TProtocolFactory {
37
38 protected bool strictRead_ = false;
39 protected bool strictWrite_ = true;
40
41 public Factory()
42 :this(false, true)
43 {
44 }
45
46 public Factory(bool strictRead, bool strictWrite)
47 {
48 strictRead_ = strictRead;
49 strictWrite_ = strictWrite;
50 }
51
52 public TProtocol GetProtocol(TTransport trans) {
53 return new TBinaryProtocol(trans, strictRead_, strictWrite_);
54 }
55 }
56
57 #endregion
58
59 public TBinaryProtocol(TTransport trans)
60 : this(trans, false, true)
61 {
62 }
63
64 public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
65 :base(trans)
66 {
67 strictRead_ = strictRead;
68 strictWrite_ = strictWrite;
69 }
70
71 #region Write Methods
72
73 public override void WriteMessageBegin(TMessage message)
74 {
75 if (strictWrite_)
76 {
77 uint version = VERSION_1 | (uint)(message.Type);
78 WriteI32((int)version);
79 WriteString(message.Name);
80 WriteI32(message.SeqID);
81 }
82 else
83 {
84 WriteString(message.Name);
85 WriteByte((byte)message.Type);
86 WriteI32(message.SeqID);
87 }
88 }
89
90 public override void WriteMessageEnd()
91 {
92 }
93
94 public override void WriteStructBegin(TStruct struc)
95 {
96 }
97
98 public override void WriteStructEnd()
99 {
100 }
101
102 public override void WriteFieldBegin(TField field)
103 {
104 WriteByte((byte)field.Type);
105 WriteI16(field.ID);
106 }
107
108 public override void WriteFieldEnd()
109 {
110 }
111
112 public override void WriteFieldStop()
113 {
114 WriteByte((byte)TType.Stop);
115 }
116
117 public override void WriteMapBegin(TMap map)
118 {
119 WriteByte((byte)map.KeyType);
120 WriteByte((byte)map.ValueType);
121 WriteI32(map.Count);
122 }
123
124 public override void WriteMapEnd()
125 {
126 }
127
128 public override void WriteListBegin(TList list)
129 {
130 WriteByte((byte)list.ElementType);
131 WriteI32(list.Count);
132 }
133
134 public override void WriteListEnd()
135 {
136 }
137
138 public override void WriteSetBegin(TSet set)
139 {
140 WriteByte((byte)set.ElementType);
141 WriteI32(set.Count);
142 }
143
144 public override void WriteSetEnd()
145 {
146 }
147
148 public override void WriteBool(bool b)
149 {
150 WriteByte(b ? (byte)1 : (byte)0);
151 }
152
153 private byte[] bout = new byte[1];
154 public override void WriteByte(byte b)
155 {
156 bout[0] = b;
157 trans.Write(bout, 0, 1);
158 }
159
160 private byte[] i16out = new byte[2];
161 public override void WriteI16(short s)
162 {
163 i16out[0] = (byte)(0xff & (s >> 8));
164 i16out[1] = (byte)(0xff & s);
165 trans.Write(i16out, 0, 2);
166 }
167
168 private byte[] i32out = new byte[4];
169 public override void WriteI32(int i32)
170 {
171 i32out[0] = (byte)(0xff & (i32 >> 24));
172 i32out[1] = (byte)(0xff & (i32 >> 16));
173 i32out[2] = (byte)(0xff & (i32 >> 8));
174 i32out[3] = (byte)(0xff & i32);
175 trans.Write(i32out, 0, 4);
176 }
177
178 private byte[] i64out = new byte[8];
179 public override void WriteI64(long i64)
180 {
181 i64out[0] = (byte)(0xff & (i64 >> 56));
182 i64out[1] = (byte)(0xff & (i64 >> 48));
183 i64out[2] = (byte)(0xff & (i64 >> 40));
184 i64out[3] = (byte)(0xff & (i64 >> 32));
185 i64out[4] = (byte)(0xff & (i64 >> 24));
186 i64out[5] = (byte)(0xff & (i64 >> 16));
187 i64out[6] = (byte)(0xff & (i64 >> 8));
188 i64out[7] = (byte)(0xff & i64);
189 trans.Write(i64out, 0, 8);
190 }
191
192 public override void WriteDouble(double d)
193 {
194 WriteI64(BitConverter.DoubleToInt64Bits(d));
195 }
196
David Reisscba57272008-02-06 22:09:44 +0000197 public override void WriteBinary(byte[] b)
David Reiss7f42bcf2008-01-11 20:59:12 +0000198 {
David Reiss7f42bcf2008-01-11 20:59:12 +0000199 WriteI32(b.Length);
200 trans.Write(b, 0, b.Length);
201 }
202
203 #endregion
204
205 #region ReadMethods
206
207 public override TMessage ReadMessageBegin()
208 {
209 TMessage message = new TMessage();
210 int size = ReadI32();
211 if (size < 0)
212 {
213 uint version = (uint)size & VERSION_MASK;
214 if (version != VERSION_1)
215 {
216 throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version);
217 }
218 message.Type = (TMessageType)(size & 0x000000ff);
219 message.Name = ReadString();
220 message.SeqID = ReadI32();
221 }
222 else
223 {
224 if (strictRead_)
225 {
226 throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
227 }
228 message.Name = ReadStringBody(size);
229 message.Type = (TMessageType)ReadByte();
230 message.SeqID = ReadI32();
231 }
232 return message;
233 }
234
235 public override void ReadMessageEnd()
236 {
237 }
238
239 public override TStruct ReadStructBegin()
240 {
241 return new TStruct();
242 }
243
244 public override void ReadStructEnd()
245 {
246 }
247
248 public override TField ReadFieldBegin()
249 {
250 TField field = new TField();
251 field.Type = (TType)ReadByte();
252
253 if (field.Type != TType.Stop)
254 {
255 field.ID = ReadI16();
256 }
257
258 return field;
259 }
260
261 public override void ReadFieldEnd()
262 {
263 }
264
265 public override TMap ReadMapBegin()
266 {
267 TMap map = new TMap();
268 map.KeyType = (TType)ReadByte();
269 map.ValueType = (TType)ReadByte();
270 map.Count = ReadI32();
271
272 return map;
273 }
274
275 public override void ReadMapEnd()
276 {
277 }
278
279 public override TList ReadListBegin()
280 {
281 TList list = new TList();
282 list.ElementType = (TType)ReadByte();
283 list.Count = ReadI32();
284
285 return list;
286 }
287
288 public override void ReadListEnd()
289 {
290 }
291
292 public override TSet ReadSetBegin()
293 {
294 TSet set = new TSet();
295 set.ElementType = (TType)ReadByte();
296 set.Count = ReadI32();
297
298 return set;
299 }
300
301 public override void ReadSetEnd()
302 {
303 }
304
305 public override bool ReadBool()
306 {
307 return ReadByte() == 1;
308 }
309
310 private byte[] bin = new byte[1];
311 public override byte ReadByte()
312 {
313 ReadAll(bin, 0, 1);
314 return bin[0];
315 }
316
317 private byte[] i16in = new byte[2];
318 public override short ReadI16()
319 {
320 ReadAll(i16in, 0, 2);
321 return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff)));
322 }
323
324 private byte[] i32in = new byte[4];
325 public override int ReadI32()
326 {
327 ReadAll(i32in, 0, 4);
328 return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff)));
329 }
330
331 private byte[] i64in = new byte[8];
332 public override long ReadI64()
333 {
334 ReadAll(i64in, 0, 8);
335 return (long)(((long)(i64in[0] & 0xff) << 56) | ((long)(i64in[1] & 0xff) << 48) | ((long)(i64in[2] & 0xff) << 40) | ((long)(i64in[3] & 0xff) << 32) |
336 ((long)(i64in[4] & 0xff) << 24) | ((long)(i64in[5] & 0xff) << 16) | ((long)(i64in[6] & 0xff) << 8) | ((long)(i64in[7] & 0xff)));
337 }
338
339 public override double ReadDouble()
340 {
341 return BitConverter.Int64BitsToDouble(ReadI64());
342 }
343
344 public void SetReadLength(int readLength)
345 {
346 readLength_ = readLength;
347 checkReadLength_ = true;
348 }
349
350 protected void CheckReadLength(int length)
351 {
352 if (checkReadLength_)
353 {
354 readLength_ -= length;
355 if (readLength_ < 0)
356 {
357 throw new Exception("Message length exceeded: " + length);
358 }
359 }
360 }
361
David Reisscba57272008-02-06 22:09:44 +0000362 public override byte[] ReadBinary()
David Reiss7f42bcf2008-01-11 20:59:12 +0000363 {
364 int size = ReadI32();
David Reisscba57272008-02-06 22:09:44 +0000365 CheckReadLength(size);
366 byte[] buf = new byte[size];
367 trans.ReadAll(buf, 0, size);
368 return buf;
David Reiss7f42bcf2008-01-11 20:59:12 +0000369 }
David Reisscba57272008-02-06 22:09:44 +0000370 private string ReadStringBody(int size)
David Reiss7f42bcf2008-01-11 20:59:12 +0000371 {
372 CheckReadLength(size);
373 byte[] buf = new byte[size];
374 trans.ReadAll(buf, 0, size);
375 return Encoding.UTF8.GetString(buf);
376 }
377
378 private int ReadAll(byte[] buf, int off, int len)
379 {
380 CheckReadLength(len);
381 return trans.ReadAll(buf, off, len);
382 }
383
384 #endregion
385 }
386}