xxl-job的dotnet core 执行器实现
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

963 lines
29 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Hessian.Collections;
using Hessian.Platform;
namespace Hessian
{
public class Deserializer
{
private readonly ValueReader reader;
private readonly IRefMap<ClassDef> classDefs;
private readonly IRefMap<object> objectRefs;
private readonly IRefMap<string> typeNameRefs;
private readonly Lazy<ListTypeResolver> listTypeResolver = new Lazy<ListTypeResolver>();
private readonly Lazy<DictionaryTypeResolver> dictTypeResolver = new Lazy<DictionaryTypeResolver>();
private static readonly EndianBitConverter BitConverter = new BigEndianBitConverter();
public Deserializer (Stream stream)
{
if (stream == null) {
throw new ArgumentNullException(nameof(stream));
}
reader = new ValueReader(stream);
classDefs = new ListRefMap<ClassDef>();
objectRefs = new ListRefMap<object>();
typeNameRefs = new ListRefMap<string>();
}
public bool CanRead()
{
var tag = reader.Peek ();
return tag.HasValue;
}
#region ReadValue
public object ReadValue ()
{
var tag = reader.Peek ();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
Console.WriteLine("------------ 0x{0:x2}----------------",tag.Value);
switch (tag.Value) {
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F:
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
Console.WriteLine("ReadShortString");
return ReadShortString();
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F:
Console.WriteLine("ReadShortBinary");
return ReadShortBinary();
case 0x30: case 0x31: case 0x32: case 0x33:
Console.WriteLine("ReadMediumString");
return ReadMediumString();
case 0x34: case 0x35: case 0x36: case 0x37:
Console.WriteLine("ReadMediumBinary");
return ReadMediumBinary();
case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F:
Console.WriteLine("ReadLongThreeBytes");
return ReadLongThreeBytes();
case 0x40:
Console.WriteLine("Reserved");
return Reserved();
case 0x41: case 0x42:
Console.WriteLine("ReadChunkedBinary");
return ReadChunkedBinary();
case 0x43:
Console.WriteLine("ReadClassDefinition");
return ReadClassDefinition();
case 0x44:
Console.WriteLine("ReadFullDouble");
return ReadFullDouble();
case 0x45:
Console.WriteLine("Reserved");
return Reserved();
case 0x46:
Console.WriteLine("ReadBoolean");
return ReadBoolean();
case 0x47:
Console.WriteLine("Reserved");
return Reserved();
case 0x48:
Console.WriteLine("ReadUntypedMap");
return ReadUntypedMap();
case 0x49:
Console.WriteLine("ReadInteger");
return ReadInteger();
case 0x4A:
Console.WriteLine("ReadDateInMillis");
return ReadDateInMillis();
case 0x4B:
Console.WriteLine("ReadDateInMinutes");
return ReadDateInMinutes();
case 0x4C:
Console.WriteLine("ReadLongFull");
return ReadLongFull();
case 0x4D:
Console.WriteLine("ReadTypedMap");
return ReadTypedMap();
case 0x4E:
Console.WriteLine("ReadNull");
return ReadNull();
case 0x4F:
Console.WriteLine("ReadObject");
return ReadObject();
case 0x50:
Console.WriteLine("Reserved");
return Reserved();
case 0x51:
Console.WriteLine("ReadRef");
return ReadRef();
case 0x52: case 0x53:
Console.WriteLine("ReadChunkedString");
return ReadChunkedString();
case 0x54:
Console.WriteLine("ReadBoolean");
return ReadBoolean();
case 0x55:
Console.WriteLine("ReadVarList");
return ReadVarList();
case 0x56:
Console.WriteLine("ReadFixList");
return ReadFixList();
case 0x57:
Console.WriteLine("ReadVarListUntyped");
return ReadVarListUntyped();
case 0x58:
Console.WriteLine("ReadFixListUntyped");
return ReadFixListUntyped();
case 0x59:
Console.WriteLine("ReadLongFourBytes");
return ReadLongFourBytes();
case 0x5A:
// List terminator - solitary list terminators are most definitely not legit.
throw new UnexpectedTagException(0x5A, "value");
case 0x5B: case 0x5C:
Console.WriteLine("ReadDoubleOneByte");
return ReadDoubleOneByte();
case 0x5D:
Console.WriteLine("ReadDoubleOneByte");
return ReadDoubleOneByte();
case 0x5E:
Console.WriteLine("ReadDoubleTwoBytes");
return ReadDoubleTwoBytes();
case 0x5F:
Console.WriteLine("ReadDoubleFourBytes");
return ReadDoubleFourBytes();
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F:
Console.WriteLine("ReadObjectCompact");
return ReadObjectCompact();
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
Console.WriteLine("ReadCompactFixList");
return ReadCompactFixList();
case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
Console.WriteLine("ReadCompactFixListUntyped");
return ReadCompactFixListUntyped();
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F:
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F:
case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7:
case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF:
case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7:
case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF:
Console.WriteLine("ReadIntegerSingleByte");
return ReadIntegerSingleByte();
case 0xC0: case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
Console.WriteLine("ReadIntegerTwoBytes");
return ReadIntegerTwoBytes();
case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: case 0xD5: case 0xD6: case 0xD7:
Console.WriteLine("ReadIntegerThreeBytes");
return ReadIntegerThreeBytes();
case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF:
case 0xE0: case 0xE1: case 0xE2: case 0xE3: case 0xE4: case 0xE5: case 0xE6: case 0xE7:
case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE: case 0xEF:
Console.WriteLine("ReadLongOneByte");
return ReadLongOneByte();
case 0xF0: case 0xF1: case 0xF2: case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF:
Console.WriteLine("ReadLongTwoBytes");
return ReadLongTwoBytes();
}
throw new Exception("WTF: byte value " + tag.Value + " not accounted for!");
}
#endregion
private string ReadTypeName()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
// A type name is either a string, or an integer reference to a
// string already read and stored in the type-name ref map.
if ((tag >= 0x00 && tag < 0x20)
|| (tag >= 0x30 && tag < 0x34)
|| tag == 0x52
|| tag == 0x53) {
var typeName = ReadString();
typeNameRefs.Add(typeName);
return typeName;
}
return typeNameRefs.Get(ReadInteger());
}
#region List
private IList<object> ReadVarList()
{
reader.ReadByte();
var type = ReadTypeName();
return ReadListCore(type: type);
}
private IList<object> ReadFixList()
{
reader.ReadByte();
var type = ReadTypeName();
var length = ReadInteger();
return ReadListCore(length, type);
}
private IList<object> ReadVarListUntyped()
{
reader.ReadByte();
return ReadListCore();
}
private IList<object> ReadFixListUntyped()
{
reader.ReadByte();
var length = ReadInteger();
return ReadListCore(length);
}
private IList<object> ReadCompactFixList()
{
var tag = reader.ReadByte();
var length = tag - 0x70;
var type = ReadTypeName();
return ReadListCore(length, type);
}
private IList<object> ReadCompactFixListUntyped()
{
var tag = reader.ReadByte();
var length = tag - 0x70;
return ReadListCore(length);
}
private IList<object> ReadListCore(int? length = null, string type = null)
{
var list = GetListInstance(type, length);
objectRefs.Add(list);
if (length.HasValue) {
PopulateFixLengthList(list, length.Value);
} else {
PopulateVarList(list);
}
return list;
}
private IList<object> GetListInstance(string type, int? length = null)
{
IList<object> list;
if (length.HasValue) {
if (!listTypeResolver.Value.TryGetListInstance(type, length.Value, out list)) {
list = new List<object>(length.Value);
}
} else {
if (!listTypeResolver.Value.TryGetListInstance(type, out list)) {
list = new List<object>();
}
}
return list;
}
private void PopulateFixLengthList(IList<object> list, int length)
{
for (var i = 0; i < length; ++i) {
list.Add(ReadValue());
}
}
private void PopulateVarList(IList<object> list)
{
while (true) {
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag == 'Z') {
reader.ReadByte();
break;
}
list.Add(ReadValue());
}
}
#endregion
public object Reserved ()
{
reader.ReadByte();
return ReadValue();
}
#region String
public string ReadString()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag.Value < 0x20) {
return ReadShortString();
}
if (tag.Value >= 0x30 && tag.Value <= 0x33) {
return ReadMediumString();
}
if (tag.Value == 'R' || tag.Value == 'S') {
return ReadChunkedString();
}
throw new UnexpectedTagException(tag.Value, "string");
}
private string ReadShortString ()
{
var length = reader.ReadByte();
return ReadStringWithLength(length);
}
private string ReadMediumString ()
{
var b0 = reader.ReadByte ();
var b1 = reader.ReadByte ();
var length = ((b0 - 0x30) << 8) | b1;
return ReadStringWithLength(length);
}
private string ReadStringWithLength (int length)
{
var sb = new StringBuilder (length);
while (length-- > 0) {
sb.AppendCodepoint(reader.ReadUtf8Codepoint());
}
return sb.ToString();
}
private string ReadChunkedString()
{
var sb = new StringBuilder();
var final = false;
while (!final) {
var tag = reader.ReadByte();
final = tag == 'S';
var length = reader.ReadShort();
while (length-- > 0) {
sb.AppendCodepoint(reader.ReadUtf8Codepoint());
}
}
return sb.ToString();
}
#endregion
#region Binary
public byte[] ReadBinary()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag.Value >= 0x20 && tag.Value <= 0x2F) {
return ReadShortBinary();
}
if (tag.Value >= 0x34 && tag.Value <= 0x37) {
return ReadMediumBinary();
}
if (tag.Value == 0x41 || tag.Value == 0x42) {
return ReadChunkedBinary();
}
throw new UnexpectedTagException(tag.Value, "binary");
}
private byte[] ReadShortBinary ()
{
var length = reader.ReadByte();
var data = new byte[length];
reader.Read(data, length);
return data;
}
private byte[] ReadMediumBinary()
{
var b0 = reader.ReadByte();
var b1 = reader.ReadByte();
var length = ((b0 - 0x34) << 8) | b1;
var data = new byte[length];
reader.Read(data, length);
return data;
}
public byte[] ReadChunkedBinary()
{
var data = new List<byte>();
var final = false;
while (!final) {
var tag = reader.ReadByte();
final = tag == 'B';
var length = reader.ReadShort();
var buff = new byte[length];
reader.Read(buff, length);
data.AddRange(buff);
}
return data.ToArray();
}
#endregion Binary
#region Integer
public int ReadInteger()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
// Full-length integer encoding is 'I' b0 b1 b2 b3 - i.e. a full 32-bit integer in big-endian order.
if (tag == 0x49) {
return ReadIntegerFull();
}
// Ints between -16 and 47 are encoded as value + 0x90.
if (tag >= 0x80 && tag <= 0xBF) {
return ReadIntegerSingleByte();
}
// Ints between -2048 and 2047 can be encoded as two octets with the leading byte from 0xC0 to 0xCF.
if (tag >= 0xC0 && tag <= 0xCF) {
return ReadIntegerTwoBytes();
}
// Ints between -262144 and 262143 can be three bytes with the first from 0xD0 to 0xD7.
if (tag >= 0xD0 && tag <= 0xD7) {
return ReadIntegerThreeBytes();
}
throw new UnexpectedTagException(tag.Value, "integer");
}
private int ReadIntegerFull()
{
reader.ReadByte(); // Discard tag.
byte b0 = reader.ReadByte(),
b1 = reader.ReadByte(),
b2 = reader.ReadByte(),
b3 = reader.ReadByte();
return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
}
private int ReadIntegerSingleByte()
{
return reader.ReadByte() - 0x90;
}
private int ReadIntegerTwoBytes()
{
byte b0 = reader.ReadByte(),
b1 = reader.ReadByte();
return ((b0 - 0xC8) << 8) | b1;
}
private int ReadIntegerThreeBytes()
{
byte b0 = reader.ReadByte(),
b1 = reader.ReadByte(),
b2 = reader.ReadByte();
return ((b0 - 0xD4) << 16) | (b1 << 8) | b2;
}
#endregion Integer
#region Class Definition
public ClassDef ReadClassDefinition()
{
var tag = reader.ReadByte();
if (tag != 'C') {
throw new UnexpectedTagException(tag, "classdef");
}
var name = ReadString();
var fieldCount = ReadInteger();
var fields = new string[fieldCount];
for (var i = 0; i < fields.Length; ++i) {
fields[i] = ReadString();
}
var classDef = new ClassDef(name, fields);
classDefs.Add(classDef);
return classDef;
}
#endregion Class Definition
#region Double
public double ReadDouble()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag == 0x44) {
return ReadFullDouble();
}
if (tag == 0x5B || tag == 0x5C) {
return ReadDoubleOneByte();
}
if (tag == 0x5D) {
return ReadDoubleTwoBytes();
}
if (tag == 0x5E) {
return ReadDoubleThreeBytes();
}
if (tag == 0x5F) {
return ReadDoubleFourBytes();
}
throw new UnexpectedTagException(tag.Value, "double");
}
private double ReadFullDouble()
{
var data = new byte[9]; // 9 bytes: tag + IEEE 8-byte double
reader.Read(data, data.Length);
return BitConverter.ToDouble(data, 1);
}
private double ReadDoubleOneByte()
{
// 0x5B encodes the double value 0.0, and 0x5C encodes 1.0.
return reader.ReadByte() - 0x5B;
}
private double ReadDoubleTwoBytes()
{
// Doubles representing integral values between -128.0 and 127.0 are
// encoded as single bytes. Java bytes are signed, .NET bytes aren't,
// so we have to cast it first.
reader.ReadByte();
return (sbyte) reader.ReadByte();
}
private double ReadDoubleThreeBytes()
{
// Doubles representing integral values between -32768.0 and 32767.0 are
// encoded as two-byte integers.
reader.ReadByte();
return reader.ReadShort();
}
private double ReadDoubleFourBytes()
{
// Doubles that can be represented as singles are thusly encoded.
var data = new byte[5];
reader.Read(data, data.Length);
return BitConverter.ToSingle(data, 0);
}
#endregion Double
public bool ReadBoolean()
{
var tag = reader.ReadByte();
switch (tag) {
case 0x46: return false;
case 0x54: return true;
}
throw new UnexpectedTagException(tag, "boolean");
}
#region Date
public DateTime ReadDate()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag == 0x4A) {
return ReadDateInMillis();
}
if (tag == 0x4B) {
return ReadDateInMinutes();
}
throw new UnexpectedTagException(tag.Value, "date");
}
private DateTime ReadDateInMillis()
{
var data = new byte[9];
reader.Read(data, data.Length);
var millis = LongFromBytes(data, 1);
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(millis);
}
private DateTime ReadDateInMinutes()
{
var data = new byte[5];
reader.Read(data, data.Length);
var minutes = IntFromBytes(data, 1);
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMinutes(minutes);
}
#endregion Date
#region Long
public long ReadLong()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag == 0x4C) {
return ReadLongFull();
}
if (tag >= 0xD8 && tag <= 0xEF) {
return ReadLongOneByte();
}
if (tag >= 0xF0 && tag <= 0xFF) {
return ReadLongTwoBytes();
}
if (tag >= 0x38 && tag <= 0x3F) {
return ReadLongThreeBytes();
}
if (tag == 0x59) {
return ReadLongFourBytes();
}
throw new UnexpectedTagException(tag.Value, "long");
}
private long ReadLongFull()
{
var data = new byte[9];
reader.Read(data, data.Length);
return LongFromBytes(data, 1);
}
private long ReadLongOneByte()
{
return reader.ReadByte() - 0xE0;
}
private long ReadLongTwoBytes()
{
byte b0 = reader.ReadByte(),
b1 = reader.ReadByte();
return ((b0 - 0xF8) << 8) | b1;
}
private long ReadLongThreeBytes()
{
byte b0 = reader.ReadByte(),
b1 = reader.ReadByte(),
b2 = reader.ReadByte();
return ((b0 - 0x3C) << 16) | (b1 << 8) | b2;
}
private long ReadLongFourBytes()
{
var data = new byte[5];
reader.Read(data, data.Length);
return IntFromBytes(data, 1);
}
#endregion Long
#region Dictionary/Map
public IDictionary<object, object> ReadMap()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag == 'H') {
return ReadUntypedMap();
}
if (tag == 'M') {
return ReadTypedMap();
}
throw new UnexpectedTagException(tag.Value, "map");
}
private IDictionary<object, object> ReadUntypedMap()
{
reader.ReadByte();
return ReadMapCore();
}
private IDictionary<object, object> ReadTypedMap()
{
reader.ReadByte();
var typeName = ReadTypeName();
return ReadMapCore(typeName);
}
private IDictionary<object, object> ReadMapCore(string type = null)
{
IDictionary<object, object> dictionary;
if (type == null || !dictTypeResolver.Value.TryGetInstance("", out dictionary)) {
dictionary = new Dictionary<object, object>();
}
objectRefs.Add(dictionary);
while (true) {
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag == 'Z') {
break;
}
var key = ReadValue();
var value = ReadValue();
dictionary.Add(key, value);
}
return dictionary;
}
#endregion
#region Object
public object ReadObject()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag == 'O') {
return ReadObjectFull();
}
if (tag >= 0x60 && tag < 0x70) {
return ReadObjectCompact();
}
throw new UnexpectedTagException(tag.Value, "object");
}
private object ReadObjectFull()
{
reader.ReadByte();
var classDefId = ReadInteger();
var classDef = classDefs.Get(classDefId);
return ReadObjectCore(classDef);
}
private object ReadObjectCompact()
{
var classDefId = reader.ReadByte() - 0x60;
var classDef = classDefs.Get(classDefId);
return ReadObjectCore(classDef);
}
private object ReadObjectCore(ClassDef classDef)
{
// XXX: This needs a better implementation - maybe, you know, constructing
// the requested type?
var builder = HessianObject.Builder.New(classDef.Name);
objectRefs.Add(builder.Object);
foreach (var field in classDef.Fields) {
builder.Add(field, ReadValue());
}
return builder.Create();
}
#endregion
public object ReadNull()
{
reader.ReadByte();
return null;
}
public object ReadRef()
{
var tag = reader.Peek();
if (!tag.HasValue) {
throw new EndOfStreamException();
}
if (tag != 0x51) {
throw new UnexpectedTagException(tag.Value, "ref");
}
reader.ReadByte();//过滤tag
return objectRefs.Get(ReadInteger());
}
private static int IntFromBytes(byte[] buffer, int offset)
{
return (buffer[offset + 0] << 0x18)
| (buffer[offset + 1] << 0x10)
| (buffer[offset + 2] << 0x08)
| (buffer[offset + 3] << 0x00);
}
private static long LongFromBytes(byte[] buffer, int offset)
{
/*
var value = (long) reader.ReadByte() << 56;
value |= ((long) reader.ReadByte() << 48);
value |= ((long) reader.ReadByte() << 40);
value |= ((long) reader.ReadByte() << 32);
value |= ((long) reader.ReadByte() << 24);
value |= ((long) reader.ReadByte() << 16);
value |= ((long) reader.ReadByte() << 8);
value |= (uint)reader.ReadByte();
return value;
*/
return ((long)buffer[offset + 0] << 0x38)
+ ((long)buffer[offset + 1] << 0x30)
| ((long)buffer[offset + 2] << 0x28)
| ((long)buffer[offset + 3] << 0x20)
| ((long)buffer[offset + 4] << 0x18)
| ((long)buffer[offset + 5] << 0x10)
| ((long)buffer[offset + 6] << 0x08)
| ((uint)buffer[offset + 7] << 0x00);
}
}
}