blob: a4faa946f1be2530ddc5c1d7c65bc03caf6e2bc5 [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
David Reiss7f42bcf2008-01-11 20:59:12 +000039
Christian Weiss8fb719e2018-03-30 21:26:04 +020040 public class Factory : TProtocolFactory
41 {
42 protected bool strictRead_ = false;
43 protected bool strictWrite_ = true;
David Reiss7f42bcf2008-01-11 20:59:12 +000044
Christian Weiss8fb719e2018-03-30 21:26:04 +020045 public Factory()
46 : this(false, true)
47 {
Jens Geyerd5436f52014-10-03 19:50:38 +020048 }
Christian Weiss8fb719e2018-03-30 21:26:04 +020049
50 public Factory(bool strictRead, bool strictWrite)
51 {
52 strictRead_ = strictRead;
53 strictWrite_ = strictWrite;
54 }
55
56 public TProtocol GetProtocol(TTransport trans)
57 {
58 return new TBinaryProtocol(trans, strictRead_, strictWrite_);
59 }
60 }
David Reiss7f42bcf2008-01-11 20:59:12 +000061
Jens Geyerd5436f52014-10-03 19:50:38 +020062 #endregion
David Reiss7f42bcf2008-01-11 20:59:12 +000063
Jens Geyerd5436f52014-10-03 19:50:38 +020064 public TBinaryProtocol(TTransport trans)
65 : this(trans, false, true)
66 {
67 }
David Reiss7f42bcf2008-01-11 20:59:12 +000068
Jens Geyerd5436f52014-10-03 19:50:38 +020069 public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
Christian Weiss8fb719e2018-03-30 21:26:04 +020070 : base(trans)
Jens Geyerd5436f52014-10-03 19:50:38 +020071 {
72 strictRead_ = strictRead;
73 strictWrite_ = strictWrite;
74 }
David Reiss7f42bcf2008-01-11 20:59:12 +000075
Jens Geyerd5436f52014-10-03 19:50:38 +020076 #region Write Methods
David Reiss7f42bcf2008-01-11 20:59:12 +000077
Jens Geyerd5436f52014-10-03 19:50:38 +020078 public override void WriteMessageBegin(TMessage message)
79 {
80 if (strictWrite_)
81 {
82 uint version = VERSION_1 | (uint)(message.Type);
83 WriteI32((int)version);
84 WriteString(message.Name);
85 WriteI32(message.SeqID);
86 }
87 else
88 {
89 WriteString(message.Name);
90 WriteByte((sbyte)message.Type);
91 WriteI32(message.SeqID);
92 }
93 }
David Reiss7f42bcf2008-01-11 20:59:12 +000094
Jens Geyerd5436f52014-10-03 19:50:38 +020095 public override void WriteMessageEnd()
96 {
97 }
David Reiss7f42bcf2008-01-11 20:59:12 +000098
Jens Geyerd5436f52014-10-03 19:50:38 +020099 public override void WriteStructBegin(TStruct struc)
100 {
101 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000102
Jens Geyerd5436f52014-10-03 19:50:38 +0200103 public override void WriteStructEnd()
104 {
105 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000106
Jens Geyerd5436f52014-10-03 19:50:38 +0200107 public override void WriteFieldBegin(TField field)
108 {
109 WriteByte((sbyte)field.Type);
110 WriteI16(field.ID);
111 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000112
Jens Geyerd5436f52014-10-03 19:50:38 +0200113 public override void WriteFieldEnd()
114 {
115 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000116
Jens Geyerd5436f52014-10-03 19:50:38 +0200117 public override void WriteFieldStop()
118 {
119 WriteByte((sbyte)TType.Stop);
120 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000121
Jens Geyerd5436f52014-10-03 19:50:38 +0200122 public override void WriteMapBegin(TMap map)
123 {
124 WriteByte((sbyte)map.KeyType);
125 WriteByte((sbyte)map.ValueType);
126 WriteI32(map.Count);
127 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000128
Jens Geyerd5436f52014-10-03 19:50:38 +0200129 public override void WriteMapEnd()
130 {
131 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000132
Jens Geyerd5436f52014-10-03 19:50:38 +0200133 public override void WriteListBegin(TList list)
134 {
135 WriteByte((sbyte)list.ElementType);
136 WriteI32(list.Count);
137 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000138
Jens Geyerd5436f52014-10-03 19:50:38 +0200139 public override void WriteListEnd()
140 {
141 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000142
Jens Geyerd5436f52014-10-03 19:50:38 +0200143 public override void WriteSetBegin(TSet set)
144 {
145 WriteByte((sbyte)set.ElementType);
146 WriteI32(set.Count);
147 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000148
Jens Geyerd5436f52014-10-03 19:50:38 +0200149 public override void WriteSetEnd()
150 {
151 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000152
Jens Geyerd5436f52014-10-03 19:50:38 +0200153 public override void WriteBool(bool b)
154 {
155 WriteByte(b ? (sbyte)1 : (sbyte)0);
156 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000157
Jens Geyerd5436f52014-10-03 19:50:38 +0200158 private byte[] bout = new byte[1];
159 public override void WriteByte(sbyte b)
160 {
161 bout[0] = (byte)b;
162 trans.Write(bout, 0, 1);
163 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000164
Jens Geyerd5436f52014-10-03 19:50:38 +0200165 private byte[] i16out = new byte[2];
166 public override void WriteI16(short s)
167 {
168 i16out[0] = (byte)(0xff & (s >> 8));
169 i16out[1] = (byte)(0xff & s);
170 trans.Write(i16out, 0, 2);
171 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000172
Jens Geyerd5436f52014-10-03 19:50:38 +0200173 private byte[] i32out = new byte[4];
174 public override void WriteI32(int i32)
175 {
176 i32out[0] = (byte)(0xff & (i32 >> 24));
177 i32out[1] = (byte)(0xff & (i32 >> 16));
178 i32out[2] = (byte)(0xff & (i32 >> 8));
179 i32out[3] = (byte)(0xff & i32);
180 trans.Write(i32out, 0, 4);
181 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000182
Jens Geyerd5436f52014-10-03 19:50:38 +0200183 private byte[] i64out = new byte[8];
184 public override void WriteI64(long i64)
185 {
186 i64out[0] = (byte)(0xff & (i64 >> 56));
187 i64out[1] = (byte)(0xff & (i64 >> 48));
188 i64out[2] = (byte)(0xff & (i64 >> 40));
189 i64out[3] = (byte)(0xff & (i64 >> 32));
190 i64out[4] = (byte)(0xff & (i64 >> 24));
191 i64out[5] = (byte)(0xff & (i64 >> 16));
192 i64out[6] = (byte)(0xff & (i64 >> 8));
193 i64out[7] = (byte)(0xff & i64);
194 trans.Write(i64out, 0, 8);
195 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000196
Jens Geyerd5436f52014-10-03 19:50:38 +0200197 public override void WriteDouble(double d)
198 {
Roger Meier284a9b52011-12-08 13:39:56 +0000199#if !SILVERLIGHT
Jens Geyerd5436f52014-10-03 19:50:38 +0200200 WriteI64(BitConverter.DoubleToInt64Bits(d));
Roger Meier284a9b52011-12-08 13:39:56 +0000201#else
202 var bytes = BitConverter.GetBytes(d);
203 WriteI64(BitConverter.ToInt64(bytes, 0));
204#endif
Jens Geyerd5436f52014-10-03 19:50:38 +0200205 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000206
Jens Geyerd5436f52014-10-03 19:50:38 +0200207 public override void WriteBinary(byte[] b)
208 {
209 WriteI32(b.Length);
210 trans.Write(b, 0, b.Length);
211 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000212
Jens Geyerd5436f52014-10-03 19:50:38 +0200213 #endregion
David Reiss7f42bcf2008-01-11 20:59:12 +0000214
Jens Geyerd5436f52014-10-03 19:50:38 +0200215 #region ReadMethods
David Reiss7f42bcf2008-01-11 20:59:12 +0000216
Jens Geyerd5436f52014-10-03 19:50:38 +0200217 public override TMessage ReadMessageBegin()
218 {
219 TMessage message = new TMessage();
220 int size = ReadI32();
221 if (size < 0)
222 {
223 uint version = (uint)size & VERSION_MASK;
224 if (version != VERSION_1)
225 {
226 throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version);
227 }
228 message.Type = (TMessageType)(size & 0x000000ff);
229 message.Name = ReadString();
230 message.SeqID = ReadI32();
231 }
232 else
233 {
234 if (strictRead_)
235 {
236 throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
237 }
238 message.Name = ReadStringBody(size);
239 message.Type = (TMessageType)ReadByte();
240 message.SeqID = ReadI32();
241 }
242 return message;
243 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000244
Jens Geyerd5436f52014-10-03 19:50:38 +0200245 public override void ReadMessageEnd()
246 {
247 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000248
Jens Geyerd5436f52014-10-03 19:50:38 +0200249 public override TStruct ReadStructBegin()
250 {
251 return new TStruct();
252 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000253
Jens Geyerd5436f52014-10-03 19:50:38 +0200254 public override void ReadStructEnd()
255 {
256 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000257
Jens Geyerd5436f52014-10-03 19:50:38 +0200258 public override TField ReadFieldBegin()
259 {
260 TField field = new TField();
261 field.Type = (TType)ReadByte();
David Reiss7f42bcf2008-01-11 20:59:12 +0000262
Jens Geyerd5436f52014-10-03 19:50:38 +0200263 if (field.Type != TType.Stop)
264 {
265 field.ID = ReadI16();
266 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000267
Jens Geyerd5436f52014-10-03 19:50:38 +0200268 return field;
269 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000270
Jens Geyerd5436f52014-10-03 19:50:38 +0200271 public override void ReadFieldEnd()
272 {
273 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000274
Jens Geyerd5436f52014-10-03 19:50:38 +0200275 public override TMap ReadMapBegin()
276 {
277 TMap map = new TMap();
278 map.KeyType = (TType)ReadByte();
279 map.ValueType = (TType)ReadByte();
280 map.Count = ReadI32();
David Reiss7f42bcf2008-01-11 20:59:12 +0000281
Jens Geyerd5436f52014-10-03 19:50:38 +0200282 return map;
283 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000284
Jens Geyerd5436f52014-10-03 19:50:38 +0200285 public override void ReadMapEnd()
286 {
287 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000288
Jens Geyerd5436f52014-10-03 19:50:38 +0200289 public override TList ReadListBegin()
290 {
291 TList list = new TList();
292 list.ElementType = (TType)ReadByte();
293 list.Count = ReadI32();
David Reiss7f42bcf2008-01-11 20:59:12 +0000294
Jens Geyerd5436f52014-10-03 19:50:38 +0200295 return list;
296 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000297
Jens Geyerd5436f52014-10-03 19:50:38 +0200298 public override void ReadListEnd()
299 {
300 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000301
Jens Geyerd5436f52014-10-03 19:50:38 +0200302 public override TSet ReadSetBegin()
303 {
304 TSet set = new TSet();
305 set.ElementType = (TType)ReadByte();
306 set.Count = ReadI32();
David Reiss7f42bcf2008-01-11 20:59:12 +0000307
Jens Geyerd5436f52014-10-03 19:50:38 +0200308 return set;
309 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000310
Jens Geyerd5436f52014-10-03 19:50:38 +0200311 public override void ReadSetEnd()
312 {
313 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000314
Jens Geyerd5436f52014-10-03 19:50:38 +0200315 public override bool ReadBool()
316 {
317 return ReadByte() == 1;
318 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000319
Jens Geyerd5436f52014-10-03 19:50:38 +0200320 private byte[] bin = new byte[1];
321 public override sbyte ReadByte()
322 {
323 ReadAll(bin, 0, 1);
324 return (sbyte)bin[0];
325 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000326
Jens Geyerd5436f52014-10-03 19:50:38 +0200327 private byte[] i16in = new byte[2];
328 public override short ReadI16()
329 {
330 ReadAll(i16in, 0, 2);
331 return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff)));
332 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000333
Jens Geyerd5436f52014-10-03 19:50:38 +0200334 private byte[] i32in = new byte[4];
335 public override int ReadI32()
336 {
337 ReadAll(i32in, 0, 4);
338 return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff)));
339 }
Jens Geyer1c99e702014-03-17 22:50:39 +0200340
341#pragma warning disable 675
342
Jens Geyeree353e62013-07-06 09:28:49 +0200343 private byte[] i64in = new byte[8];
Jens Geyerd5436f52014-10-03 19:50:38 +0200344 public override long ReadI64()
345 {
346 ReadAll(i64in, 0, 8);
Christian Weiss8fb719e2018-03-30 21:26:04 +0200347 unchecked
348 {
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)));
Jake Farrell98f93772012-10-20 16:47:51 +0000358 }
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 }
Christian Weiss8fb719e2018-03-30 21:26:04 +0200381 private string ReadStringBody(int size)
Jens Geyerd5436f52014-10-03 19:50:38 +0200382 {
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}