| // |
| // TBinaryProtocol.cs |
| // |
| // Begin: Aug 19, 2007 |
| // Authors: |
| // Todd Berman <tberman@imeem.com> |
| // Will Palmeri <will@imeem.com> |
| // |
| // Distributed under the Thrift Software License |
| // |
| // See accompanying file LICENSE or visit the Thrift site at: |
| // http://developers.facebook.com/thrift/using |
| |
| using System; |
| using System.Collections.Generic; |
| using System.Text; |
| using Thrift.Transport; |
| |
| namespace Thrift.Protocol |
| { |
| public class TBinaryProtocol : TProtocol |
| { |
| protected const uint VERSION_MASK = 0xffff0000; |
| protected const uint VERSION_1 = 0x80010000; |
| |
| protected bool strictRead_ = false; |
| protected bool strictWrite_ = true; |
| |
| protected int readLength_; |
| protected bool checkReadLength_ = false; |
| |
| |
| #region BinaryProtocol Factory |
| /** |
| * Factory |
| */ |
| public class Factory : TProtocolFactory { |
| |
| protected bool strictRead_ = false; |
| protected bool strictWrite_ = true; |
| |
| public Factory() |
| :this(false, true) |
| { |
| } |
| |
| public Factory(bool strictRead, bool strictWrite) |
| { |
| strictRead_ = strictRead; |
| strictWrite_ = strictWrite; |
| } |
| |
| public TProtocol GetProtocol(TTransport trans) { |
| return new TBinaryProtocol(trans, strictRead_, strictWrite_); |
| } |
| } |
| |
| #endregion |
| |
| public TBinaryProtocol(TTransport trans) |
| : this(trans, false, true) |
| { |
| } |
| |
| public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) |
| :base(trans) |
| { |
| strictRead_ = strictRead; |
| strictWrite_ = strictWrite; |
| } |
| |
| #region Write Methods |
| |
| public override void WriteMessageBegin(TMessage message) |
| { |
| if (strictWrite_) |
| { |
| uint version = VERSION_1 | (uint)(message.Type); |
| WriteI32((int)version); |
| WriteString(message.Name); |
| WriteI32(message.SeqID); |
| } |
| else |
| { |
| WriteString(message.Name); |
| WriteByte((byte)message.Type); |
| WriteI32(message.SeqID); |
| } |
| } |
| |
| public override void WriteMessageEnd() |
| { |
| } |
| |
| public override void WriteStructBegin(TStruct struc) |
| { |
| } |
| |
| public override void WriteStructEnd() |
| { |
| } |
| |
| public override void WriteFieldBegin(TField field) |
| { |
| WriteByte((byte)field.Type); |
| WriteI16(field.ID); |
| } |
| |
| public override void WriteFieldEnd() |
| { |
| } |
| |
| public override void WriteFieldStop() |
| { |
| WriteByte((byte)TType.Stop); |
| } |
| |
| public override void WriteMapBegin(TMap map) |
| { |
| WriteByte((byte)map.KeyType); |
| WriteByte((byte)map.ValueType); |
| WriteI32(map.Count); |
| } |
| |
| public override void WriteMapEnd() |
| { |
| } |
| |
| public override void WriteListBegin(TList list) |
| { |
| WriteByte((byte)list.ElementType); |
| WriteI32(list.Count); |
| } |
| |
| public override void WriteListEnd() |
| { |
| } |
| |
| public override void WriteSetBegin(TSet set) |
| { |
| WriteByte((byte)set.ElementType); |
| WriteI32(set.Count); |
| } |
| |
| public override void WriteSetEnd() |
| { |
| } |
| |
| public override void WriteBool(bool b) |
| { |
| WriteByte(b ? (byte)1 : (byte)0); |
| } |
| |
| private byte[] bout = new byte[1]; |
| public override void WriteByte(byte b) |
| { |
| bout[0] = b; |
| trans.Write(bout, 0, 1); |
| } |
| |
| private byte[] i16out = new byte[2]; |
| public override void WriteI16(short s) |
| { |
| i16out[0] = (byte)(0xff & (s >> 8)); |
| i16out[1] = (byte)(0xff & s); |
| trans.Write(i16out, 0, 2); |
| } |
| |
| private byte[] i32out = new byte[4]; |
| public override void WriteI32(int i32) |
| { |
| i32out[0] = (byte)(0xff & (i32 >> 24)); |
| i32out[1] = (byte)(0xff & (i32 >> 16)); |
| i32out[2] = (byte)(0xff & (i32 >> 8)); |
| i32out[3] = (byte)(0xff & i32); |
| trans.Write(i32out, 0, 4); |
| } |
| |
| private byte[] i64out = new byte[8]; |
| public override void WriteI64(long i64) |
| { |
| i64out[0] = (byte)(0xff & (i64 >> 56)); |
| i64out[1] = (byte)(0xff & (i64 >> 48)); |
| i64out[2] = (byte)(0xff & (i64 >> 40)); |
| i64out[3] = (byte)(0xff & (i64 >> 32)); |
| i64out[4] = (byte)(0xff & (i64 >> 24)); |
| i64out[5] = (byte)(0xff & (i64 >> 16)); |
| i64out[6] = (byte)(0xff & (i64 >> 8)); |
| i64out[7] = (byte)(0xff & i64); |
| trans.Write(i64out, 0, 8); |
| } |
| |
| public override void WriteDouble(double d) |
| { |
| WriteI64(BitConverter.DoubleToInt64Bits(d)); |
| } |
| |
| public override void WriteString(string s) |
| { |
| byte[] b = Encoding.UTF8.GetBytes(s); |
| WriteI32(b.Length); |
| trans.Write(b, 0, b.Length); |
| } |
| |
| #endregion |
| |
| #region ReadMethods |
| |
| public override TMessage ReadMessageBegin() |
| { |
| TMessage message = new TMessage(); |
| int size = ReadI32(); |
| if (size < 0) |
| { |
| uint version = (uint)size & VERSION_MASK; |
| if (version != VERSION_1) |
| { |
| throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version); |
| } |
| message.Type = (TMessageType)(size & 0x000000ff); |
| message.Name = ReadString(); |
| message.SeqID = ReadI32(); |
| } |
| else |
| { |
| if (strictRead_) |
| { |
| throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?"); |
| } |
| message.Name = ReadStringBody(size); |
| message.Type = (TMessageType)ReadByte(); |
| message.SeqID = ReadI32(); |
| } |
| return message; |
| } |
| |
| public override void ReadMessageEnd() |
| { |
| } |
| |
| public override TStruct ReadStructBegin() |
| { |
| return new TStruct(); |
| } |
| |
| public override void ReadStructEnd() |
| { |
| } |
| |
| public override TField ReadFieldBegin() |
| { |
| TField field = new TField(); |
| field.Type = (TType)ReadByte(); |
| |
| if (field.Type != TType.Stop) |
| { |
| field.ID = ReadI16(); |
| } |
| |
| return field; |
| } |
| |
| public override void ReadFieldEnd() |
| { |
| } |
| |
| public override TMap ReadMapBegin() |
| { |
| TMap map = new TMap(); |
| map.KeyType = (TType)ReadByte(); |
| map.ValueType = (TType)ReadByte(); |
| map.Count = ReadI32(); |
| |
| return map; |
| } |
| |
| public override void ReadMapEnd() |
| { |
| } |
| |
| public override TList ReadListBegin() |
| { |
| TList list = new TList(); |
| list.ElementType = (TType)ReadByte(); |
| list.Count = ReadI32(); |
| |
| return list; |
| } |
| |
| public override void ReadListEnd() |
| { |
| } |
| |
| public override TSet ReadSetBegin() |
| { |
| TSet set = new TSet(); |
| set.ElementType = (TType)ReadByte(); |
| set.Count = ReadI32(); |
| |
| return set; |
| } |
| |
| public override void ReadSetEnd() |
| { |
| } |
| |
| public override bool ReadBool() |
| { |
| return ReadByte() == 1; |
| } |
| |
| private byte[] bin = new byte[1]; |
| public override byte ReadByte() |
| { |
| ReadAll(bin, 0, 1); |
| return bin[0]; |
| } |
| |
| private byte[] i16in = new byte[2]; |
| public override short ReadI16() |
| { |
| ReadAll(i16in, 0, 2); |
| return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff))); |
| } |
| |
| private byte[] i32in = new byte[4]; |
| public override int ReadI32() |
| { |
| ReadAll(i32in, 0, 4); |
| return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff))); |
| } |
| |
| private byte[] i64in = new byte[8]; |
| public override long ReadI64() |
| { |
| ReadAll(i64in, 0, 8); |
| return (long)(((long)(i64in[0] & 0xff) << 56) | ((long)(i64in[1] & 0xff) << 48) | ((long)(i64in[2] & 0xff) << 40) | ((long)(i64in[3] & 0xff) << 32) | |
| ((long)(i64in[4] & 0xff) << 24) | ((long)(i64in[5] & 0xff) << 16) | ((long)(i64in[6] & 0xff) << 8) | ((long)(i64in[7] & 0xff))); |
| } |
| |
| public override double ReadDouble() |
| { |
| return BitConverter.Int64BitsToDouble(ReadI64()); |
| } |
| |
| public void SetReadLength(int readLength) |
| { |
| readLength_ = readLength; |
| checkReadLength_ = true; |
| } |
| |
| protected void CheckReadLength(int length) |
| { |
| if (checkReadLength_) |
| { |
| readLength_ -= length; |
| if (readLength_ < 0) |
| { |
| throw new Exception("Message length exceeded: " + length); |
| } |
| } |
| } |
| |
| public override string ReadString() |
| { |
| int size = ReadI32(); |
| return ReadStringBody(size); |
| } |
| |
| public string ReadStringBody(int size) |
| { |
| CheckReadLength(size); |
| byte[] buf = new byte[size]; |
| trans.ReadAll(buf, 0, size); |
| return Encoding.UTF8.GetString(buf); |
| } |
| |
| private int ReadAll(byte[] buf, int off, int len) |
| { |
| CheckReadLength(len); |
| return trans.ReadAll(buf, off, len); |
| } |
| |
| #endregion |
| } |
| } |