Skip to content

Instantly share code, notes, and snippets.

@dimzon
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dimzon/2b1d22b6d5d0589cdca6 to your computer and use it in GitHub Desktop.
Save dimzon/2b1d22b6d5d0589cdca6 to your computer and use it in GitHub Desktop.
MeaasagePack for JSON.NET
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.MessagePack
{
public static class MessagePack
{
private static class MessagePackConstants
{
public const sbyte ExtTypeDateTime = 21;
public const sbyte ExtTypeTimeStamp = 22;
public const byte TagNil = 0xc0;
public const byte TagFalse = 0xc2;
public const byte TagTrue = 0xc3;
public const byte TagBin8 = 0xc4;
public const byte TagBin16 = 0xc5;
public const byte TagBin32 = 0xc6;
public const byte TagFloat32 = 0xca;
public const byte TagFloat64 = 0xcb;
public const byte TagUint8 = 0xcc;
public const byte TagUint16 = 0xcd;
public const byte TagUint32 = 0xce;
public const byte TagUint64 = 0xcf;
public const byte TagInt8 = 0xd0;
public const byte TagInt16 = 0xd1;
public const byte TagInt32 = 0xd2;
public const byte TagInt64 = 0xd3;
public const byte TagFixExt1 = 0xd4;
public const byte TagFixExt2 = 0xd5;
public const byte TagFixExt4 = 0xd6;
public const byte TagFixExt8 = 0xd7;
public const byte TagFixExt16 = 0xd8;
public const byte TagStr8 = 0xd9;
public const byte TagStr16 = 0xda;
public const byte TagStr32 = 0xdb;
public const byte TagArr16 = 0xdc;
public const byte TagArr32 = 0xdd;
public const byte TagMap16 = 0xde;
public const byte TagMap32 = 0xdf;
}
public class MessagePackWriter : JsonWriter
{
private class Container
{
public readonly Stream Out;
public ulong Counter;
public Container(Stream str)
{
Out = str;
}
protected Container() : this(new MemoryStream()) { }
public virtual void OnObjectProperty()
{
}
public virtual void OnArrayItem()
{
}
}
private class ObjectContainer : Container
{
public override void OnObjectProperty()
{
++Counter;
}
}
private class ArrayContainer : Container
{
public override void OnArrayItem()
{
++Counter;
}
}
private readonly Stack<Container> _containers = new Stack<Container>();
private readonly Stream _outputStream;
private Container _peekContainer;
public MessagePackWriter(Stream outputStream)
{
_outputStream = outputStream;
_peekContainer = new Container(outputStream);
_containers.Push(_peekContainer);
}
public override void WriteNull()
{
//!! base.WriteNull();
_ints[0] = MessagePackConstants.TagNil;
_peekContainer.Out.Write(_ints, 0, 1);
_peekContainer.OnArrayItem();
}
public override void WriteUndefined()
{
WriteNull();
}
public override void Close()
{
//!! base.Close();
// foreach (var container in _containers)
// {
// container.Out.Close();
// }
_outputStream.Close();
}
public override void WriteStartObject()
{
//!! base.WriteStartObject();
_peekContainer = new ObjectContainer();
_containers.Push(_peekContainer);
}
public override void WriteEndObject()
{
//!! base.WriteEndObject();
var objectContainer = _containers.Pop();
_peekContainer = _containers.Peek();
_peekContainer.OnArrayItem();
var mapSize = objectContainer.Counter;
var stream = _peekContainer.Out;
if (mapSize < 16)
{
_ints[0] = (byte)(0x80 | mapSize);
stream.Write(_ints, 0, 1);
}
else if (mapSize <= 0xFFFF)
{
Write16(stream, MessagePackConstants.TagMap16, mapSize);
}
else
{
Write32(stream, MessagePackConstants.TagMap32, mapSize);
}
using (var memoryStream = ((MemoryStream)objectContainer.Out))
{
var buff = memoryStream.GetBuffer();
stream.Write(buff, 0, (int)memoryStream.Length);
}
}
private void Write08(Stream stream, byte prefix, ulong l2)
{
_ints[0] = prefix;
_ints[1] = (byte)(l2 & 0xff);
stream.Write(_ints, 0, 2);
}
private void Write16(Stream stream, byte prefix, ulong l2)
{
_ints[0] = prefix;
_ints[1] = (byte)((l2 & 0xff00) >> 8);
_ints[2] = (byte)(l2 & 0xff);
stream.Write(_ints, 0, 3);
}
private void Write32(Stream stream, byte prefix, ulong l2)
{
_ints[0] = prefix;
_ints[1] = (byte)((l2 & 0xff000000) >> 24);
_ints[2] = (byte)((l2 & 0xff0000) >> 16);
_ints[3] = (byte)((l2 & 0xff00) >> 8);
_ints[4] = (byte)(l2 & 0xff);
stream.Write(_ints, 0, 5);
}
private readonly byte[] _ints = new byte[9];
private void Write64(Stream stream, byte prefix, ulong l2)
{
_ints[0] = prefix;
_ints[1] = (byte)((l2 & 0xff00000000000000) >> 56);
_ints[2] = (byte)((l2 & 0xff000000000000) >> 48);
_ints[3] = (byte)((l2 & 0xff0000000000) >> 40);
_ints[4] = (byte)((l2 & 0xff00000000) >> 32);
_ints[5] = (byte)((l2 & 0xff000000) >> 24);
_ints[6] = (byte)((l2 & 0xff0000) >> 16);
_ints[7] = (byte)((l2 & 0xff00) >> 8);
_ints[8] = (byte)(l2 & 0xff);
stream.Write(_ints, 0, 9);
}
public override void WriteStartArray()
{
//!! base.WriteStartArray();
_peekContainer = new ArrayContainer();
_containers.Push(_peekContainer);
}
public override void WriteEndArray()
{
//!! base.WriteEndArray();
var arrayContainer = _containers.Pop();
_peekContainer = _containers.Peek();
_peekContainer.OnArrayItem();
var arraySize = arrayContainer.Counter;
var stream = _peekContainer.Out;
if (arraySize < 16)
{
_ints[0] = ((byte)(0x90 | arraySize));
stream.Write(_ints, 0, 1);
}
else if (arraySize <= 0xFFFF)
{
Write16(stream, MessagePackConstants.TagArr16, arraySize);
}
else
{
Write32(stream, MessagePackConstants.TagArr32, arraySize);
}
using (var memoryStream = ((MemoryStream)arrayContainer.Out))
{
var buff = memoryStream.GetBuffer();
stream.Write(buff, 0, (int)memoryStream.Length);
}
}
public override void WriteStartConstructor(string name)
{
throw new JsonWriterException("Cannot write JSON constructor as MsgPack.");
}
public override void WritePropertyName(string name)
{
//!! base.WritePropertyName(name);
_peekContainer.OnObjectProperty();
if (name == null)
{
_ints[0] = MessagePackConstants.TagNil;
_peekContainer.Out.Write(_ints, 0, 1);
}
else
PutString(name);
}
public override void WritePropertyName(string name, bool escape)
{
WritePropertyName(name);
}
protected override void WriteIndent()
{
}
protected override void WriteValueDelimiter()
{
}
protected override void WriteIndentSpace()
{
}
public override void WriteRaw(string json)
{
throw new JsonWriterException("Cannot write raw as MsgPack.");
}
public override void WriteRawValue(string json)
{
throw new JsonWriterException("Cannot write raw as MsgPack.");
}
internal static readonly UTF8Encoding Utf8 = new UTF8Encoding(false);
public override void WriteValue(string value)
{
if (value == null)
{
WriteNull();
return;
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
PutString(value);
}
private int _buffSize = 256;
private byte[] _buffBytes = new byte[256];
private void PutString(string value)
{
unchecked
{
var charCount = value.Length;
var maxCount = 4 * charCount + 16; //Utf8.GetMaxByteCount(charCount);
if (_buffSize < maxCount)
{
_buffSize = maxCount;
_buffBytes = new byte[maxCount];
}
var len = (ulong)Utf8.GetBytes(value, 0, charCount, _buffBytes, 1);
var @out = _peekContainer.Out;
if (len < 0x20)
{
_buffBytes[0] = ((byte)(0xA0 | len));
@out.Write(_buffBytes, 0, (int)len + 1);
return;
}
if (len < 0x100)
{
Write08(@out, MessagePackConstants.TagStr8, len);
}
else if (len < 0x10000)
{
Write16(@out, MessagePackConstants.TagStr16, len);
}
else
{
Write32(@out, MessagePackConstants.TagStr32, len);
}
@out.Write(_buffBytes, 1, (int)len);
}
}
public override void WriteValue(byte[] value)
{
if (value == null)
{
WriteNull();
return;
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
var str = _peekContainer.Out;
unchecked
{
var len = (ulong)value.Length;
if (len < 0x100)
{
Write08(str, MessagePackConstants.TagBin8, len);
}
else if (len < 0x10000)
{
Write16(str, MessagePackConstants.TagBin16, len);
}
else
{
Write32(str, MessagePackConstants.TagBin32, len);
}
}
str.Write(value, 0, value.Length);
}
public override void WriteValue(char value)
{
WriteValue((ulong)value);
}
public override void WriteValue(sbyte value)
{
unchecked
{
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
if (value >= -32)
{
// -32..+127
// 111YYYYY .. 0XXXXXXX
// positive fixnum stores 7-bit positive integer
// negative fixnum stores 5-bit negative integer
_ints[0] = (byte)value;
_peekContainer.Out.Write(_ints, 0, 1);
return;
}
Write08(_peekContainer.Out, MessagePackConstants.TagInt8, (ulong)value);
}
}
public override void WriteValue(byte value)
{
unchecked
{
if (value <= SByte.MaxValue)
{
WriteValue((sbyte)value);
return;
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
Write16(_peekContainer.Out, MessagePackConstants.TagUint8, value);
}
}
public override void WriteValue(short value)
{
unchecked
{
if (value >= 0)
{
if (value <= Byte.MaxValue)
{
WriteValue((byte)value);
return;
}
}
else
{
if (value >= SByte.MinValue)
{
WriteValue((sbyte)value);
return;
}
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
Write16(_peekContainer.Out, MessagePackConstants.TagInt16, (ulong)value);
}
}
public override void WriteValue(ushort value)
{
unchecked
{
if (value <= Int16.MaxValue)
{
WriteValue((short)value);
return;
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
Write16(_peekContainer.Out, MessagePackConstants.TagUint16, value);
}
}
public override void WriteValue(int value)
{
unchecked
{
if (value >= 0)
{
if (value <= UInt16.MaxValue)
{
WriteValue((ushort)value);
return;
}
}
else
{
if (value >= Int16.MinValue)
{
WriteValue((short)value);
return;
}
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
Write32(_peekContainer.Out, MessagePackConstants.TagInt32, (ulong)value);
}
}
public override void WriteValue(uint value)
{
unchecked
{
if (value <= Int32.MaxValue)
{
WriteValue((int)value);
return;
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
Write32(_peekContainer.Out, MessagePackConstants.TagUint32, value);
}
}
public override void WriteValue(long value)
{
unchecked
{
if (value >= 0)
{
if (value <= UInt32.MaxValue)
{
WriteValue((uint)value);
return;
}
}
else
{
if (value >= Int32.MinValue)
{
WriteValue((int)value);
return;
}
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
Write64(_peekContainer.Out, MessagePackConstants.TagInt64, (ulong)value);
}
}
public override void WriteValue(ulong value)
{
unchecked
{
if (value <= Int64.MaxValue)
{
WriteValue((long)value);
return;
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
Write64(_peekContainer.Out, MessagePackConstants.TagUint64, value);
}
}
private static readonly byte[] FloatTag = { MessagePackConstants.TagFloat32 };
public override void WriteValue(float value)
{
var bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
_peekContainer.Out.Write(FloatTag, 0, 1);
_peekContainer.Out.Write(bytes, 0, 4);
}
private static readonly byte[] DoubleTag = { MessagePackConstants.TagFloat64 };
public override void WriteValue(double value)
{
var bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
_peekContainer.Out.Write(DoubleTag, 0, 1);
_peekContainer.Out.Write(bytes, 0, 8);
}
public override void WriteValue(bool value)
{
//!! base.WriteValue(value);
_peekContainer.OnArrayItem();
_ints[0] = value ? MessagePackConstants.TagTrue : MessagePackConstants.TagFalse;
_peekContainer.Out.Write(_ints, 0, 1);
}
public override void WriteValue(decimal value)
{
WriteValue(value.ToString(Culture));
}
private void WriteFixExt8(sbyte type, ulong value)
{
unchecked
{
_ints[0] = MessagePackConstants.TagFixExt8;
var @out = _peekContainer.Out;
@out.Write(_ints, 0, 1);
Write64(@out, (byte)type, value);
}
}
public override void WriteValue(DateTime value)
{
unchecked
{
WriteFixExt8(MessagePackConstants.ExtTypeDateTime,(ulong) value.ToBinary());
}
}
public override void WriteValue(DateTimeOffset value)
{
WriteValue(value.UtcDateTime);
}
public override void WriteValue(Guid value)
{
WriteValue(value.ToByteArray());
}
public override void WriteValue(TimeSpan value)
{
unchecked
{
WriteFixExt8(MessagePackConstants.ExtTypeTimeStamp, (ulong)value.Ticks);
}
}
public override void WriteValue(int? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(uint? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(long? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(ulong? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(float? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(double? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(bool? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(short? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(ushort? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(char? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(byte? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(sbyte? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(decimal? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(DateTime? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(DateTimeOffset? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(Guid? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(TimeSpan? value)
{
if (value.HasValue)
WriteValue(value.Value);
else
WriteNull();
}
public override void WriteValue(Uri value)
{
WriteValue(value.ToString());
}
public override void WriteComment(string text)
{
}
public override void WriteWhitespace(string ws)
{
}
public override void Flush()
{
_outputStream.Flush();
}
}
public class MessagePackReader : JsonReader
{
private readonly Stream _inputStream;
private readonly Stack<Container> _ctxs = new Stack<Container>();
private Container _topCtx;
private void PushCtx(Container ctx)
{
_ctxs.Push(ctx);
_topCtx = ctx;
}
private void PopCtx()
{
_ctxs.Pop();
_topCtx = _ctxs.Peek();
}
public MessagePackReader(Stream inputStream)
{
_inputStream = inputStream;
PushCtx(new RootContainer(this));
}
public override void Close()
{
base.Close();
_inputStream.Close();
}
public override bool Read()
{
return _topCtx.Read();
}
private abstract class Container
{
protected readonly MessagePackReader Reader;
protected Container(MessagePackReader reader)
{
Reader = reader;
}
public virtual bool Read()
{
return Reader.ReadValue(Reader.SetToken);
}
}
private class RootContainer : Container
{
public RootContainer(MessagePackReader reader)
: base(reader)
{
}
}
private class ArrayContainer : Container
{
private uint _size;
public ArrayContainer(MessagePackReader reader, uint size)
: base(reader)
{
_size = size;
}
public override bool Read()
{
if (_size == 0)
{
Reader.SetToken(JsonToken.EndArray);
Reader.PopCtx();
return true;
}
--_size;
return base.Read();
}
}
private class ObjectContainer : Container
{
private uint _size;
private bool _prop = true;
public ObjectContainer(MessagePackReader reader, uint size)
: base(reader)
{
_size = size;
}
public override bool Read()
{
if (_size == 0)
{
Reader.SetToken(JsonToken.EndObject);
Reader.PopCtx();
return true;
}
if (_prop)
{
_prop = false;
Reader.ReadValue((token, o) =>
{
switch (token)
{
case JsonToken.String:
Reader.SetToken(JsonToken.PropertyName, o);
break;
case JsonToken.Date:
case JsonToken.Float:
case JsonToken.Integer:
Reader.SetToken(JsonToken.PropertyName, o.ToString());
break;
default:
throw new Exception("TODO: unknownToken" + token);
}
});
return true;
}
_prop = true;
--_size;
return base.Read();
}
}
private static readonly object TrueBox = true;
private static readonly object FalseBox = false;
private byte[] ReadBytes(int n)
{
var bytes = new byte[n];
if(n!=_inputStream.Read(bytes,0,n)) throw new Exception("TODO:EOF");
return bytes;
}
private bool ReadValue(Action<JsonToken,Object> setToken)
{
unchecked
{
if (1 != _inputStream.Read(_buff, 0, 1)) return false;
var type = _buff[0];
switch (type)
{
case MessagePackConstants.TagNil:
setToken(JsonToken.Null, null);
return true;
case MessagePackConstants.TagFalse:
setToken(JsonToken.Boolean, FalseBox);
return true;
case MessagePackConstants.TagTrue:
setToken(JsonToken.Boolean, TrueBox);
return true;
case MessagePackConstants.TagBin8:
setToken(JsonToken.Bytes, ReadBytes(ReadByte()));
return true;
case MessagePackConstants.TagBin16:
setToken(JsonToken.Bytes, ReadBytes(ReadUshort()));
return true;
case MessagePackConstants.TagBin32:
setToken(JsonToken.Bytes, ReadBytes((int) ReadUint()));
return true;
case MessagePackConstants.TagFloat32:
setToken(JsonToken.Float, ReadFloat32());
return true;
case MessagePackConstants.TagFloat64:
setToken(JsonToken.Float, ReadFloat64());
return true;
case MessagePackConstants.TagUint8:
setToken(JsonToken.Integer, ReadByte());
return true;
case MessagePackConstants.TagUint16:
setToken(JsonToken.Integer, ReadUshort());
return true;
case MessagePackConstants.TagUint32:
setToken(JsonToken.Integer, ReadUint());
return true;
case MessagePackConstants.TagUint64:
setToken(JsonToken.Integer, ReadUlong());
return true;
case MessagePackConstants.TagInt8:
setToken(JsonToken.Integer, (sbyte)ReadByte());
return true;
case MessagePackConstants.TagInt16:
setToken(JsonToken.Integer, (short)ReadUshort());
return true;
case MessagePackConstants.TagInt32:
setToken(JsonToken.Integer, (int)ReadUint());
return true;
case MessagePackConstants.TagInt64:
setToken(JsonToken.Integer, (long)ReadUlong());
return true;
case MessagePackConstants.TagFixExt1:
ProcessFixExt1((sbyte) ReadByte(), setToken);
return true;
case MessagePackConstants.TagFixExt2:
ProcessFixExt2((sbyte)ReadByte(), setToken);
return true;
case MessagePackConstants.TagFixExt4:
ProcessFixExt4((sbyte) ReadByte(), setToken);
return true;
case MessagePackConstants.TagFixExt8:
ProcessFixExt8((sbyte) ReadByte(),setToken);
return true;
case MessagePackConstants.TagFixExt16:
ProcessFixExt16((sbyte) ReadByte(),setToken);
return true;
case MessagePackConstants.TagStr8:
setToken(JsonToken.String, GetStr(ReadByte()));
return true;
case MessagePackConstants.TagStr16:
setToken(JsonToken.String, GetStr(ReadUshort()));
return true;
case MessagePackConstants.TagStr32:
setToken(JsonToken.String, GetStr((int)ReadUint()));
return true;
case MessagePackConstants.TagArr16:
PushCtx(new ArrayContainer(this, ReadUshort()));
setToken(JsonToken.StartArray, null);
return true;
case MessagePackConstants.TagArr32:
PushCtx(new ArrayContainer(this, ReadUint()));
setToken(JsonToken.StartArray, null);
return true;
case MessagePackConstants.TagMap16:
PushCtx(new ObjectContainer(this, ReadUshort()));
setToken(JsonToken.StartObject, null);
return true;
case MessagePackConstants.TagMap32:
PushCtx(new ObjectContainer(this, ReadUint()));
setToken(JsonToken.StartObject, null);
return true;
default:
if ( /*type >=0 &&*/ type <= 0x7f)
{
setToken(JsonToken.Integer, type);
return true;
}
if (type >= 0xe0 && type <= 0xff)
{
setToken(JsonToken.Integer, (sbyte)type);
return true;
}
if (type >= 0x80 && type <= 0x8f)
{
PushCtx(new ObjectContainer(this, (uint)(type & 0x0f)));
setToken(JsonToken.StartObject, null);
return true;
}
if (type >= 0x90 && type <= 0x9f)
{
PushCtx(new ArrayContainer(this, (uint)(type & 0x0f)));
setToken(JsonToken.StartArray, null);
return true;
}
if (type >= 0xa0 && type <= 0xbf)
{
setToken(JsonToken.String, GetStr(type & 0x1f));
return true;
}
throw new Exception("TODO:Unknown type=" + type);
}
}
}
private class UnknownExtensionContainer: Container
{
private readonly sbyte _type;
private readonly byte _tag;
private readonly object _dataBytes;
private readonly JsonToken _valueToken;
private int _step;
public UnknownExtensionContainer(MessagePackReader reader, byte tag, sbyte type, object dataBytes, JsonToken valueToken) : base(reader)
{
_tag = tag;
_type = type;
_dataBytes = dataBytes;
_valueToken = valueToken;
}
public override bool Read()
{
switch (++_step)
{
case 1:
Reader.SetToken(JsonToken.PropertyName,String.Format("$ext:{0:x}:{1:x}",_tag,_type));
return true;
case 2:
Reader.SetToken(_valueToken,_dataBytes);
return true;
default:
Reader.PopCtx();
Reader.SetToken(JsonToken.EndObject);
return true;
}
}
}
private void ProcessFixExt1(sbyte type, Action<JsonToken, object> setToken)
{
PushCtx(new UnknownExtensionContainer(this, MessagePackConstants.TagFixExt1,type,ReadByte(),JsonToken.Integer));
setToken(JsonToken.StartObject, null);
}
private void ProcessFixExt2(sbyte type, Action<JsonToken, object> setToken)
{
PushCtx(new UnknownExtensionContainer(this, MessagePackConstants.TagFixExt2, type, ReadUshort(),JsonToken.Integer));
setToken(JsonToken.StartObject, null);
}
private void ProcessFixExt4(sbyte type, Action<JsonToken, object> setToken)
{
PushCtx(new UnknownExtensionContainer(this, MessagePackConstants.TagFixExt4, type, ReadUint(),JsonToken.Integer));
setToken(JsonToken.StartObject, null);
}
private void ProcessFixExt8(sbyte type, Action<JsonToken, object> setToken)
{
unchecked
{
switch (type)
{
case MessagePackConstants.ExtTypeDateTime:
setToken(JsonToken.Date, DateTime.FromBinary((long) ReadUlong()));
return;
case MessagePackConstants.ExtTypeTimeStamp:
setToken(JsonToken.Date, new TimeSpan((long) ReadUlong()));
return;
default:
PushCtx(new UnknownExtensionContainer(this, MessagePackConstants.TagFixExt8, type, (long)ReadUlong(),JsonToken.Integer));
setToken(JsonToken.StartObject,null);
return;
}
}
}
private void ProcessFixExt16(sbyte type, Action<JsonToken, object> setToken)
{
PushCtx(new UnknownExtensionContainer(this, MessagePackConstants.TagFixExt16, type, ReadBytes(16),JsonToken.Bytes));
setToken(JsonToken.StartObject,null);
}
public override int? ReadAsInt32()
{
throw new NotImplementedException();
}
public override string ReadAsString()
{
throw new NotImplementedException();
}
public override byte[] ReadAsBytes()
{
throw new NotImplementedException();
}
public override decimal? ReadAsDecimal()
{
while (Read())
{
var tokenType = TokenType;
switch (tokenType)
{
case JsonToken.Comment:
continue;
case JsonToken.Integer:
case JsonToken.Float:
return !(Value is Decimal)
? Convert.ToDecimal(Value, CultureInfo.InvariantCulture)
: (Decimal) Value;
case JsonToken.Null:
return null;
case JsonToken.String:
var s = (string) Value;
if (string.IsNullOrEmpty(s))
{
return null;
}
Decimal result;
if (!Decimal.TryParse(s, NumberStyles.Number, Culture, out result))
throw new JsonReaderException(String.Format(CultureInfo.InvariantCulture,
"Could not convert string to decimal: {0}.", Value));
return result;
case JsonToken.EndArray:
return null;
default:
throw new JsonReaderException(String.Format(CultureInfo.InvariantCulture,
"Error reading decimal. Unexpected token: {0}.", tokenType));
}
}
return null;
}
private readonly byte[] _buff = new byte[256];
private void ReadToBuffer(int bytes)
{
if (bytes != _inputStream.Read(_buff, 0, bytes))
throw new Exception("TODO:EOF");
}
private byte ReadByte()
{
ReadToBuffer(1);
return _buff[0];
}
private ushort ReadUshort()
{
ReadToBuffer(2);
return (ushort)(_buff[0] << 8 | _buff[1]);
}
private uint ReadUint()
{
ReadToBuffer(4);
return ((uint)_buff[0] << 24 | (uint)_buff[1] << 16 | (uint)_buff[2] << 8 | _buff[3]);
}
private ulong ReadUlong()
{
ReadToBuffer(8);
return (ulong)_buff[0] << 56 | (ulong)_buff[1] << 48 | (ulong)_buff[2] << 40 | (ulong)_buff[3] << 32 | (ulong)_buff[4] << 24 | (ulong)_buff[5] << 16 | (ulong)_buff[6] << 8 | _buff[7];
}
private float ReadFloat32()
{
ReadToBuffer(4);
if (BitConverter.IsLittleEndian) Array.Reverse(_buff, 0, 4);
return BitConverter.ToSingle(_buff, 0);
}
private double ReadFloat64()
{
ReadToBuffer(8);
if (BitConverter.IsLittleEndian) Array.Reverse(_buff, 0, 8);
return BitConverter.ToDouble(_buff, 0);
}
private string GetStr(int len)
{
var buff = len > _buff.Length ? new byte[len] : _buff;
if (len != _inputStream.Read(buff, 0, len))
throw new Exception("TODO:EOF");
return MessagePackWriter.Utf8.GetString(buff, 0, len);
}
public override DateTime? ReadAsDateTime()
{
throw new NotImplementedException();
}
public override DateTimeOffset? ReadAsDateTimeOffset()
{
throw new NotImplementedException();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment