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