blob: a4faa946f1be2530ddc5c1d7c65bc03caf6e2bc5 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* Contains some contributions under the Thrift Software License.
* Please see doc/old-thrift-license.txt in the Thrift distribution for
* details.
*/
using System;
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;
#region BinaryProtocol 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((sbyte)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((sbyte)field.Type);
WriteI16(field.ID);
}
public override void WriteFieldEnd()
{
}
public override void WriteFieldStop()
{
WriteByte((sbyte)TType.Stop);
}
public override void WriteMapBegin(TMap map)
{
WriteByte((sbyte)map.KeyType);
WriteByte((sbyte)map.ValueType);
WriteI32(map.Count);
}
public override void WriteMapEnd()
{
}
public override void WriteListBegin(TList list)
{
WriteByte((sbyte)list.ElementType);
WriteI32(list.Count);
}
public override void WriteListEnd()
{
}
public override void WriteSetBegin(TSet set)
{
WriteByte((sbyte)set.ElementType);
WriteI32(set.Count);
}
public override void WriteSetEnd()
{
}
public override void WriteBool(bool b)
{
WriteByte(b ? (sbyte)1 : (sbyte)0);
}
private byte[] bout = new byte[1];
public override void WriteByte(sbyte b)
{
bout[0] = (byte)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)
{
#if !SILVERLIGHT
WriteI64(BitConverter.DoubleToInt64Bits(d));
#else
var bytes = BitConverter.GetBytes(d);
WriteI64(BitConverter.ToInt64(bytes, 0));
#endif
}
public override void WriteBinary(byte[] b)
{
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 sbyte ReadByte()
{
ReadAll(bin, 0, 1);
return (sbyte)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)));
}
#pragma warning disable 675
private byte[] i64in = new byte[8];
public override long ReadI64()
{
ReadAll(i64in, 0, 8);
unchecked
{
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)));
}
}
#pragma warning restore 675
public override double ReadDouble()
{
#if !SILVERLIGHT
return BitConverter.Int64BitsToDouble(ReadI64());
#else
var value = ReadI64();
var bytes = BitConverter.GetBytes(value);
return BitConverter.ToDouble(bytes, 0);
#endif
}
public override byte[] ReadBinary()
{
int size = ReadI32();
byte[] buf = new byte[size];
trans.ReadAll(buf, 0, size);
return buf;
}
private string ReadStringBody(int size)
{
byte[] buf = new byte[size];
trans.ReadAll(buf, 0, size);
return Encoding.UTF8.GetString(buf, 0, buf.Length);
}
private int ReadAll(byte[] buf, int off, int len)
{
return trans.ReadAll(buf, off, len);
}
#endregion
}
}