blob: 4eceb868f2be1ae78114963f859c96e4096fc630 [file] [log] [blame]
Kevin Clarkab4460d2009-03-20 02:28:41 +00001/**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
Todd Lipcon53ae9f32009-12-07 00:42:38 +000018 *
19 * Contains some contributions under the Thrift Software License.
20 * Please see doc/old-thrift-license.txt in the Thrift distribution for
21 * details.
Kevin Clarkab4460d2009-03-20 02:28:41 +000022 */
David Reiss7f42bcf2008-01-11 20:59:12 +000023
24using System;
David Reiss7f42bcf2008-01-11 20:59:12 +000025using System.Text;
26using Thrift.Transport;
27
28namespace Thrift.Protocol
29{
Jens Geyerd5436f52014-10-03 19:50:38 +020030 public class TBinaryProtocol : TProtocol
31 {
32 protected const uint VERSION_MASK = 0xffff0000;
33 protected const uint VERSION_1 = 0x80010000;
David Reiss7f42bcf2008-01-11 20:59:12 +000034
Jens Geyerd5436f52014-10-03 19:50:38 +020035 protected bool strictRead_ = false;
36 protected bool strictWrite_ = true;
David Reiss7f42bcf2008-01-11 20:59:12 +000037
Jens Geyerd5436f52014-10-03 19:50:38 +020038 #region BinaryProtocol Factory
39 /**
40 * Factory
41 */
42 public class Factory : TProtocolFactory {
David Reiss7f42bcf2008-01-11 20:59:12 +000043
Jens Geyerd5436f52014-10-03 19:50:38 +020044 protected bool strictRead_ = false;
45 protected bool strictWrite_ = true;
David Reiss7f42bcf2008-01-11 20:59:12 +000046
Jens Geyerd5436f52014-10-03 19:50:38 +020047 public Factory()
48 :this(false, true)
49 {
50 }
David Reiss7f42bcf2008-01-11 20:59:12 +000051
Jens Geyerd5436f52014-10-03 19:50:38 +020052 public Factory(bool strictRead, bool strictWrite)
53 {
54 strictRead_ = strictRead;
55 strictWrite_ = strictWrite;
56 }
David Reiss7f42bcf2008-01-11 20:59:12 +000057
Jens Geyerd5436f52014-10-03 19:50:38 +020058 public TProtocol GetProtocol(TTransport trans) {
59 return new TBinaryProtocol(trans, strictRead_, strictWrite_);
60 }
61 }
David Reiss7f42bcf2008-01-11 20:59:12 +000062
Jens Geyerd5436f52014-10-03 19:50:38 +020063 #endregion
David Reiss7f42bcf2008-01-11 20:59:12 +000064
Jens Geyerd5436f52014-10-03 19:50:38 +020065 public TBinaryProtocol(TTransport trans)
66 : this(trans, false, true)
67 {
68 }
David Reiss7f42bcf2008-01-11 20:59:12 +000069
Jens Geyerd5436f52014-10-03 19:50:38 +020070 public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
71 :base(trans)
72 {
73 strictRead_ = strictRead;
74 strictWrite_ = strictWrite;
75 }
David Reiss7f42bcf2008-01-11 20:59:12 +000076
Jens Geyerd5436f52014-10-03 19:50:38 +020077 #region Write Methods
David Reiss7f42bcf2008-01-11 20:59:12 +000078
Jens Geyerd5436f52014-10-03 19:50:38 +020079 public override void WriteMessageBegin(TMessage message)
80 {
81 if (strictWrite_)
82 {
83 uint version = VERSION_1 | (uint)(message.Type);
84 WriteI32((int)version);
85 WriteString(message.Name);
86 WriteI32(message.SeqID);
87 }
88 else
89 {
90 WriteString(message.Name);
91 WriteByte((sbyte)message.Type);
92 WriteI32(message.SeqID);
93 }
94 }
David Reiss7f42bcf2008-01-11 20:59:12 +000095
Jens Geyerd5436f52014-10-03 19:50:38 +020096 public override void WriteMessageEnd()
97 {
98 }
David Reiss7f42bcf2008-01-11 20:59:12 +000099
Jens Geyerd5436f52014-10-03 19:50:38 +0200100 public override void WriteStructBegin(TStruct struc)
101 {
102 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000103
Jens Geyerd5436f52014-10-03 19:50:38 +0200104 public override void WriteStructEnd()
105 {
106 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000107
Jens Geyerd5436f52014-10-03 19:50:38 +0200108 public override void WriteFieldBegin(TField field)
109 {
110 WriteByte((sbyte)field.Type);
111 WriteI16(field.ID);
112 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000113
Jens Geyerd5436f52014-10-03 19:50:38 +0200114 public override void WriteFieldEnd()
115 {
116 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000117
Jens Geyerd5436f52014-10-03 19:50:38 +0200118 public override void WriteFieldStop()
119 {
120 WriteByte((sbyte)TType.Stop);
121 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000122
Jens Geyerd5436f52014-10-03 19:50:38 +0200123 public override void WriteMapBegin(TMap map)
124 {
125 WriteByte((sbyte)map.KeyType);
126 WriteByte((sbyte)map.ValueType);
127 WriteI32(map.Count);
128 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000129
Jens Geyerd5436f52014-10-03 19:50:38 +0200130 public override void WriteMapEnd()
131 {
132 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000133
Jens Geyerd5436f52014-10-03 19:50:38 +0200134 public override void WriteListBegin(TList list)
135 {
136 WriteByte((sbyte)list.ElementType);
137 WriteI32(list.Count);
138 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000139
Jens Geyerd5436f52014-10-03 19:50:38 +0200140 public override void WriteListEnd()
141 {
142 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000143
Jens Geyerd5436f52014-10-03 19:50:38 +0200144 public override void WriteSetBegin(TSet set)
145 {
146 WriteByte((sbyte)set.ElementType);
147 WriteI32(set.Count);
148 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000149
Jens Geyerd5436f52014-10-03 19:50:38 +0200150 public override void WriteSetEnd()
151 {
152 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000153
Jens Geyerd5436f52014-10-03 19:50:38 +0200154 public override void WriteBool(bool b)
155 {
156 WriteByte(b ? (sbyte)1 : (sbyte)0);
157 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000158
Jens Geyerd5436f52014-10-03 19:50:38 +0200159 private byte[] bout = new byte[1];
160 public override void WriteByte(sbyte b)
161 {
162 bout[0] = (byte)b;
163 trans.Write(bout, 0, 1);
164 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000165
Jens Geyerd5436f52014-10-03 19:50:38 +0200166 private byte[] i16out = new byte[2];
167 public override void WriteI16(short s)
168 {
169 i16out[0] = (byte)(0xff & (s >> 8));
170 i16out[1] = (byte)(0xff & s);
171 trans.Write(i16out, 0, 2);
172 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000173
Jens Geyerd5436f52014-10-03 19:50:38 +0200174 private byte[] i32out = new byte[4];
175 public override void WriteI32(int i32)
176 {
177 i32out[0] = (byte)(0xff & (i32 >> 24));
178 i32out[1] = (byte)(0xff & (i32 >> 16));
179 i32out[2] = (byte)(0xff & (i32 >> 8));
180 i32out[3] = (byte)(0xff & i32);
181 trans.Write(i32out, 0, 4);
182 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000183
Jens Geyerd5436f52014-10-03 19:50:38 +0200184 private byte[] i64out = new byte[8];
185 public override void WriteI64(long i64)
186 {
187 i64out[0] = (byte)(0xff & (i64 >> 56));
188 i64out[1] = (byte)(0xff & (i64 >> 48));
189 i64out[2] = (byte)(0xff & (i64 >> 40));
190 i64out[3] = (byte)(0xff & (i64 >> 32));
191 i64out[4] = (byte)(0xff & (i64 >> 24));
192 i64out[5] = (byte)(0xff & (i64 >> 16));
193 i64out[6] = (byte)(0xff & (i64 >> 8));
194 i64out[7] = (byte)(0xff & i64);
195 trans.Write(i64out, 0, 8);
196 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000197
Jens Geyerd5436f52014-10-03 19:50:38 +0200198 public override void WriteDouble(double d)
199 {
Roger Meier284a9b52011-12-08 13:39:56 +0000200#if !SILVERLIGHT
Jens Geyerd5436f52014-10-03 19:50:38 +0200201 WriteI64(BitConverter.DoubleToInt64Bits(d));
Roger Meier284a9b52011-12-08 13:39:56 +0000202#else
203 var bytes = BitConverter.GetBytes(d);
204 WriteI64(BitConverter.ToInt64(bytes, 0));
205#endif
Jens Geyerd5436f52014-10-03 19:50:38 +0200206 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000207
Jens Geyerd5436f52014-10-03 19:50:38 +0200208 public override void WriteBinary(byte[] b)
209 {
210 WriteI32(b.Length);
211 trans.Write(b, 0, b.Length);
212 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000213
Jens Geyerd5436f52014-10-03 19:50:38 +0200214 #endregion
David Reiss7f42bcf2008-01-11 20:59:12 +0000215
Jens Geyerd5436f52014-10-03 19:50:38 +0200216 #region ReadMethods
David Reiss7f42bcf2008-01-11 20:59:12 +0000217
Jens Geyerd5436f52014-10-03 19:50:38 +0200218 public override TMessage ReadMessageBegin()
219 {
220 TMessage message = new TMessage();
221 int size = ReadI32();
222 if (size < 0)
223 {
224 uint version = (uint)size & VERSION_MASK;
225 if (version != VERSION_1)
226 {
227 throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version);
228 }
229 message.Type = (TMessageType)(size & 0x000000ff);
230 message.Name = ReadString();
231 message.SeqID = ReadI32();
232 }
233 else
234 {
235 if (strictRead_)
236 {
237 throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
238 }
239 message.Name = ReadStringBody(size);
240 message.Type = (TMessageType)ReadByte();
241 message.SeqID = ReadI32();
242 }
243 return message;
244 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000245
Jens Geyerd5436f52014-10-03 19:50:38 +0200246 public override void ReadMessageEnd()
247 {
248 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000249
Jens Geyerd5436f52014-10-03 19:50:38 +0200250 public override TStruct ReadStructBegin()
251 {
252 return new TStruct();
253 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000254
Jens Geyerd5436f52014-10-03 19:50:38 +0200255 public override void ReadStructEnd()
256 {
257 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000258
Jens Geyerd5436f52014-10-03 19:50:38 +0200259 public override TField ReadFieldBegin()
260 {
261 TField field = new TField();
262 field.Type = (TType)ReadByte();
David Reiss7f42bcf2008-01-11 20:59:12 +0000263
Jens Geyerd5436f52014-10-03 19:50:38 +0200264 if (field.Type != TType.Stop)
265 {
266 field.ID = ReadI16();
267 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000268
Jens Geyerd5436f52014-10-03 19:50:38 +0200269 return field;
270 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000271
Jens Geyerd5436f52014-10-03 19:50:38 +0200272 public override void ReadFieldEnd()
273 {
274 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000275
Jens Geyerd5436f52014-10-03 19:50:38 +0200276 public override TMap ReadMapBegin()
277 {
278 TMap map = new TMap();
279 map.KeyType = (TType)ReadByte();
280 map.ValueType = (TType)ReadByte();
281 map.Count = ReadI32();
David Reiss7f42bcf2008-01-11 20:59:12 +0000282
Jens Geyerd5436f52014-10-03 19:50:38 +0200283 return map;
284 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000285
Jens Geyerd5436f52014-10-03 19:50:38 +0200286 public override void ReadMapEnd()
287 {
288 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000289
Jens Geyerd5436f52014-10-03 19:50:38 +0200290 public override TList ReadListBegin()
291 {
292 TList list = new TList();
293 list.ElementType = (TType)ReadByte();
294 list.Count = ReadI32();
David Reiss7f42bcf2008-01-11 20:59:12 +0000295
Jens Geyerd5436f52014-10-03 19:50:38 +0200296 return list;
297 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000298
Jens Geyerd5436f52014-10-03 19:50:38 +0200299 public override void ReadListEnd()
300 {
301 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000302
Jens Geyerd5436f52014-10-03 19:50:38 +0200303 public override TSet ReadSetBegin()
304 {
305 TSet set = new TSet();
306 set.ElementType = (TType)ReadByte();
307 set.Count = ReadI32();
David Reiss7f42bcf2008-01-11 20:59:12 +0000308
Jens Geyerd5436f52014-10-03 19:50:38 +0200309 return set;
310 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000311
Jens Geyerd5436f52014-10-03 19:50:38 +0200312 public override void ReadSetEnd()
313 {
314 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000315
Jens Geyerd5436f52014-10-03 19:50:38 +0200316 public override bool ReadBool()
317 {
318 return ReadByte() == 1;
319 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000320
Jens Geyerd5436f52014-10-03 19:50:38 +0200321 private byte[] bin = new byte[1];
322 public override sbyte ReadByte()
323 {
324 ReadAll(bin, 0, 1);
325 return (sbyte)bin[0];
326 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000327
Jens Geyerd5436f52014-10-03 19:50:38 +0200328 private byte[] i16in = new byte[2];
329 public override short ReadI16()
330 {
331 ReadAll(i16in, 0, 2);
332 return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff)));
333 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000334
Jens Geyerd5436f52014-10-03 19:50:38 +0200335 private byte[] i32in = new byte[4];
336 public override int ReadI32()
337 {
338 ReadAll(i32in, 0, 4);
339 return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff)));
340 }
Jens Geyer1c99e702014-03-17 22:50:39 +0200341
342#pragma warning disable 675
343
Jens Geyeree353e62013-07-06 09:28:49 +0200344 private byte[] i64in = new byte[8];
Jens Geyerd5436f52014-10-03 19:50:38 +0200345 public override long ReadI64()
346 {
347 ReadAll(i64in, 0, 8);
Jake Farrell98f93772012-10-20 16:47:51 +0000348 unchecked {
349 return (long)(
350 ((long)(i64in[0] & 0xff) << 56) |
351 ((long)(i64in[1] & 0xff) << 48) |
352 ((long)(i64in[2] & 0xff) << 40) |
353 ((long)(i64in[3] & 0xff) << 32) |
354 ((long)(i64in[4] & 0xff) << 24) |
355 ((long)(i64in[5] & 0xff) << 16) |
356 ((long)(i64in[6] & 0xff) << 8) |
357 ((long)(i64in[7] & 0xff)));
358 }
Jens Geyer1c99e702014-03-17 22:50:39 +0200359 }
360
361#pragma warning restore 675
362
Jens Geyeree353e62013-07-06 09:28:49 +0200363 public override double ReadDouble()
Jens Geyerd5436f52014-10-03 19:50:38 +0200364 {
Roger Meier284a9b52011-12-08 13:39:56 +0000365#if !SILVERLIGHT
Jens Geyerd5436f52014-10-03 19:50:38 +0200366 return BitConverter.Int64BitsToDouble(ReadI64());
Roger Meier284a9b52011-12-08 13:39:56 +0000367#else
368 var value = ReadI64();
369 var bytes = BitConverter.GetBytes(value);
370 return BitConverter.ToDouble(bytes, 0);
371#endif
Jens Geyerd5436f52014-10-03 19:50:38 +0200372 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000373
Jens Geyerd5436f52014-10-03 19:50:38 +0200374 public override byte[] ReadBinary()
375 {
376 int size = ReadI32();
377 byte[] buf = new byte[size];
378 trans.ReadAll(buf, 0, size);
379 return buf;
380 }
381 private string ReadStringBody(int size)
382 {
383 byte[] buf = new byte[size];
384 trans.ReadAll(buf, 0, size);
385 return Encoding.UTF8.GetString(buf, 0, buf.Length);
386 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000387
Jens Geyerd5436f52014-10-03 19:50:38 +0200388 private int ReadAll(byte[] buf, int off, int len)
389 {
390 return trans.ReadAll(buf, off, len);
391 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000392
Jens Geyerd5436f52014-10-03 19:50:38 +0200393 #endregion
394 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000395}